• Spring扩展接口(4):InstantiationAwareBeanPostProcessor


    在此系列文章中,我总结了Spring几乎所有的扩展接口,以及各个扩展点的使用场景。并整理出一个bean在spring中从被加载到最终初始化的所有可扩展点的顺序调用图。这样,我们也可以看到bean是如何一步步加载到spring容器中的。


    InstantiationAwareBeanPostProcessor

    1、概述

    public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
        @Nullable
        default Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
            return null;
        }
    
        default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
            return true;
        }
    
        @Nullable
        default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
            return null;
        }
    }
    

    Spring框架提供了许多扩展接口,用于在Bean的生命周期中插入自定义逻辑。其中之一是InstantiationAwareBeanPostProcessor接口,它允许我们在Spring容器实例化Bean之前和之后进行一些自定义处理。

    InstantiationAwareBeanPostProcessor接口是BeanPostProcessor接口的子接口,它定义了在Bean实例化过程中的扩展点。与BeanPostProcessor接口相比,InstantiationAwareBeanPostProcessor接口提供了更细粒度的控制能力。它在Bean实例化的不同阶段提供了多个回调方法,允许我们在不同的时机对Bean进行自定义处理。

    在Spring容器启动过程中,InstantiationAwareBeanPostProcessor接口的方法执行顺序如下:

    1. postProcessBeforeInstantiation方法:在Bean实例化之前调用,如果返回null,一切按照正常顺序执行,如果返回的是一个实例的对象,那么这个将会跳过实例化、初始化的过程
    2. postProcessAfterInstantiation方法:在Bean实例化之后调用,可以对已实例化的Bean进行进一步的自定义处理。
    3. postProcessPropertyValues方法:在Bean的属性注入之前调用,可以修改Bean的属性值或进行其他自定义操作,当postProcessAfterInstantiation返回true才执行。
    方法 执行顺序 备注
    postProcessBeforeInstantiation() 在 Bean 创建前调用 可用于创建代理类,如果返回的不是 null(也就是返回的是一个代理类) ,那么后续只会调用 postProcessAfterInitialization() 方法
    postProcessAfterInstantiation() 在 Bean 创建后调用 返回值会影响 postProcessProperties() 是否执行,其中返回 false 的话,是不会执行。
    postProcessProperties() 在 Bean 设置属性前调用 用于修改 bean 的属性,如果返回值不为空,那么会更改指定字段的值

    2、简单案例

    下面是一个示例,演示了TestUser这个Bean内部的执行流程。

    
    // InstantiationAwareBeanPostProcessor扩展实现
    @Component
    public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
        @Override
        public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
            if(isMatchClass(beanClass)){
                System.out.println("调用 postProcessBeforeInstantiation 方法");
            }
            return null;
        }
    
        @Override
        public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
            if(isMatchClass(bean.getClass())){
                System.out.println("调用 postProcessAfterInstantiation 方法");
            }
            return true;
        }
    
        @Override
        public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
            if(isMatchClass(bean.getClass())){
                System.out.println("调用 postProcessProperties 方法");
            }
            return pvs;
        }
    
        private boolean isMatchClass(Class beanClass){
            return TestUser.class.equals(ClassUtils.getUserClass(beanClass));
        }
    }
    
    // TestUser测试类
    @Component
    public class TestUser implements InitializingBean {
        String name;
        String password;
    
        public TestUser() {
            System.out.println("创建【TestUser】对象");
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            System.out.println("设置【name】属性");
            this.name = name;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            System.out.println("设置【password】属性");
            this.password = password;
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("所有属性设置完毕");
        }
    }
    

    输出:

    调用 postProcessBeforeInstantiation 方法
    创建【TestUser】对象
    调用 postProcessAfterInstantiation 方法
    调用 postProcessProperties 方法
    所有属性设置完毕
    

    3、源码分析

    InstantiationAwareBeanPostProcessor是在对象实例化和初始化前后执行的逻辑,因此主要的代码都在getBean,doGetBean,cerateBean方法中。

    • 在MyBeanFactoryPostProcessor打上断点,启动SpringApplication,可以看到左下角的调用链路。

    • spring的AbstractApplicationContext的refresh方法,执行this.onRefresh()。

    • 在实例化之前,调用postProcessBeforeInstantiation方法入口就在this.resolveBeforeInstantiation(beanName, mbdToUse)中。

    • bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName)中遍历InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法。
    • 若 this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName)返回了已实例化的Bean,则执行调用postProcessAfterInitialization方法。

    • 在执行完resolveBeforeInstantiation()后,调用doCreateBean()
    • doCreateBean()中先实例化Bean,再调用populateBean()执行后续的postProcessAfterInstantiation()和postProcessProperties()。

  • 相关阅读:
    Markdown 文档标题序号重排版(WebUI Tool)
    武汉新时标文化传媒有限公司企媒体营销与SaaS系统的加持
    uni-app App端优化
    12.1 Go 测试的概念
    2022 第297周周赛
    人工智能 | ShowMeAI资讯日报 #2022.06.23
    正则表达式
    Nuxt3 实战 (五):Header 头部布局
    Python 3.12.0 Release 版本
    今日论文阅读2022-11-10
  • 原文地址:https://www.cnblogs.com/myshare/p/17797936.html