【提问】

Spring中所说的FactoryBean和普通Bean的区别有什么区别?

【解答】

具体区别:

维度不同

Bean只是一个概念,统称所有被SpringIOC工厂(容器)管理的对象,硬要说也要有一个规范,那就是Object。

FactoryBean是一个实际的接口,在spring-beans包中:org.springframework.beans.factory.FactoryBean
FactoryBean通过编码方式负责Bean的生成,由于同样会被SpringIOC工厂(容器)所管理,所以可以看成一个具有特殊功能的Bean。

使用方式不同

Bean,任意类都可以委托给SpringIOC管理,不需要实现任何接口或继承任何类,只需要通过注解、配置等方式告知Spring即可,如下:
在这里插入图片描述

FactoryBean,需要实现FactoryBean接口,然后和Bean一样,告知Spring,如下:在这里插入图片描述

获取方式不同

Bean,可以通过AbstractBeanFactory.getBean方法或注解(@Autowired等)的方式获取,获取到的即是Bean对象。

FactoryBean,和Bean一样,可以通过AbstractBeanFactory.getBean方法或注解(@Autowired等)的方式获取,但通过这种方式获得是其getObject方法中返回的Bean对象,而不是FactoryBean本身。
如果想获取FactoryBean对象本身,则需要在调用getBean时,入参前增加“&”:applicationContext.getBean("&testFactoryBean")

存放的位置和时机不同

Bean
Spring所管理的所有单例Bean,都是在初始化AnnotationConfigApplicationContext时,存放在applicationContext.beanFactory.singletonObjects这个变量中的。

可以追溯一下源码,初始化AnnotationConfigApplicationContext时,运行流程如下:

AnnotationConfigApplicationContext() -> 
AbstractApplicationContext.refresh() ->
AbstractApplicationContext.finishBeanFactoryInitialization()-> 
AbstractBeanFactory.preInstantiateSingletons() -> 
AbstractBeanFactory.getBean() -> 
AbstractBeanFactory.doGetBean() -> 
DefaultSingletonBeanRegistry.getSingleton() -> 
DefaultSingletonBeanRegistry.addSingleton()

可以看到,在addSingleton方法中,将初始化好的bean实例放入applicationContext.beanFactory.singletonObjects变量中。

FactoryBean
Spring所管理的所有单例FactoryBean,都是在获取Bean时,存放在applicationContext.beanFactory.factoryBeanObjectCache这个变量中的。

可以追溯一下源码,初始化AnnotationConfigApplicationContext时,并没有将对应的factoryBean放入factoryBeanObjectCache,而是在getBean时存入,运行流程如下:

AbstractApplicationContext.getBean() ->
AbstractBeanFactory.getBean() -> 
AbstractBeanFactory.doGetBean() -> 
AbstractBeanFactory.getObjectForBeanInstance() ->
FactoryBeanRegistrySupport.getObjectFromFactoryBean()

可以看到,在getObjectFromFactoryBean方法中,将初始化好的factoryBean实例放入applicationContext.beanFactory.factoryBeanObjectCache变量中。

用途不同

Bean,简单理解就是被SpringIOC工厂(容器)所管理的对象,绝大多数情况下,使用普通的Bean即可。

FactoryBean顾名思义,是为了生成Bean而存在的,大部分设计都没必要使用FactoryBean,一般来说会考虑使用FactoryBean的情况:

1、当一些Bean的实例化过程复杂、需要执行大量初始化逻辑的。
例如:Spring体系官方的大量类FeignClientFactoryBean、SchedulerFactoryBean等;

2、无法直接构造得到的对象。
例如:需要引入一些通过getInstance封装了构造过程的。

通过实现接口getObject()方法,返回实际上想要得到的Bean,这个方法的实现可以按照不同场景来编写。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