彻底搞懂Spring中BeanFactory和FactoryBean的区别

我认为Spring中BeanFactory和FactoryBean这两个接口是Spring源码中最让人迷惑的两个接口,各自的javadoc文档实际上写的还是很清楚的,只不过要看懂javadoc 前提是你得先真正理解这两个类的用途,是不是像代码里面的死锁,有点黑色幽默了。其实我当初研究这一块的时候,真真切切经历这个过程,刚开始看javadoc 一头雾水,当彻底弄懂这两个类后,再回头来看,就发现原来javadoc写的是明明白白的。
 
其实这两个接口的分工是很明确的:
 
BeanFactory 是Spring容器的核心接口,ApplicationContext继承了BeanFactory,BeanFactory是Spring容器的门面。
 
0
 
从上图继承关系可以看出,BeanFactory与我们普通程序员关系不大,他属于spring容器的核心组件。
 
FactoryBean 是spring 提供Bean工厂接口,我们自己可以实现这个接口生产我们自己需要的Bean。
0
 
总结: FactoryBean 子类更多的是偏应用层用于创建具体的bean,BeanFactory 是偏容器的基础设施,是一个门面。
 
这样说可能还是很难懂,来个形象的比喻,假设spring容器是食堂,BeanFactory 就是食堂打菜的窗口, FactoryBean 才是真正烧菜的地方。BeanFactory 是容器核心类,一般不需要自己实现子类,FactoryBean 是工厂类,一般写个插件啥的会用到,比如mysql-sprijng插件。假如食堂原来只能做西餐,我现在需要做中餐,那么BeanFactory不需要动,我只需要写个FactoryBean 子类就行了。
 
 
BeanFactory和FactoryBean的关系:
 
Spring对所有FactoryBean子类提供超常规服务的,通过spring门面BeanFactory子类getBean时候,如果发现getBean对应的class是FactoryBean的子类,那么BeanFactory在getBean时候代码做了特殊处理,具体特殊处理代码在方法AbstractBeanFactory.getObjectForBeanInstance()中,如下图
0
上图中beanInstance 是spring容器中存贮的原始对象,序号1处如果这个bean不是FactoryBean,那么直接返回原始对象;序号2处,如果是FactoryBean子类则返回的对象是FactoryBean.getObject() 创造的对象。
 
举例说明:
我创建了一个TestFactoryBean 实现了 FactoryBean 接口,注册到spring容器的名字是test
那么在代码中 getBean(“test”),返回的是 Test 对象,而不是 TestFactoryBean对象,如果我需要TestFactoryBean那么就需要用到特殊符号&,getBean(“&test”)
0
 
0
 
 
&符号究竟是如何工作的呢,则还是要回到 AbstractBeanFactory.getObjectForBeanInstance() 方法
进入方法后,首先会判断原始name是不是&开头,如果是&开头且是 FactoryBean的子类,则直接返回 FactoryBean 实例。如果是非&开头,则需要判断是不是FactoryBean 实例,如果是则返回 factory.getObject() 创造的对象。
 
0
 
 
现在回过头来看看javadoc ,是不是已经已经讲的很清楚了。
0
 
0
 
 
实验源码地址: https://gitee.com/zfj321/spring-sourcecode-study
posted @ 2020-10-02 12:49  jean zhang  阅读(695)  评论(0编辑  收藏  举报