spring FactoryBean接口

Posted liguangming

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring FactoryBean接口相关的知识,希望对你有一定的参考价值。

这个接口有以下几个方法

获取真实的对象

T getObject() throws Exception;

获取真实的对象的class对象

Class<?> getObjectType();

是不是单例

boolean isSingleton();

在使用过程中我们可以通过实现这个接口的几个方法,来创建一个类型为其它类型的bean

主要是通过getObjectType()方法来实现。

而且通常配合着动态代理来使用,这样就能够通过注入target的方式,将target对象代理上,并且创建出相应的对象。

看下面一个例子:

先创建一个实现了FactoryBean接口的MyFactoryBean

package demo;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;

public class MyFactoryBean implements FactoryBean<Object>, InitializingBean, DisposableBean {
    private static final Logger logger = LoggerFactory.getLogger(MyFactoryBean.class);
    private String interfaceName = "demo.DemoService";
    private Object target;
    public String getInterfaceName() {
        return interfaceName;
    }

    public void setInterfaceName(String interfaceName) {
        this.interfaceName = interfaceName;
    }

    public Object getTarget() {
        return target;
    }

    public void setTarget(Object target) {
        this.target = target;
    }

    public Object getProxyObj() {
        return proxyObj;
    }

    public void setProxyObj(Object proxyObj) {
        this.proxyObj = proxyObj;
    }

    private Object proxyObj;

    public Object getObject() throws Exception {
         return proxyObj;
    }

    public Class<?> getObjectType() {
        return proxyObj.getClass();
    }

    public boolean isSingleton() {
        return true;
    }

    public void afterPropertiesSet() throws Exception {
        proxyObj = Proxy.newProxyInstance(this.getClass().getClassLoader(),
                new Class[] { Class.forName(interfaceName) }, new InvocationHandler() {
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        logger.info("invoke method......" + method.getName());
                        logger.info("invoke method before......" + System.currentTimeMillis());
                        Object result = method.invoke(target, args);
                        logger.info("invoke method after......" + System.currentTimeMillis());
                        return result;
                    }
                });

    }

    public void destroy() throws Exception {
        logger.info("destroy......");

    }
}

这里面除了实现了FactoryBean接口以外,还实现了InitializingBean接口,也就是说spring启动的时候会调用

afterPropertiesSet方法

这样就将target与代理对象绑定到了一起,因为当方法调用的时候会先执行一些代理自己的内容,在方法invoke之前和之后,invoke执行的是target对象的具体方法

看一下具体调用

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                new String[] { "spring/consumer.xml" });
        context.start();
        System.out.println("consumer start !");
//        Person person = context.getBean("person",Person.class);
        
//        DemoService demoService = context.getBean(DemoService.class);
        DemoService bean = (DemoService)context.getBean("myFactoryBean");
        bean.sayHello("sina");

再看一下配置文件

<bean id="myRealBean" class="demo.DemoServiceImpl"></bean>
    <bean id="myFactoryBean" class="demo.MyFactoryBean" >
        <property name="target" ref="myRealBean" />
    </bean>

可以看到target是注入到MyfactoryBean里面的

再看一下Mbatis的一个具体的例子

public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {

public void afterPropertiesSet() throws Exception {
    notNull(dataSource, "Property ‘dataSource‘ is required");
    notNull(sqlSessionFactoryBuilder, "Property ‘sqlSessionFactoryBuilder‘ is required");
    state((configuration == null && configLocation == null) || !(configuration != null && configLocation != null),
              "Property ‘configuration‘ and ‘configLocation‘ can not specified with together");

    this.sqlSessionFactory = buildSqlSessionFactory();
  }
public SqlSessionFactory getObject() throws Exception {
    if (this.sqlSessionFactory == null) {
      afterPropertiesSet();
    }
}

可以看到mybatis在启动的时候会调用

 buildSqlSessionFactory()

来创建sqlSessionFactory

在getObject的时候在将创建了的sqlSessionFactory返回。这样就可以直接把SqlSessionFactoryBean定义为一个spring的一个bean供使用了

 

以上是关于spring FactoryBean接口的主要内容,如果未能解决你的问题,请参考以下文章

Spring - FactoryBean扩展接口

spring中的工厂FactoryBean

spring FactoryBean接口

Spring拓展接口之FactoryBean

Spring拓展接口之FactoryBean

Spring拓展接口之FactoryBean