Spring IoC源码学习:registerBeanPostProcessors 详解

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 在 Spring IoC:invokeBeanFactoryPostProcessors解析 中我们介绍了 invokeBeanFactoryPostProcessors 方法,而本文将介绍另一个类似的方法——registerBeanPostProcessors。

目录

Spring IoC源码学习全系列

前言

概述

正文

registerBeanPostProcessors

代码块1registerBeanPostProcessors

代码块2registerBeanPostProcessors

代码块3beanFactory.addBeanPostProcessor

基本使用

总结

相关文章


Spring IoC源码学习全系列


小白也看得懂的 Spring IoC 核心流程介绍

Spring IoC源码学习:总览

Spring IoC源码学习ApplicationContext 刷新前的配置

Spring IoC源码学习obtainFreshBeanFactory详解

Spring IoC源码学习parseDefaultElement详解

Spring IoC源码学习parseCustomElement详解

Spring IoC源码学习:context:component-scan 节点详解

Spring IoC源码学习invokeBeanFactoryPostProcessors详解

Spring IoC源码学习registerBeanPostProcessors详解

Spring IoC源码学习finishBeanFactoryInitialization详解

Spring IoC源码学习getBean详解

Spring IoC源码学习createBean详解(上)

Spring IoC码学习createBean详解(下)

Spring IoC源码学习:@Autowire 详解

Spring IoC源码学习:finishRefresh 详解

 

前言


Spring IoCinvokeBeanFactoryPostProcessors解析中我们介绍了 invokeBeanFactoryPostProcessors 方法,而本文将介绍另一个类似的方法——registerBeanPostProcessors。


invokeBeanFactoryPostProcessors 方法主要用于处理 BeanFactoryPostProcessor 接口,而registerBeanPostProcessors 方法主要用于处理 BeanPostProcessor 接口。BeanFactoryPostProcessor BeanPostProcessor,相信大家很容易从命名看出来这两个接口长得很像BeanFactoryPostProcessor 是针对 BeanFactory 的扩展,主要用在 bean 实例化之前,读取 bean 的定义,并可以修改它。BeanPostProcessor 是针对 bean 的扩展,主要用在 bean 实例化之后,执行初始化方法前后,允许开发者对 bean实例进行修改。

 

概述


本方法会注册所有的 BeanPostProcessor,将所有实现了 BeanPostProcessor 接口的类加载到BeanFactory 中。


BeanPostProcessor 接口是 Spring 初始化 bean时对外暴露的扩展点,Spring IoC 容器允许 BeanPostProcessor 在容器初始化 bean 的前后,添加自己的逻辑处理。在 registerBeanPostProcessors 方法只是注册到BeanFactory 中,具体调用是在 bean 初始化的时候。


具体的:在所有 bean 实例化时,执行初始化方法前会调用所有 BeanPostProcessor postProcessBeforeInitialization 方法,在执行初始化方法后会调用所有 BeanPostProcessor postProcessAfterInitialization 方法。

 

正文


首先我们回到 AbstractApplicationContext.refresh()方法,找到代码:registerBeanPostProcessors(beanFactory),单击该行代码跳转到具体的实现。

 

registerBeanPostProcessors


protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 1.注册BeanPostProcessor
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

1.注册 BeanPostProcessor见代码块1详解

 

代码块1registerBeanPostProcessors

