FactoryBean 就是 生产 Bean 的 Bean 它的目的就是创建一个对象
FactoryBean 就是一个工厂Bean,相当于将工厂类放到了Spring中管理、当获取此Bean的时候返回的是此工厂生成的Bean
2022-05-12补充
今天的我对这个问题有了新的感悟,很多时候,我们只要细细的品这个名字就能想到一二。
FactoryBean、FactoryBean 工厂Bean?
他就是一个工厂类!这个工厂负责创建对象,这个创建出来的对象直接放在了Spring容器中管理。
既然创建出来的对象要放在Spring容器中,所以这个工厂也得在Spring容器中(方便直接使用Spring的特性:生命周期回调、使用容器中的其他对象),所以他叫做FactocyBean,你细细品这个名字!
再看使用方式,直接注入目标对象就行了!多么简便!
先来个总结
单独的使用对象实现FactoryBean接口往往收益不大, 常用的都是同时继承其他类,实现其他接口来协作使用
1. 创建对象时需要依赖于 别的接口 监听数据,推送数据过来的接口 做一些数据处理时, 可以使用FactoryBean.
2. 需要搭配其他接口协作, 依赖于Spring的某个生命周期内, 某个时间节点 来生成对象
详情往下看
目录
1. 示例1 一个简单的例子: 创建一个FacoryBean
4. 源码实现
1. 示例1 一个简单的例子: 创建一个FacoryBean
创建一个FactoryBean首先就是实现 FactoryBean接口
接口泛型为创建的Bean
然后实现以下方法
FactoryBean 就是 让我们自己 来创建一个对象
但是就像上面的例子中那样, 如果你那样使用,FactoryBean是没有多大的好处
2. 什么时候使用?
问题就在这里, 如果这里的创建步骤特别复杂,或需要计算后 才能得到一个对象。就可以使用
示例2 根据指定数据创建对象
当创建对象的过程复杂时可使用BeanFactory,调用方只需要注入就可使用
问题: 既然是根据一些数据创建对象,为什么非要写到FactoryBean中,而不是直接写一个方法 Car getObject(Data)
如果这么使用 貌似非要用FactoryBean的理由也没有了
我理解的FactoryBean使创建对象操作 更加语义化
3. 使用FactoryBean与 自己创建对象对比
既然factoryBean目的就是创建对象, 那如果我们自己写一个方法也可以完成同样的操作, 那为什么要使用factoryBean呢?
对于这个问题, 我列出使用两种方式的写法
1. 使用方法创建对象
2. 使用FactoryBean创建对象
上面已经举例过了,大概就是这个样子
但是调用端发生了不同之处: 可以直接注入使用!
对比之间的区别, FactoryBean总结如下:
1. 对于调用方只需要知道需要对象即可, 不需要管生产方式, 符合迪米特法则: 知道的越少越好, 减少耦合
2. 通过FactoryBean创建的对象与其他正常对象 使用起来毫无差异, 不需要区别对待
3. 将创建对象的复杂操作, 全部封装到了FactoryBean接口的实现类中, 这个类更具语义化, 让大家一看就知道它要做什么事情, 并与Spring的编码风格进行统一
本以为找到了使用BeanFactory的合理理由, 但是突然想到
这种方式貌似也能实现FactoryBean的功能, 还比FactoryBean更加简洁!
为此, 我又去看了源码, 找到FactoryBean的实现类, 看看别人都是怎么用这个接口的
1. EhCache
可以看到这里只是简单返回了对象
别急, 来看看他创建对象的复杂位置
抽象的总结一下: 需要搭配其他接口协作, 依赖于Spring的某个生命周期内, 某个时间节点 来生成对象, 因为将创建对象的逻辑写到了Spring的某个方法回调中
2. PropertyPathFactoryBean
创建对象的过程也是用到了多个Spring接口相互协作
抽象总结: 创建对象时需要依赖于 别的接口 监听数据,推送数据过来的接口 做一些数据处理时, 可以使用FactoryBean.
以下不举例了.
总结:
单独的使用对象实现FactoryBean接口往往收益不大, 常用的都是同时继承其他类,实现其他接口来协作使用
1. 创建对象时需要依赖于 别的接口 监听数据,推送数据过来的接口 做一些数据处理时, 可以使用FactoryBean.
2. 需要搭配其他接口协作, 依赖于Spring的某个生命周期内, 某个时间节点 来生成对象
4. 源码
factoryBean会在容器初始化的时候 和其他普通bean一样 被创建
根据beanName获取其内部的bean
org.springframework.beans.factory.support.FactoryBeanRegistrySupport#doGetObjectFromFactoryBean
源码部分说的有些简陋了。