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供使用了
posted on 2018-11-17 13:19 liguangming 阅读(180) 评论(0) 编辑 收藏 举报