前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring扩展接口(4):InstantiationAwareBeanPostProcessor

Spring扩展接口(4):InstantiationAwareBeanPostProcessor

作者头像
夕阳也是醉了
发布2023-10-31 13:53:02
1460
发布2023-10-31 13:53:02
举报
文章被收录于专栏:夕阳醉了夕阳醉了

在此系列文章中,我总结了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内部的执行流程。

代码语言:javascript
复制
// 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("所有属性设置完毕");
    }
}

输出:

代码语言:javascript
复制
调用 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()。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-10-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • InstantiationAwareBeanPostProcessor
    • 1、概述
      • 2、简单案例
        • 3、源码分析
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档