public static void registerBeanPostProcessors(
        ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
    // 1.找出所有实现BeanPostProcessor接口的类
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
    // Register BeanPostProcessorChecker that logs an info message when
    // a bean is created during BeanPostProcessor instantiation, i.e. when
    // a bean is not eligible for getting processed by all BeanPostProcessors.
    // BeanPostProcessor的目标计数
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    // 2.添加BeanPostProcessorChecker(主要用于记录信息)到beanFactory中
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
    // Separate between BeanPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    // 3.定义不同的变量用于区分: 实现PriorityOrdered接口的BeanPostProcessor、实现Ordered接口的BeanPostProcessor、普通BeanPostProcessor
    // 3.1 priorityOrderedPostProcessors: 用于存放实现PriorityOrdered接口的BeanPostProcessor
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    // 3.2 internalPostProcessors: 用于存放Spring内部的BeanPostProcessor
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
    // 3.3 orderedPostProcessorNames: 用于存放实现Ordered接口的BeanPostProcessor的beanName
    List<String> orderedPostProcessorNames = new ArrayList<String>();
    // 3.4 nonOrderedPostProcessorNames: 用于存放普通BeanPostProcessor的beanName
    List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
    // 4.遍历postProcessorNames, 将BeanPostProcessors按3.1 - 3.4定义的变量区分开
    for (String ppName : postProcessorNames) {
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            // 4.1 如果ppName对应的Bean实例实现了PriorityOrdered接口, 则拿到ppName对应的Bean实例并添加到priorityOrderedPostProcessors
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            priorityOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                // 4.2 如果ppName对应的Bean实例也实现了MergedBeanDefinitionPostProcessor接口,
                // 则将ppName对应的Bean实例添加到internalPostProcessors
                internalPostProcessors.add(pp);
            }
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            // 4.3 如果ppName对应的Bean实例没有实现PriorityOrdered接口, 但是实现了Ordered接口, 则将ppName添加到orderedPostProcessorNames
            orderedPostProcessorNames.add(ppName);
        }
        else {
            // 4.4 否则, 将ppName添加到nonOrderedPostProcessorNames
            nonOrderedPostProcessorNames.add(ppName);
        }
    }
    // First, register the BeanPostProcessors that implement PriorityOrdered.
    // 5.首先, 注册实现PriorityOrdered接口的BeanPostProcessors
    // 5.1 对priorityOrderedPostProcessors进行排序
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    // 5.2 注册priorityOrderedPostProcessors
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
    // Next, register the BeanPostProcessors that implement Ordered.
    // 6.接下来, 注册实现Ordered接口的BeanPostProcessors
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : orderedPostProcessorNames) {
        // 6.1 拿到ppName对应的BeanPostProcessor实例对象
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        // 6.2 将ppName对应的BeanPostProcessor实例对象添加到orderedPostProcessors, 准备执行注册
        orderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            // 6.3 如果ppName对应的Bean实例也实现了MergedBeanDefinitionPostProcessor接口,
            // 则将ppName对应的Bean实例添加到internalPostProcessors
            internalPostProcessors.add(pp);
        }
    }
    // 6.4 对orderedPostProcessors进行排序
    sortPostProcessors(orderedPostProcessors, beanFactory);
    // 6.5 注册orderedPostProcessors
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);
    // Now, register all regular BeanPostProcessors.
    // 7.注册所有常规的BeanPostProcessors(过程与6类似)
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : nonOrderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        nonOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
    // Finally, re-register all internal BeanPostProcessors.
    // 8.最后, 重新注册所有内部BeanPostProcessors(相当于内部的BeanPostProcessor会被移到处理器链的末尾)
    // 8.1 对internalPostProcessors进行排序
    sortPostProcessors(internalPostProcessors, beanFactory);
    // 8.2注册internalPostProcessors
    registerBeanPostProcessors(beanFactory, internalPostProcessors);
    // Re-register post-processor for detecting inner beans as ApplicationListeners,
    // moving it to the end of the processor chain (for picking up proxies etc).
    // 9.重新注册ApplicationListenerDetector(跟8类似,主要是为了移动到处理器链的末尾)
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

5.1 priorityOrderedPostProcessors进行排序,在Spring IoCinvokeBeanFactoryPostProcessors解析代码中3已经解析过。

5.2 注册 priorityOrderedPostProcessors见代码块2详解

 

代码块2registerBeanPostProcessors

private static void registerBeanPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
    // 1.遍历postProcessors
    for (BeanPostProcessor postProcessor : postProcessors) {
        // 2.将PostProcessor添加到BeanFactory中的beanPostProcessors缓存
        beanFactory.addBeanPostProcessor(postProcessor);
    }
}

2. PostProcessor 添加到 BeanFactory 中的beanPostProcessors 缓存,见代码块3详解

 

代码块3beanFactory.addBeanPostProcessor

@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
    Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
    // 1.如果beanPostProcessor已经存在则移除(可以起到排序的效果,beanPostProcessor可能本来在前面,移除再添加,则变到最后面)
    this.beanPostProcessors.remove(beanPostProcessor);
    // 2.将beanPostProcessor添加到beanPostProcessors缓存
    this.beanPostProcessors.add(beanPostProcessor);
    if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
        // 3.如果beanPostProcessor是InstantiationAwareBeanPostProcessor, 则将hasInstantiationAwareBeanPostProcessors设置为true,
        // 该变量用于指示beanFactory是否已注册过InstantiationAwareBeanPostProcessors
        this.hasInstantiationAwareBeanPostProcessors = true;
    }
    if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
        // 4.如果beanPostProcessor是DestructionAwareBeanPostProcessor, 则将hasInstantiationAwareBeanPostProcessors设置为true,
        // 该变量用于指示beanFactory是否已注册过DestructionAwareBeanPostProcessor
        this.hasDestructionAwareBeanPostProcessors = true;
    }
}

