问题描述
代码详见: extention-FactoryBean ; clone 之后可以直接运行 DemoApplication 即可,可以观察到 控制台不输出 GlmapperBeanPostProcessor 里面 print out 的字符串。
运行代码,即可观察到具体的执行现场;代码里除了 BeanPostProcessor 之外,另外一个是 FactoryBean,也就是本篇所要聊的重点: FactoryBean getObjectType 为 null 时导致 bean 提前初始化,从而使得作用与目标 bean 的 BeanPostProcessors 都失效了。
下面将基于这个问题,展开进行分析。
bean 生命周期
先来看下 ApplicationContext 和 bean 生命周期(仅列出部分关键流程):
从流程中可以看到:BeanPostProcessor 的注册是在 ApplicationContext 生命周期中完成的,故而当 bean 创建时,如果相应拦截器 BeanPostProcessor 还没有注册,那么其就不会起作用,这个可能有以下两种原因:
- 1、bean 本身是一个 BeanPostProcessor ,且实现了 PriorityOrdered 或者 Ordered 接口
- 2、bean 由于某种原因,被提前初始化了,初始化的时候相应拦截器 BeanPostProcessor 还没有注册
关于第一个其实很好理解,不再赘述,本篇主要基于第二个原因进行说明。
bean 由于某种原因,被提前初始化了,初始化的时候相应拦截器 BeanPostProcessor 还没有注册
bean 被提前初始化的情况就比较多了,归纳下来都能符合同一个规律:在 创建所有 non-lazy-init bean 这一步之前,也即在创建 BeanFactoryPostProcessor 或者 BeanPostProcessor 的过程中,引发了 bean 的创建,导致其被提前初始化,大体可以分为两种情形:
- 用户自定义的 BeanFactoryPostProcessor 或者 BeanPostProcessor 中会通过构造函数、属性注入等方式引用到目标 bean 导致其被提前创建
- 在上述过程中由于 Spring 自身对 FactoryBean 的 typeCheck(类型检测) 机制导致目标 bean 被提前创建
对于第一种情形,比较简单,这个通常是用户的配置导致的,比如我的 TestBeanFactoryPostProcessor 中通过属性注入了目标 bean 导致了其被提前创建,最终拦截器失效(如果去掉相应 TestBeanFactoryPostProcessor 配置,可以看到拦截器是能够成功的 )。
简单代码如下,作用在 TestFacade 上的 BeanFactoryPostProcessor 可能会由于 TestFacade 的提前被创建而失效
public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @@Autowired private TestFacade testFacade; @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { // ... } 复制代码
如何找到 bean 被提前初始化的时机呢?可以在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[]) 打一个条件断点,通过 beanName 进行匹配,然后顺着 debug 堆栈往回找,就能够看到是在哪里导致了 bean 被提前创建。
对于第二种情形,其实也是通过上述方法先找到被提前创建的源头,只不过这种情形更加隐晦,也更加复杂,这里我们单独在下面的部分中来分析。