1. BeanFactory
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提供的方法及其简单,仅提供了六种方法供客户调用:
- boolean containsBean(String beanName) 判断工厂中是否包含给定名称的bean定义,若有则返回true
- Object getBean(String) 返回给定名称注册的bean实例。根据bean的配置情况,如果是singleton模式将返回一个共享实例,否则将返回一个新建的实例,如果没有找到指定bean,该方法可能会抛出异常
- Object getBean(String, Class) 返回以给定名称注册的bean实例,并转换为给定class类型
- Class getType(String name) 返回给定名称的bean的Class,如果没有找到指定的bean实例,则排除NoSuchBeanDefinitionException异常
- boolean isSingleton(String) 判断给定名称的bean定义是否为单例模式
- String[] getAliases(String name) 返回给定bean名称的所有别名
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<T>接口的Bean,根据该Bean的ID从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身,如果要获取FactoryBean对象,请在id前面加一个&符号来获取。
通常来讲,根据XML的节点中配置的class路径,Spring可以通过反射机制来实例化。
如:
但实际工作中,实例化一个对象并不如此简单。比如要在实例化的时候做一些复杂的处理。这就用上FactoryBean了。
比如最常用的Quartz框架,我们在配置调度任务的时候,配置的都是FactoryBean。
FactoryBean隐藏了许多实例化的复杂细节,方便上层调用。
如果在中配置的是FactoryBean,那么getBean()返回的其实是FactoryBean#getObject()返回的对象。
如:
getBean("beanA")返回的其实是BeanAFactoryBean#getObject()返回的对象,至于是什么,就由BeanAFactoryBean来决定了。
要想返回BeanFactory的实例,应该getBean("&beanA")。
- <span style="white-space:pre"> </span>public interface FactoryBean<T> {
- //返回由FactoryBean创建的bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中单实例缓存池中。
- T getObject() throws Exception;
- //返回FactoryBean创建的bean类型。
- Class<?> getObjectType();
- //返回由FactoryBean创建的bean实例的作用域是singleton还是prototype。
- boolean isSingleton();
- }
- public class Person {
- private String name;
- private String address;
- private int age;
- }
- <bean id="personBean" class="com.gh.MavenTest.Person">
- <property name="name" value="gh1" />
- <property name="address" value="address1" />
- <property name="age" value="28" />
- </bean>
- public class PersonFactoryBean implements FactoryBean<Person>{
- private String personInfo;
- public Person getObject() throws Exception {
- Person person = new Person () ;
- String [] infos = personInfo.split ( "," ) ;
- person.setName(infos[0]);
- person.setAddress(infos[1]);
- person.setAge(Integer.parseInt(infos[2]));
- return person;
- }
- public Class<Person> getObjectType() {
- return Person.class;
- }
- public boolean isSingleton() {
- return true;
- }
- }
- <bean id="personFactory" class="com.hik.MavenTest.PersonFactory">
- <property name="personInfo" value="gh2,address2,22"></property>
- </bean>
应用案例
很多开源项目在集成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>
<dubbo:reference
对应的Bean是com.alibaba.dubbo.config.spring.ReferenceBean
类,如下:
public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean {
}
作者:FX_SKY
链接:https://www.jianshu.com/p/6f0a59623090
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- FactoryBean:是一个Java Bean,但是它是一个能生产对象的工厂Bean,它的实现和工厂模式及修饰器模式很像。比如下:我们把bean比作是人,那么FactoryBean可以算是一个女人,首先它本身也是一个人,但它能够生产人。【挺尴尬的比喻】。
- BeanFactory:这就是一个Factory,是一个IOC容器或者叫对象工厂,它里面存着很多的bean。还用上面那个比如:如果bean是人,那么它可以理解成学校,学校里面很多人,学校管理这么多的人。