SpringFactoryBean和普通Bean的区别
Posted 猿人林克
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringFactoryBean和普通Bean的区别相关的知识,希望对你有一定的参考价值。
【提问】
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,这个方法的实现可以按照不同场景来编写。
以上是关于SpringFactoryBean和普通Bean的区别的主要内容,如果未能解决你的问题,请参考以下文章
SpringMVC 错误:Bean 名称“用户”的 BindingResult 和普通目标对象都不能用作请求属性
Thymeleaf + Spring:Bean 名称“用户”的 BindingResult 和普通目标对象都不能用作请求属性