BeanFactory,以Factory结尾,表示它是一个工厂类(接口),用于管理Bean的一个工厂。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
Spring为我们提供了许多易用的BeanFactory实现,XmlBeanFactory就是常用的一个,该实现将以XML方式描述组成应用的对象及对象间的依赖关系。XmlBeanFactory类将持有此XML配置元数据,并用它来构建一个完全可配置的系统或应用。
实例化容器
1 Resource resource = new FileSystemResource("beans.xml"); 2 BeanFactory factory = new XmlBeanFactory(resource);
1 ClassPathResource resource = new ClassPathResource("beans.xml"); 2 BeanFactory factory = new XmlBeanFactory(resource);
1 ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml", "applicationContext-part2.xml"}); 3 BeanFactory factory = (BeanFactory) context;
基本就是这些了,接着使用getBean(String beanName)方法就可以取得bean的实例;BeanFactory提供的方法及其简单,仅提供了六种方法供客户调用:
BeanFactory实例化Bean的过程:
1、 调用bean的默认构造方法(或指定的构造方法),生成bean1。
2、 将配置文件中配置的属性值注入bean1,生成bean2。
3、 如bean实现了InitalizingBean接口,则执行afterPropertiesSet()方法,生成bean3。
4、 如配置文件配置了init-method属性,则执行指定的方法,生成bean4。
构造函数-->set-->InitalizingBean#afterPropertiesSet()-->init-method
2, FactoryBean
以Bean结尾,表示它是一个Bean,不同于普通Bean的是:它是实现了FactoryBean
通常来讲,根据XML的节点中配置的class路径,Spring可以通过反射机制来实例化。
如:
但实际工作中,实例化一个对象并不如此简单。比如要在实例化的时候做一些复杂的处理。这就用上FactoryBean了。
比如最常用的Quartz框架,我们在配置调度任务的时候,配置的都是FactoryBean。
FactoryBean隐藏了许多实例化的复杂细节,方便上层调用。
如果在中配置的是FactoryBean,那么getBean()返回的其实是FactoryBean#getObject()返回的对象。
如:
getBean("beanA")返回的其实是BeanAFactoryBean#getObject()返回的对象,至于是什么,就由BeanAFactoryBean来决定了。
要想返回BeanFactory的实例,应该getBean("&beanA")。
很多开源项目在集成Spring 时都使用到FactoryBean,比如 MyBatis3 提供 mybatis-spring项目中的 org.mybatis.spring.SqlSessionFactoryBean
:
<bean id="tradeSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="trade" />
<property name="mapperLocations" value="classpath*:mapper/trade/*Mapper.xml" />
<property name="configLocation" value="classpath:mybatis-config.xml" />
<property name="typeAliasesPackage" value="com.bytebeats.mybatis3.domain.trade" />
bean>
org.mybatis.spring.SqlSessionFactoryBean
如下:
package org.mybatis.spring;
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
private static final Log LOGGER = LogFactory.getLog(SqlSessionFactoryBean.class);
......
}
另外,阿里开源的分布式服务框架 Dubbo 中的Consumer 也使用到了FactoryBean:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
">
<dubbo:application name="demo-consumer" />
<dubbo:protocol name="dubbo" port="20813" />
<dubbo:reference id="demoService" interface="com.alibaba.dubbo.config.spring.api.DemoService" />
beans>
com.alibaba.dubbo.config.spring.ReferenceBean
类,如下:
public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean {
}