一、概述
- 本方法会实例化和调用所有
BeanFactoryPostProcessor(包括其子类BeanDefinitionRegistryPostProcessor)。 BeanFactoryPostProcessor接口是 Spring 初始化BeanFactory时对外暴露的扩展点,Spring IoC容器允许BeanFactoryPostProcessor在容器实例化任何 bean 之前读取 bean 的定义,并可以修改它。BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor,比BeanFactoryPostProcessor具有更高的优先级,主要用来在常规的 BeanFactoryPostProcessor 检测开始之前注册其他 bean 定义。(关于BeanDefinitionRegistryPostProcessor更加详细一些的介绍可以查看这边博客中的内容:https://www.cnblogs.com/tdyang/p/12088554.html)- 特别是,你可以通过 BeanDefinitionRegistryPostProcessor 来注册一些常规的 BeanFactoryPostProcessor,因为此时所有常规的 BeanFactoryPostProcessor 都还没开始被处理。
注:这边的 “常规 BeanFactoryPostProcessor” 主要用来跟 BeanDefinitionRegistryPostProcessor 区分。
首先我们回到AbstractApplicationContext.refresh()方法,找到代码:invokeBeanFactoryPostProcessors(beanFactory),单击该行代码跳转到具体的实现。
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {// 1.getBeanFactoryPostProcessors(): 拿到当前应用上下文beanFactoryPostProcessors变量中的值// 2.invokeBeanFactoryPostProcessors: 实例化并调用所有已注册的BeanFactoryPostProcessorPostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}}
1.拿到当前应用上下文 beanFactoryPostProcessors 变量中的值,见代码块1详解。
2.实例化并调用所有已注册的 BeanFactoryPostProcessor,见代码块2详解。
二、getBeanFactoryPostProcessors
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {return this.beanFactoryPostProcessors;}
这边 getBeanFactoryPostProcessors()会拿到当前应用上下文中已经注册的BeanFactoryPostProcessor,在默认情况下,this.beanFactoryPostProcessors 是返回空的。
如何添加自定义 BeanFactoryPostProcessor 到 this.beanFactoryPostProcessors 变量中了?
该成员变量的值是哪里设置的呢?查找后发现,来自AbstractApplicationContext.addBeanFactoryPostProcessor()方法被调用的时候设置的。
@Overridepublic void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");this.beanFactoryPostProcessors.add(postProcessor);}
AbstractApplicationContext.addBeanFactoryPostProcessor()方法是留给业务扩展时调用的,例如在springboot初始化时,ConfigurationWarningsApplicationContextInitializer类的initialize方法中就有调用:
@Overridepublic void initialize(ConfigurableApplicationContext context) {context.addBeanFactoryPostProcessor(new ConfigurationWarningsPostProcessor(getChecks()));}
三、invokeBeanFactoryPostProcessors
invokeBeanFactoryPostProcessors方法是:调用beanFactory的后置处理器,后面s表示复数,该方法两个参数:beanFactory一个单对象,和beanFactoryPostProcessors1个beanFactory后置处理器列表。- bean后置处理器处理的是bean实例
- beanfactory后置处理器处理的是bean的定义,就是尚未实例化的bean
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {// Invoke BeanDefinitionRegistryPostProcessors first, if any.Set<String> processedBeans = new HashSet<String>();// 1.判断beanFactory是否为BeanDefinitionRegistry,beanFactory为DefaultListableBeanFactory,// 而DefaultListableBeanFactory实现了BeanDefinitionRegistry接口,因此这边为trueif (beanFactory instanceof BeanDefinitionRegistry) {BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;// 用于存放普通的BeanFactoryPostProcessorList<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();// 用于存放BeanDefinitionRegistryPostProcessorList<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();// 2.首先处理入参中的beanFactoryPostProcessors// 遍历所有的beanFactoryPostProcessors, 将BeanDefinitionRegistryPostProcessor和普通BeanFactoryPostProcessor区分开for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {// 2.1 如果是BeanDefinitionRegistryPostProcessorBeanDefinitionRegistryPostProcessor registryProcessor =(BeanDefinitionRegistryPostProcessor) postProcessor;// 2.1.1 直接执行BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法registryProcessor.postProcessBeanDefinitionRegistry(registry);// 2.1.2 添加到registryProcessors(用于最后执行postProcessBeanFactory方法)registryProcessors.add(registryProcessor);} else {// 2.2 否则,只是普通的BeanFactoryPostProcessor// 2.2.1 添加到regularPostProcessors(用于最后执行postProcessBeanFactory方法)regularPostProcessors.add(postProcessor);}}// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let the bean factory post-processors apply to them!// Separate between BeanDefinitionRegistryPostProcessors that implement// PriorityOrdered, Ordered, and the rest.// =====================================================================// 这后面的代码都是执行的是第一个参数beanFactory的获取到的BeanFactoryPostProcessor// 用于保存本次要执行的BeanDefinitionRegistryPostProcessorList<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.// 3.调用所有实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor实现类// 3.1 找出所有实现BeanDefinitionRegistryPostProcessor接口的Bean的beanNameString[] postProcessorNames =beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);// 3.2 遍历postProcessorNamesfor (String ppName : postProcessorNames) {// 3.3 校验是否实现了PriorityOrdered接口if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {// 3.4 获取ppName对应的bean实例, 添加到currentRegistryProcessors中,// beanFactory.getBean: 这边getBean方法会触发创建ppName对应的bean对象, 目前暂不深入解析currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));// 3.5 将要被执行的加入processedBeans,避免后续重复执行processedBeans.add(ppName);}}// 3.6 进行排序(根据是否实现PriorityOrdered、Ordered接口和order值来排序)sortPostProcessors(currentRegistryProcessors, beanFactory);// 3.7 添加到registryProcessors(用于最后执行postProcessBeanFactory方法)// 因为实现了BeanDefinitionRegistryPostProcessor接口的类,会执行两个方法,// 第一个方法是:postProcessBeanDefinitionRegistry方法// 第二个方法是:postProcessBeanFactory方法,这个方法放在后面执行registryProcessors.addAll(currentRegistryProcessors);// 3.8 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);// 3.9 执行完毕后, 清空currentRegistryProcessorscurrentRegistryProcessors.clear();// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.// 4.调用所有实现了Ordered接口的BeanDefinitionRegistryPostProcessor实现类(过程跟上面的步骤3基本一样)// 4.1 找出所有实现BeanDefinitionRegistryPostProcessor接口的类, 这边重复查找是因为执行完上面的BeanDefinitionRegistryPostProcessor,// 可能会新增了其他的BeanDefinitionRegistryPostProcessor, 因此需要重新查找postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {// 校验是否实现了Ordered接口,并且还未执行过if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);}}sortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);// 4.2 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);currentRegistryProcessors.clear();
1.判断beanFactory是否为 BeanDefinitionRegistry。beanFactory是在之前的 obtainFreshBeanFactory方法获取的,obtainFreshBeanFactory方法如果这里是基于注解的情况下,是在初始化的时候就已经是构建好的,初始化的时候构建的是DefaultListableBeanFactory。而 DefaultListableBeanFactory 实现了BeanDefinitionRegistry 接口,因此beanFactory instanceof BeanDefinitionRegistry 结果为 true。
3.4 获取ppName 对应的 bean 实例,添加到 currentRegistryProcessors 中,准备执行。beanFactory.getBean 方法会触发创建 ppName 对应的 bean 实例对象,创建 bean 实例是 IoC 的另一个核心内容,之后会单独解析,目前暂不深入解析。
优秀的博主:https://www.zhihu.com/people/opiece.me/posts
四、基本使用
我们通常在使用 Mybatis + Spring 时,经常用到的 org.mybatis.spring.mapper.MapperScannerConfigurer 就是一个BeanDefinitionRegistryPostProcessor。MapperScannerConfigurer 在 postProcessBeanDefinitionRegistry 方法中进行了一些操作,主要是:扫描 basePackage 指定的目录,将该目录下的类(通常是 DAO/MAPPER 接口)封装成 BeanDefinition 并加载到 BeanFactory 中。因此,我们可以看到我们项目中的 DAO(MAPPER)接口,通常都没有使用注解或 XML 的方式注册到 Spring 容器,但是我们还是可以在 Service 服务中,使用 @Autowire 注解来将其注入到 Service 中,就是因为这个原因。
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><!--basePackage指定要扫描的包,在此包之下的映射器都会被搜索到。可指定多个包,包与包之间用逗号或分号分隔--><property name="basePackage" value="com.joonwhee.open.demo.mapper"/><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/></bean>