该方法作用就是将 BeanPostProcessor 添加到beanPostProcessors 缓存,这边的先移除再添加,主要是起一个排序的作用。而 hasInstantiationAwareBeanPostProcessors hasDestructionAwareBeanPostProcessors 变量用于指示beanFactory 是否已注册过 InstantiationAwareBeanPostProcessors DestructionAwareBeanPostProcessor,在之后的 IoC 创建过程会用到这两个变量,这边先有个印象。

 

基本使用


使用方法比较简单,新建一个类实现 BeanPostProcessor 接口,并将该类注册到 Spring IoC 容器中。

package com.joonwhee.open.demo.spring;
import com.joonwhee.open.demo.service.UserService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.PriorityOrdered;
/**
 * @author joonwhee
 * @date 2019/2/23
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor, PriorityOrdered {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor#postProcessBeforeInitialization");
        if (bean instanceof UserService) {
            System.out.println(beanName);
        }
        // 自己的逻辑
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor#postProcessAfterInitialization");
        // 自己的逻辑
        return bean;
    }
    @Override
    public int getOrder() {
        return 0;
    }
}

这样,在 Spring 创建 bean 实例时,执行初始化方法前会调用 MyBeanPostProcessor postProcessBeforeInitialization 方法,在执行初始化方法后会调用MyBeanPostProcessor postProcessAfterInitialization 方法。

 

总结


如同 invokeBeanFactoryPostProcessors 方法一样,registerBeanPostProcessors 方法的内容也比较少,核心过程在代码块1的注释已经写清楚,这边稍微总结一下。


1.整个 registerBeanPostProcessors 方法围绕 BeanPostProcessor 接口展开,和 invokeBeanFactoryPostProcessors不同的是,invokeBeanFactoryPostProcessors 方法会直接调用 BeanFactoryPostProcessor 实现类的方法,而 registerBeanPostProcessors 方法只是将 BeanPostProcessor 实现类注册到 BeanFactory beanPostProcessors 缓存中。这是因为,此时还未到 BeanPostProcessor 实现类出场的时候


2.BeanPostProcessor 实现类具体的出场时机在创建 bean 实例时,执行初始化方法前后。postProcessBeforeInitialization 方法在执行初始化方法前被调用,postProcessAfterInitialization 方法在执行初始化方法后被调用。


3.BeanPostProcessor 实现类和 BeanFactoryPostProcessor 实现类一样,也可以通过实现 PriorityOrderedOrdered 接口来调整自己的优先级。


4.registerBeanPostProcessors 方法和 invokeBeanFactoryPostProcessors 也会触发bean 实例的创建,创建 Bean 实例是 IoC 的核心内容,之后会单独解析,目前暂不深入解析。

 

相关文章
|
3天前
|
前端开发 Java 数据库
SpringBoot学习
【10月更文挑战第7天】Spring学习
24 9
|
4天前
|
JavaScript Java 关系型数据库
自主版权的Java诊所管理系统源码,采用Vue 2、Spring Boot等技术栈,支持二次开发
这是一个自主版权的Java诊所管理系统源码,支持二次开发。采用Vue 2、Spring Boot等技术栈,涵盖患者管理、医生管理、门诊管理、药店管理、药品管理、收费管理、医保管理、报表统计及病历电子化等功能模块。
|
4天前
|
XML Java 数据格式
Spring学习
【10月更文挑战第6天】Spring学习
14 1
|
9天前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
|
9天前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)
|
9天前
|
Java 测试技术 开发者
springboot学习四:Spring Boot profile多环境配置、devtools热部署
这篇文章主要介绍了如何在Spring Boot中进行多环境配置以及如何整合DevTools实现热部署,以提高开发效率。
27 2
|
9天前
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
24 1
|
9天前
|
Java API Spring
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中拦截器的入门教程和实战项目场景实现的详细指南。
13 0
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
|
9天前
|
Java API Spring
springboot学习六:Spring Boot2.x 过滤器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中过滤器的基础知识和实战项目应用的教程。
12 0
springboot学习六:Spring Boot2.x 过滤器基础入门&实战项目场景实现
|
9天前
|
Java 关系型数据库 MySQL
springboot学习五:springboot整合Mybatis 连接 mysql数据库
这篇文章是关于如何使用Spring Boot整合MyBatis来连接MySQL数据库,并进行基本的增删改查操作的教程。
14 0
springboot学习五:springboot整合Mybatis 连接 mysql数据库