Spring Bean后处理器

引言

Spring框架的核心能力之一是依赖注入(DI)​生命周期管理 ,而实现这一能力的核心组件是BeanPostProcessor(Bean后处理器)。它贯穿Bean的整个生命周期,负责处理依赖注入、生命周期回调、属性绑定等关键逻辑。本文将结合源码示例,深入解析Spring Bean后处理器的执行流程,覆盖依赖注入(@Autowired/@Resource)、初始化回调(@PostConstruct/@PreDestroy)、配置属性绑定(@ConfigurationProperties)等核心场景,并通过手动模拟验证底层实现原理。


一、Spring容器初始化全流程概览

要理解BeanPostProcessor的作用,首先需要明确Spring容器的初始化流程。以下是基于GenericApplicationContext的典型流程(对应refresh()方法核心逻辑):

  1. 容器创建 :初始化BeanFactoryBeanDefinitionRegistry等核心组件。
  2. Bean定义注册 :将用户定义的Bean(如BeanPostProcessorA)转换为BeanDefinition并存入beanDefinitionMap
  3. 后处理器注册 :注册Spring内置的BeanPostProcessor(如AutowiredAnnotationBeanPostProcessor)及自定义后处理器。
  4. Bean实例化与初始化 :根据BeanDefinition创建Bean实例,依次执行依赖注入、初始化回调。
  5. 容器刷新完成 :触发ContextRefreshedEvent,通知监听器。
  6. 容器关闭 :触发@PreDestroy回调,销毁Bean,清空缓存。

本文将通过BeanPostProcessorCase主类演示这一完整流程,并结合AutowiredPostProcessorCase手动模拟@Autowired的处理逻辑。


二、BeanPostProcessorCase深度解析:Spring自动流程

2.1 容器初始化与Bean注册

2.1.1 容器创建

主方法中首先创建GenericApplicationContext

java 复制代码
GenericApplicationContext context = new GenericApplicationContext();

此时容器处于初始状态 ​:beanDefinitionMap为空(无Bean定义),singletonObjects缓存为空(无单例Bean)。

2.1.2 Bean定义注册

通过registerBean方法注册测试Bean(BeanPostProcessorABCE):

java 复制代码
context.registerBean(BeanPostProcessorA.class);
context.registerBean(BeanPostProcessorB.class);
// ...其他Bean

registerBean方法内部会:

  1. 创建BeanDefinition(默认使用RootBeanDefinition)。
  2. BeanDefinition存入beanFactory.beanDefinitionMap(键为Bean名称,默认是类名首字母小写)。
  3. 若Bean是FactoryBean,会额外处理FactoryBean的元数据。

此时beanDefinitionMap的大小为4(对应4个注册的Bean),但尚未实例化任何Bean。


2.2 后处理器注册:Spring内置组件的协作

Spring通过BeanPostProcessor扩展点实现功能解耦,主方法中显式注册了3类核心后处理器:

2.2.1 AutowiredAnnotationBeanPostProcessor:依赖注入处理器

负责处理@Autowired@Value注解的依赖注入,执行顺序最先​(在Bean实例化后、初始化前)。

2.2.2 CommonAnnotationBeanPostProcessor:生命周期处理器

负责处理@Resource(JSR-250)、@PostConstruct@PreDestroy注解,执行顺序在AutowiredAnnotationBeanPostProcessor之后。

2.2.3 ConfigurationPropertiesBindingPostProcessor:配置属性绑定处理器

负责将配置文件(如application.properties)中以${prefix}.开头的属性绑定到@ConfigurationProperties标记的Bean,由Spring Boot自动注册(此处手动调用register方法)。

注册顺序的关键性 ​:
BeanPostProcessor的执行顺序由注册顺序决定。例如,AutowiredAnnotationBeanPostProcessor需先于CommonAnnotationBeanPostProcessor执行,因为@Resource可能依赖@Autowired注入的Bean。


2.3 依赖注入:@Autowired/@Resource/@Value的处理

BeanPostProcessorA为例,其包含@Autowired@Resource@Value三种注入方式,Spring按以下顺序处理:

2.3.1 @Autowired注入(方法注入)

