一、背景
BeanFactory与FactoryBean名字相似,但是意义确大不相同,可以说基本没有关系。BeanFactory是一个工厂,负责创建bean、获取到bean,而FactoryBean只是一个bean。
二、两者不同
本文主要通过FactoryBean的作用大家可以明白为什么不同。
FactoryBean相信大家都明白一个类(比如BeanA)如果实现了它,那么从容器中getBean(“beanA”)时拿到的是另一个bean,如果想拿到BeanA本身,那么需要getBean(“&beanA”)来操作,如代码所示:
BeanA:
public class IndexFactoryBean implements FactoryBean<IndexFactory> {
private String name;
private Integer age;
public IndexFactoryBean(String name, Integer age) {
this.name = name;
this.age = age;
}
public IndexFactory getObject() throws Exception {
IndexFactory indexFactory = new IndexFactory();
indexFactory.setName(name);
indexFactory.setAge(age);
return indexFactory;
}
public Class<?> getObjectType() {
return null;
}
}
希望获取的bean:
public class IndexFactory {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
配置类:
@Configuration
public class Config {
@Bean
public IndexFactoryBean indexFactoryBean(){
return new IndexFactoryBean("test",1);
}
}
测试类:
public class ApplicationMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationContext = new AnnotationConfigApplicationContext(Config.class);
System.out.println(annotationContext.getBean("&indexFactoryBean"));
System.out.println(annotationContext.getBean("indexFactoryBean"));
IndexFactory indexFactory = (IndexFactory) annotationContext.getBean("indexFactoryBean");
System.out.println(indexFactory.getName());
System.out.println(indexFactory.getAge());
}
}
结果输出:
com.wolf.test.facade.bean.IndexFactoryBean@1ebea008
com.wolf.test.facade.bean.IndexFactory@72d6b3ba
test
1
这个效果大家肯定都知道,但是为什么要有这个FactoryBean,我们知道既然要生成IndexFactory这个实例,我们直接用它不就行了吗?直接把属性放置进去不就行了吗?
设计者这么做肯定有道理。比如我们这个IndexFactory类属性很多很多,而且IndexFactory要提供给外部使用,难道也要别人每次都要set那么多属性吗?本质上可以,但是一般不要这么做,不是很和谐,那么我们就利用IndexFactoryBean暴露给外部使用,这样,外部可能只需要set某些关键属性就可以了。
例子:我们来看常用的SqlSessionFactoryBean,我们可以看到它也实现了FactoryBean,那这个是为了什么呢?
源码:
public SqlSessionFactory getObject() throws Exception {
if (this.sqlSessionFactory == null) {
afterPropertiesSet();
}
return this.sqlSessionFactory;
}
我们可以看到里面返回的sqlSeesionFactory,那么继续跟进
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();
}
看到buildSqlSessionFactory可以明白,SqlSessionFactory内部需要很多属性(如果通过xml方式配置bean那么就不会走到这一步),为了方便外部使用,SqlSessionFactoryBean都帮忙处理好了,而我们外部使用的时候只需要setDatasource就可以了,仅仅需要set一个属性,很大程度地方便外部使用。
看到这里,相信大家明白了吧。
结束语:
本文主要描述FactoryBean的作用,相信明白了作用就可以明白与BeanFactory的区别了。
谢谢大家阅读,请大家多多指教文章中的不足,互相学习!!