BeanPostProcessorAsetBeanPostProcessorB方法被@Autowired标记:

java 复制代码
@Autowired
public void setBeanPostProcessorB(BeanPostProcessorB beanPostProcessorB) {
    // 注入逻辑
}

Spring处理@Autowired的流程(对应AutowiredAnnotationBeanPostProcessor.postProcessProperties方法):

  1. 扫描元数据 :通过反射扫描所有@Autowired标注的方法、字段,生成InjectionMetadata(记录所有需要注入的元素)。
  2. 依赖查找 :对于每个注入点(如BeanPostProcessorB类型),通过BeanFactory查找匹配的Bean(按类型匹配,若有多个则按@Qualifier或名称匹配)。
  3. 属性注入 :调用目标方法(如setBeanPostProcessorB)传入找到的Bean实例。

关键源码逻辑 ​(AutowiredAnnotationBeanPostProcessor.postProcessProperties):

java 复制代码
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    // 1. 获取或生成InjectionMetadata(包含所有@Autowired/@Value元素)
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    // 2. 执行注入
    metadata.inject(bean, beanName, pvs);
    return pvs;
}

2.3.2 @Resource注入(方法注入)

BeanPostProcessorAsetBeanPostProcessorC方法被@Resource标记:

java 复制代码
@Resource
public void setBeanPostProcessorC(BeanPostProcessorC beanPostProcessorC) {
    // 注入逻辑
}

@Resource的处理由CommonAnnotationBeanPostProcessor完成,流程与@Autowired类似,但支持按名称匹配(若name属性存在)。

2.3.3 @Value注入(方法参数)

BeanPostProcessorAsetHome方法通过@Value("${JAVA_HOME}")注入环境变量:

java 复制代码
@Autowired
public void setHome(@Value("${JAVA_HOME}") String home) {
    // 注入逻辑
}

@Value的解析依赖ContextAnnotationAutowireCandidateResolver(已通过setDefaultListableBeanFactory配置),它会解析${}占位符为环境变量值(如System.getenv("JAVA_HOME"))。


2.4 生命周期回调:@PostConstruct/@PreDestroy

BeanPostProcessorAinit@PostConstruct)和destroy@PreDestroy)方法由CommonAnnotationBeanPostProcessor处理:

2.4.1 @PostConstruct(初始化前回调)

执行时机:依赖注入完成后,InitializingBean.afterPropertiesSet()之前。

源码逻辑(CommonAnnotationBeanPostProcessor.postProcessBeforeInitialization):

java 复制代码
public Object postProcessBeforeInitialization(Object bean, String beanName) {
    // 查找@PostConstruct方法并执行
    return invokeAwareMethods(beanName, bean);
}

2.4.2 @PreDestroy(销毁前回调)

执行时机:容器关闭时,DisposableBean.destroy()之前。

源码逻辑(CommonAnnotationBeanPostProcessor.postProcessAfterInitialization):

java 复制代码
public Object postProcessAfterInitialization(Object bean, String beanName) {
    // 记录@PreDestroy方法,待销毁时调用
    return bean;
}

2.5 配置属性绑定:@ConfigurationProperties

BeanPostProcessorE通过@ConfigurationProperties(prefix = "java")绑定JDK环境变量(如java.homejava.version),处理流程如下:

2.5.1 元数据解析

Spring Boot通过ConfigurationPropertiesBindingPostProcessor扫描@ConfigurationProperties标记的类,解析其字段与配置文件前缀的映射关系(如home字段对应java.home)。

2.5.2 属性绑定

在Bean实例化后,ConfigurationPropertiesBindingPostProcessor会将配置文件中匹配的属性值注入到Bean的字段中(通过反射设置字段值)。


三、AutowiredPostProcessorCase:手动模拟@Autowired处理流程

为了深入理解@Autowired的底层逻辑,我们手动模拟Spring的处理流程,重点关注依赖注入元数据生成实际注入执行

3.1 容器与基础Bean注册

首先创建DefaultListableBeanFactory并注册基础Bean(BeanPostProcessorBC等):

java 复制代码
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
factory.registerSingleton("beanPostProcessorB", new BeanPostProcessorCase.BeanPostProcessorB());
// ...其他Bean

registerSingleton直接将Bean实例存入singletonObjects缓存(跳过实例化和依赖注入阶段),模拟已初始化的成品Bean。


3.2 依赖注入元数据生成(InjectionMetadata)

AutowiredAnnotationBeanPostProcessor通过findAutowiringMetadata方法生成InjectionMetadata,记录所有需要注入的元素(如@Autowired方法、@Resource字段)。

3.2.1 反射调用私有方法

由于findAutowiringMetadata是私有方法,需通过反射调用:

java 复制代码
Method findAutowiringMetadataMethod = AutowiredAnnotationBeanPostProcessor.class.getDeclaredMethod(
    "findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
findAutowiringMetadataMethod.setAccessible(true);
InjectionMetadata injectionMetadata = (InjectionMetadata) findAutowiringMetadataMethod.invoke(
    processor, "beanPostProcessorA", beanA.getClass(), null);

3.2.2 InjectionMetadata结构

InjectionMetadata包含injectedElements(所有需要注入的元素),每个元素是InjectedElement(记录注入目标的位置和依赖描述符)。


3.3 依赖注入执行(InjectionMetadata.inject)

生成InjectionMetadata后,调用inject方法执行实际注入:

java 复制代码
processor.postProcessProperties(null, beanA, "beanPostProcessorA");  // 触发@Autowired注入
metadata.inject(beanH, "beanPostProcessorH", null);  // 触发@Resource/@Value注入

3.3.1 按类型依赖解析(@Autowired)

对于@Autowired注入的BeanPostProcessorB,Spring通过BeanFactory.getBean(Class<T>)查找匹配的单例Bean(beanPostProcessorB已注册,直接返回)。

3.3.2 按名称依赖解析(@Resource)

@Resource默认按名称匹配(name属性为beanPostProcessorC),查找beanFactory中名称为beanPostProcessorC的单例Bean。

3.3.3 @Value占位符解析

@Value("${JAVA_HOME}")通过ContextAnnotationAutowireCandidateResolver解析为环境变量值(如/usr/lib/jvm/java-17-openjdk)。


3.4 验证依赖解析逻辑

通过手动解析依赖验证流程:

java 复制代码
// 解析@Autowired字段beanPostProcessorF(单例Bean)
Field fField = beanH.getClass().getDeclaredField("beanPostProcessorF");
DependencyDescriptor fDescriptor = new DependencyDescriptor(fField, false);
Object fObject = factory.doResolveDependency(fDescriptor, "beanPostProcessorH", null, null);
// 输出:03:53:39.736 [main] INFO com.dwl.post_processor.AutowiredPostProcessorCase -- @Autowired 字段 beanPostProcessorF 解析结果: com.dwl.post_processor.BeanPostProcessorCase$BeanPostProcessorF@9353778

// 解析@Resource方法参数beanPostProcessorG(单例Bean)
Method gMethod = beanH.getClass().getDeclaredMethod("setBeanPostProcessorG", BeanPostProcessorCase.BeanPostProcessorG.class);
MethodParameter gParam = new MethodParameter(gMethod, 0);
DependencyDescriptor gDescriptor = new DependencyDescriptor(gParam, false);
Object gObject = factory.doResolveDependency(gDescriptor, "beanPostProcessorH", null, null);
// 输出:03:53:39.737 [main] INFO com.dwl.post_processor.AutowiredPostProcessorCase -- @Resource 方法参数 beanPostProcessorG 解析结果: com.dwl.post_processor.BeanPostProcessorCase$BeanPostProcessorG@5e82df6a

// 解析@Value注入的JAVA_HOME
Method homeMethod = beanH.getClass().getDeclaredMethod("setHome", String.class);
MethodParameter homeParam = new MethodParameter(homeMethod, 0);
DependencyDescriptor homeDescriptor = new DependencyDescriptor(homeParam, false);
Object homeObject = factory.doResolveDependency(homeDescriptor, "beanPostProcessorH", null, null);
// 输出:03:53:39.737 [main] INFO com.dwl.post_processor.AutowiredPostProcessorCase -- @Value 注入 JAVA_HOME 解析结果: G:\DevelopmentSoftware\JAVA-17

四、总结与扩展

4.1 核心结论

  • BeanPostProcessor执行顺序AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessorConfigurationPropertiesBindingPostProcessor
  • 依赖注入流程 :元数据生成(InjectionMetadata)→ 依赖查找(BeanFactory)→ 属性注入(方法/字段赋值)。
  • 生命周期回调@PostConstruct(初始化前)→ InitializingBean.afterPropertiesSet()(可选)→ 自定义初始化方法 → @PreDestroy(销毁前)→ DisposableBean.destroy()(可选)→ 自定义销毁方法。

4.2 扩展思考

  • 自定义BeanPostProcessor :可通过实现BeanPostProcessor接口,插入自定义逻辑(如AOP织入、属性校验)。
  • 循环依赖处理 :Spring通过三级缓存(singletonFactories)解决循环依赖,需结合@Autowired的字段注入场景理解。
  • 配置属性绑定优化@ConfigurationProperties支持类型安全的校验(如@Validated),可结合Binder工具类手动绑定配置。

完整代码

java 复制代码
package com.dwl.post_processor;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import jakarta.annotation.Resource;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.context.support.GenericApplicationContext;

/**
 * @ClassName BeanPostProcessorCase
 * @Description 演示 Spring 核心 Bean 后处理器(BeanPostProcessor)的完整执行流程,
 * 涵盖依赖注入(@Autowired/@Resource)、初始化回调(@PostConstruct/@PreDestroy)、
 * 配置属性绑定(@ConfigurationProperties)的执行逻辑。
 * @Version 1.0.0
 * @Date 2025
 * @Author By Dwl
 */
@Slf4j
public class BeanPostProcessorCase {

    /**
     * 主方法:驱动整个 Spring 容器的初始化、刷新和销毁流程。
     * 对应 Spring 源码中的 {@link GenericApplicationContext#refresh()} 方法入口。
     */
    public static void main(String[] args) {

        // 1. 创建空容器(未初始化任何 Bean 定义或后处理器)
        GenericApplicationContext context = new GenericApplicationContext();
        log.info("[main] 1. 创建 GenericApplicationContext,初始状态:beanDefinitionMap={}, singletonObjects={}",
                context.getBeanFactory().getBeanDefinitionCount(), context.getBeanFactory().getSingletonCount());


        // 2. 注册自定义 Bean 到容器(生成 BeanDefinition 并存入 beanDefinitionMap)
        // 对应 Spring 源码中的 {@link GenericApplicationContext#registerBean(Class)} 方法
        context.registerBean(BeanPostProcessorA.class);  // 包含多种注解的测试 Bean
        context.registerBean(BeanPostProcessorB.class);  // 被 A 依赖的 Bean
        context.registerBean(BeanPostProcessorC.class);  // 被 A 依赖的 Bean
        context.registerBean("beanPostProcessorE", BeanPostProcessorE.class);  // 配置属性绑定测试 Bean
        log.info("[main] 2. 注册自定义 Bean 后,beanDefinitionMap 包含 {} 个 BeanDefinition",
                context.getBeanFactory().getBeanDefinitionCount());


        // 3. 配置容器解析规则:支持 @Value 的 ${} 占位符解析
        // 对应 Spring 源码中的 {@link DefaultListableBeanFactory#setAutowireCandidateResolver(AutowireCandidateResolver)}
        context.getDefaultListableBeanFactory().setAutowireCandidateResolver(
                new ContextAnnotationAutowireCandidateResolver()  // 支持 @Value 的解析器
        );
        log.info("[main] 3. 配置 AutowireCandidateResolver,启用 @Value 占位符解析");

        // 4. 注册核心 BeanPostProcessor(按执行顺序排列)
        // 对应 Spring 源码中的 {@link AbstractApplicationContext#registerBeanPostProcessors(ConfigurableListableBeanFactory)}
        context.registerBean(AutowiredAnnotationBeanPostProcessor.class);  // 依赖注入处理器(@Autowired/@Value)
        context.registerBean(CommonAnnotationBeanPostProcessor.class);     // 生命周期处理器(@Resource/@PostConstruct/@PreDestroy)
        // 手动注册 ConfigurationPropertiesBindingPostProcessor(Spring Boot 自动完成)
        ConfigurationPropertiesBindingPostProcessor.register(context.getDefaultListableBeanFactory());
        log.info("[main] 4. 注册 BeanPostProcessor:AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、ConfigurationPropertiesBindingPostProcessor");


        // 5. 刷新容器(触发 Bean 生命周期全流程:实例化→注入→初始化→销毁)
        // 对应 Spring 源码中的 {@link AbstractApplicationContext#refresh()} 核心方法
        context.refresh();
        log.info("[main] 5. 容器刷新完成,当前单例 Bean 数量:{}", context.getBeanFactory().getSingletonCount());

        // 6. 验证 BeanPostProcessorE 的配置绑定结果
        log.info("[main] beanPostProcessorE: {}", context.getBean("beanPostProcessorE"));

        // 7. 关闭容器(触发 @PreDestroy 回调和资源清理)
        // 对应 Spring 源码中的 {@link AbstractApplicationContext#close()} 方法
        context.close();
        log.info("[main] 7. 容器关闭完成,singletonObjects 缓存已清空");

    }

    /**
     * 测试 Bean:包含 @Autowired、@Resource、@PostConstruct、@PreDestroy、@Value 注解,
     * 用于验证 Spring 依赖注入和生命周期回调的执行顺序。
     */

    @Slf4j
    static class BeanPostProcessorA {

        private BeanPostProcessorB beanPostProcessorB;  // 被 @Resource 注入
        private BeanPostProcessorC beanPostProcessorC;  // 被 @Autowired 注入
        private String home;                            // 被 @Value 注入

        /**
         * @Autowired 注入(方法注入)
         * 执行时机:依赖注入阶段(@PostConstruct 之前)
         * 对应 Spring 源码中的 {@link AutowiredAnnotationBeanPostProcessor#postProcessProperties(PropertyValues, Object, String)}
         */
        @Autowired
        public void setBeanPostProcessorB(BeanPostProcessorB beanPostProcessorB) {
            log.info("[BeanPostProcessorA] @Autowired 生效,注入 BeanPostProcessorB: {}", beanPostProcessorB);
            this.beanPostProcessorB = beanPostProcessorB;
        }

        /**
         * @Resource 注入(方法注入)
         * 执行时机:依赖注入阶段(@Autowired 之后,顺序由 @Resource 的 name 属性决定)
         * 对应 Spring 源码中的 {@link CommonAnnotationBeanPostProcessor#postProcessProperties(PropertyValues, Object, String)}
         */
        @Resource
        public void setBeanPostProcessorC(BeanPostProcessorC beanPostProcessorC) {
            log.info("[BeanPostProcessorA] @Resource 生效,注入 BeanPostProcessorC: {}", beanPostProcessorC);
            this.beanPostProcessorC = beanPostProcessorC;
        }

        /**
         * @Value 注入(方法参数)
         * 执行时机:依赖注入阶段(与 @Autowired 同阶段)
         * 对应 Spring 源码中的 {@link AutowiredAnnotationBeanPostProcessor#postProcessProperties(PropertyValues, Object, String)}
         */
        @Autowired
        public void setHome(@Value("${JAVA_HOME}") String home) {
            log.info("[BeanPostProcessorA] @Value 生效,注入 JAVA_HOME: {}", home);
            this.home = home;
        }

        /**
         * @PostConstruct 初始化回调
         * 执行时机:依赖注入完成后,初始化方法(如 InitializingBean.afterPropertiesSet)之前
         * 对应 Spring 源码中的 {@link CommonAnnotationBeanPostProcessor#postProcessBeforeInitialization(Object, String)}
         */
        @PostConstruct
        public void init() {
            log.info("[BeanPostProcessorA] @PostConstruct 生效,完成初始化");
        }

        /**
         * @PreDestroy 销毁回调
         * 执行时机:容器关闭时,在 Bean 实际销毁前调用
         * 对应 Spring 源码中的 {@link CommonAnnotationBeanPostProcessor#postProcessAfterInitialization(Object, String)}
         */
        @PreDestroy
        public void destroy() {
            log.info("[BeanPostProcessorA] @PreDestroy 生效,准备销毁");
        }

        @Override
        public String toString() {
            return "BeanPostProcessorA{" +
                    "beanPostProcessorB=" + beanPostProcessorB +
                    ", beanPostProcessorC=" + beanPostProcessorC +
                    ", home='" + home + '\'' +
                    '}';
        }
    }

    // 以下为辅助测试 Bean(无特殊注解)
    static class BeanPostProcessorB {
    }

    static class BeanPostProcessorC {
    }

    static class BeanPostProcessorF {
    }

    static class BeanPostProcessorG {
    }


    /**
     * 演示 Spring 配置属性绑定(@ConfigurationProperties)的核心流程,
     * 用于将配置文件中以 "java." 为前缀的属性(如 java.home、java.version)绑定到 Bean 的字段。
     * <p>
     * 关键流程解析:
     * 1. 类级别注解 {@link ConfigurationProperties()}:声明该 Bean 用于绑定配置属性,
     * 其中 prefix="java" 表示只读取配置文件中以 "java." 开头的属性(如 java.home、java.version)。
     * 2. 字段映射:类中的字段(home、version)会自动与配置文件中 "java.home"、"java.version" 属性绑定,
     * 无需手动编写属性读取逻辑(由 Spring 自动完成)。
     * 3. 容器注册:在 BeanPostProcessorCase 的 main 方法中通过 context.registerBean() 注册为单例 Bean,
     * Spring 在刷新容器时会触发配置属性绑定逻辑(由 ConfigurationPropertiesBindingPostProcessor 处理)。
     */
    @Data
    @ConfigurationProperties(prefix = "java")  // 绑定配置文件中以 "java." 为前缀的属性
    static class BeanPostProcessorE {
        /**
         * 对应配置文件中的 java.home 属性(JDK 安装路径)
         */
        private String home;

        /**
         * 对应配置文件中的 java.version 属性(JDK 版本号)
         */
        private String version;
    }

    /**
     * 测试类:用于演示依赖注入失败场景(依赖未注册的 Bean)
     */
    @Slf4j
    static class BeanPostProcessorH {
        private BeanPostProcessorF beanPostProcessorF;  // 未在容器中注册的 Bean
        private BeanPostProcessorG beanPostProcessorG;  // 未在容器中注册的 Bean
        private String home;

        @Autowired
        public void setBeanPostProcessorF(BeanPostProcessorF beanPostProcessorF) {
            log.info("[BeanPostProcessorH] @Autowired 生效,注入 BeanPostProcessorF: {}", beanPostProcessorF);
            this.beanPostProcessorF = beanPostProcessorF;
        }

        @Resource
        public void setBeanPostProcessorG(BeanPostProcessorG beanPostProcessorG) {
            log.info("[BeanPostProcessorH] @Resource 生效,注入 BeanPostProcessorG: {}", beanPostProcessorG);
            this.beanPostProcessorG = beanPostProcessorG;
        }

        @Autowired
        public void setHome(@Value("${JAVA_HOME}") String home) {
            log.info("[BeanPostProcessorH] @Value 生效,注入 JAVA_HOME: {}", home);
            this.home = home;
        }

        @PostConstruct
        public void init() {
            log.info("[BeanPostProcessorH] @PostConstruct 生效,完成初始化");
        }

        @PreDestroy
        public void destroy() {
            log.info("[BeanPostProcessorH] @PreDestroy 生效,准备销毁");
        }

        @Override
        public String toString() {
            return "BeanPostProcessorH{" +
                    "beanPostProcessorF=" + beanPostProcessorF +
                    ", beanPostProcessorG=" + beanPostProcessorG +
                    ", home='" + home + '\'' +
                    '}';
        }
    }
}

package com.dwl.post_processor;

import com.dwl.json.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.env.StandardEnvironment;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @ClassName AutowiredPostProcessorCase
 * @Description 手动模拟 Spring 对 @Autowired 注解的处理流程,
 * 深入理解依赖注入元数据(InjectionMetadata)的生成和注入逻辑。
 * <p>
 * 关键方法对应 Spring 源码中的核心逻辑(如 AutowiredAnnotationBeanPostProcessor 的 postProcessProperties)。
 * @Version 1.0.0
 * @Date 2025
 * @Author By Dwl
 */
@Slf4j
public class AutowiredPostProcessorCase {

    /**
     * 主方法:驱动整个手动模拟流程,验证 @Autowired 注入逻辑。
     */
    public static void main(String[] args) throws Throwable {
        // 1. 创建容器并注册基础 Bean(模拟已存在的 Bean)
        log.info("[main] 1. 创建 DefaultListableBeanFactory 并注册基础 Bean...");
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

        // 注册单例 Bean(不会触发依赖注入,视为已初始化完成的成品 Bean)
        // 对应 Spring 源码中的 {@link DefaultListableBeanFactory#registerSingleton(String, Object)}
        factory.registerSingleton("beanPostProcessorB", new BeanPostProcessorCase.BeanPostProcessorB());
        factory.registerSingleton("beanPostProcessorC", new BeanPostProcessorCase.BeanPostProcessorC());
        factory.registerSingleton("beanPostProcessorF", new BeanPostProcessorCase.BeanPostProcessorF());
        factory.registerSingleton("beanPostProcessorG", new BeanPostProcessorCase.BeanPostProcessorG());
        log.info("[main] 1. 注册单例 Bean 后,singletonCount={}", factory.getSingletonCount());

        // 2. 配置容器:支持 @Value 的 ${} 占位符解析
        // 对应 Spring 源码中的 {@link DefaultListableBeanFactory#setAutowireCandidateResolver(AutowireCandidateResolver)}
        log.info("[main] 2. 配置容器的自动装配解析器...");
        factory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());

        // 3. 创建 AutowiredAnnotationBeanPostProcessor 并关联容器
        // 对应 Spring 源码中的 {@link AutowiredAnnotationBeanPostProcessor#setBeanFactory(BeanFactory)}
        log.info("[main] 3. 创建 AutowiredAnnotationBeanPostProcessor...");
        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(factory);

        // ------------------------- 演示 BeanPostProcessorA 的 @Autowired 注入 -------------------------
        // 目标 Bean:包含 @Autowired、@Resource、@Value 注解的 BeanPostProcessorA
        BeanPostProcessorCase.BeanPostProcessorA beanA = new BeanPostProcessorCase.BeanPostProcessorA();
        log.info("\n===== 开始处理 BeanPostProcessorA =====");
        log.info("原始 Bean 状态(未注入): {}", beanA);

        // 3.1 扫描 Bean 的 @Autowired 元数据(生成 InjectionMetadata)
        // 对应 Spring 源码中的 {@link AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata(String, Class, PropertyValues)}
        // 注意:findAutowiringMetadata 是私有方法,需通过反射调用
        log.info("[main] 3.1 反射调用 findAutowiringMetadata...");
        Method findAutowiringMetadataMethod = AutowiredAnnotationBeanPostProcessor.class.getDeclaredMethod(
                "findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        findAutowiringMetadataMethod.setAccessible(true);
        InjectionMetadata injectionMetadata = (InjectionMetadata) findAutowiringMetadataMethod.invoke(
                processor, "beanPostProcessorA", beanA.getClass(), null);
        log.info("检测到 @Autowired 元素数量: {}", injectionMetadata.getInjectedElements().size());

        // 3.2 执行依赖注入(按类型查找并设置属性/方法参数)
        // 对应 Spring 源码中的 {@link AutowiredAnnotationBeanPostProcessor#postProcessProperties(PropertyValues, Object, String)}
        log.info("[main] 3.2 执行依赖注入...");
        processor.postProcessProperties(null, beanA, "beanPostProcessorA");  // 参数为 PropertyValues(此处无额外属性)
        log.info("注入后 Bean 状态: {}", beanA);

        // ------------------------- 演示 BeanPostProcessorH 的依赖注入 -------------------------
        // 目标 Bean:包含 @Resource、@Value 注解的 BeanPostProcessorH
        BeanPostProcessorCase.BeanPostProcessorH beanH = new BeanPostProcessorCase.BeanPostProcessorH();
        log.info("\n===== 开始处理 BeanPostProcessorH =====");
        log.info("原始 Bean 状态(未注入): {}", beanH);

        // 4.1 手动注册 @Value 解析器(模拟 Spring 自动配置)
        // 对应 Spring 源码中的 {@link ConfigurableApplicationContext#addEmbeddedValueResolver}
        log.info("[main] 4.1 注册 @Value 解析器...");
        factory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders);

        // 4.2 扫描 Bean 的依赖元数据(包括 @Resource、@Value)
        // 对应 Spring 源码中的 {@link AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata(String, Class, PropertyValues)}
        log.info("[main] 4.2 反射调用 findAutowiringMetadata...");
        InjectionMetadata metadata = (InjectionMetadata) findAutowiringMetadataMethod.invoke(
                processor, "beanPostProcessorH", beanH.getClass(), null);
        log.info("检测到依赖元数据: {}", JSON.toJSON(metadata));

        // 4.3 执行依赖注入(按字段和方法)
        // 对应 Spring 源码中的 {@link InjectionMetadata#inject(Object, String, PropertyValues)}
        log.info("[main] 4.3 执行 BeanPostProcessorH 的依赖注入...");
        metadata.inject(beanH, "beanPostProcessorH", null);
        log.info("注入后 BeanH 状态: {}", beanH);

        // ------------------------- 验证依赖解析逻辑 -------------------------
        log.info("\n===== 验证依赖解析逻辑 =====");
        // 按字段解析依赖(BeanPostProcessorF)
        Field fField = beanH.getClass().getDeclaredField("beanPostProcessorF");
        DependencyDescriptor fDescriptor = new DependencyDescriptor(fField, false);  // required=true
        Object fObject = factory.doResolveDependency(fDescriptor, "beanPostProcessorH", null, null);
        log.info("@Autowired 字段 beanPostProcessorF 解析结果: {}", fObject);  // 应注入单例 BeanPostProcessorF

        // 按方法参数解析依赖(BeanPostProcessorG)
        Method gMethod = beanH.getClass().getDeclaredMethod("setBeanPostProcessorG", BeanPostProcessorCase.BeanPostProcessorG.class);
        MethodParameter gParam = new MethodParameter(gMethod, 0);
        DependencyDescriptor gDescriptor = new DependencyDescriptor(gParam, false);
        Object gObject = factory.doResolveDependency(gDescriptor, "beanPostProcessorH", null, null);
        log.info("@Resource 方法参数 beanPostProcessorG 解析结果: {}", gObject);  // 应注入单例 BeanPostProcessorG

        // 解析 @Value 注入(JAVA_HOME)
        Method homeMethod = beanH.getClass().getDeclaredMethod("setHome", String.class);
        MethodParameter homeParam = new MethodParameter(homeMethod, 0);
        DependencyDescriptor homeDescriptor = new DependencyDescriptor(homeParam, false);
        Object homeObject = factory.doResolveDependency(homeDescriptor, "beanPostProcessorH", null, null);
        log.info("@Value 注入 JAVA_HOME 解析结果: {}", homeObject);  // 应输出系统 JAVA_HOME 环境变量值
    }
}
相关推荐
方圆想当图灵14 分钟前
深入理解软件设计:什么是好的架构?
后端·架构·代码规范
fajianchen28 分钟前
Spring中观察者模式的应用
java·开发语言
库库林_沙琪马33 分钟前
深入理解 @JsonGetter:精准掌控前端返回数据格式!
java·前端
手握风云-44 分钟前
JavaEE初阶第一期:计算机是如何 “思考” 的(上)
java·java-ee
普通的冒险者1 小时前
微博项目(总体搭建)
java·开发语言
BAGAE1 小时前
Flutter 与原生技术(Objective-C/Swift,java)的关系
java·开发语言·macos·objective-c·cocoa·智慧城市·hbase
江湖有缘1 小时前
使用obsutil工具在OBS上完成基本的数据存取【玩转华为云】
android·java·华为云
bxlj_jcj2 小时前
Kafka环境搭建全攻略:从Docker到Java实战
java·docker·kafka
国科安芯2 小时前
【AS32系列MCU调试教程】性能优化:Eclipse环境下AS32芯片调试效率提升
java·性能优化·eclipse
Chase_______2 小时前
静态变量详解(static variable)
java·开发语言·jvm