美文网首页@IT·互联网
Bean的后置处理器

Bean的后置处理器

作者: 我可能是个假开发 | 来源:发表于2023-12-23 15:47 被阅读0次

一、后处理器作用

    1. @Autowired 等注解的解析属于 bean 生命周期阶段(依赖注入, 初始化)的扩展功能,这些扩展功能由 bean 后处理器来完成
    1. 每个后处理器各自增强什么功能
    • AutowiredAnnotationBeanPostProcessor 解析 @Autowired 与 @Value
    • CommonAnnotationBeanPostProcessor 解析 @Resource、@PostConstruct、@PreDestroy
    • ConfigurationPropertiesBindingPostProcessor 解析 @ConfigurationProperties
    1. ContextAnnotationAutowireCandidateResolver 负责获取 @Value 的值,解析 @Qualifier、泛型、@Lazy 等
/*
    bean 后处理器的作用
    a. @Autowired 等注解的解析属于 bean 生命周期阶段(依赖注入, 初始化)的扩展功能
    b. 这些扩展功能由 bean 后处理器来完成
 */
public class PostProcessorTest {
    public static void main(String[] args) {
        // 1.GenericApplicationContext 是一个【干净】的容器
        GenericApplicationContext context = new GenericApplicationContext();

        // 2.️用原始方法注册三个 bean
        context.registerBean("bean1", Bean1.class);
        context.registerBean("bean2", Bean2.class);
        context.registerBean("bean3", Bean3.class);
        context.registerBean("bean4", Bean4.class);

        //默认的解析器不能解析值注入,使用ContextAnnotationAutowireCandidateResolver解析 @Value 等
        context.getDefaultListableBeanFactory().setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());

        // 解析 @Autowired @Value 注解的后置处理器
        context.registerBean(AutowiredAnnotationBeanPostProcessor.class);

        // 解析 @Resource @PostConstruct @PreDestroy 注解的后置处理器
        context.registerBean(CommonAnnotationBeanPostProcessor.class);

        // 解析 @ConfigurationProperties 注解
        ConfigurationPropertiesBindingPostProcessor.register(context.getDefaultListableBeanFactory());

        // 3.初始化容器: 执行beanFactory后处理器, 添加bean后处理器, 初始化所有单例
        context.refresh();

        System.out.println("Bean1"+context.getBean(Bean1.class));
        System.out.println("Bean4"+context.getBean(Bean4.class));

        // 4.销毁容器
        context.close();

    }
}
public class Bean1 {
    private static final Logger log = LoggerFactory.getLogger(Bean1.class);

    private Bean2 bean2;

    @Autowired
    public void setBean2(Bean2 bean2) {
        log.debug("@Autowired 生效: {}", bean2);
        this.bean2 = bean2;
    }

    @Autowired
    private Bean3 bean3;

    @Resource
    public void setBean3(Bean3 bean3) {
        log.debug("@Resource 生效: {}", bean3);
        this.bean3 = bean3;
    }

    private String home;

    @Autowired
    public void setHome(@Value("${JAVA_HOME}") String home) {
        log.debug("@Value 生效: {}", home);
        this.home = home;
    }

    @PostConstruct
    public void init() {
        log.debug("@PostConstruct 生效");
    }

    @PreDestroy
    public void destroy() {
        log.debug("@PreDestroy 生效");
    }

    @Override
    public String toString() {
        return "Bean1{" +
               "bean2=" + bean2 +
               ", bean3=" + bean3 +
               ", home='" + home + '\'' +
               '}';
    }
}
public class Bean2 {
}
public class Bean3 {
}
@ConfigurationProperties(prefix = "java")
public class Bean4 {
    //java.home
    private String home;

    //java.version
    private String version;

    public String getHome() {
        return home;
    }

    public void setHome(String home) {
        this.home = home;
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    @Override
    public String toString() {
        return "Bean4{" +
               "home='" + home + '\'' +
               ", version='" + version + '\'' +
               '}';
    }
}
[DEBUG] 10:04:13.711 [main] com.hcx.springdemo.Bean1            - @Resource 生效: com.hcx.springdemo.Bean3@105fece7 
[DEBUG] 10:04:13.733 [main] com.hcx.springdemo.Bean1            - @Value 生效: ${JAVA_HOME} 
[DEBUG] 10:04:13.734 [main] com.hcx.springdemo.Bean1            - @Autowired 生效: com.hcx.springdemo.Bean2@11dc3715 
[DEBUG] 10:04:13.734 [main] com.hcx.springdemo.Bean1            - @PostConstruct 生效 
Bean1Bean1{bean2=com.hcx.springdemo.Bean2@11dc3715, bean3=com.hcx.springdemo.Bean3@105fece7, home='${JAVA_HOME}'}
Bean4Bean4{home='/Library/Java/JavaVirtualMachines/jdk1.8.0_271.jdk/Contents/Home/jre', version='1.8.0_271'}
[DEBUG] 10:04:13.852 [main] com.hcx.springdemo.Bean1            - @PreDestroy 生效 

二、AutowiredAnnotationBeanPostProcessor:@Autowired bean后处理器运行分析

  • 1.AutowiredAnnotationBeanPostProcessor.findAutowiringMetadata 用来获取某个 bean 上加了 @Value @Autowired 的成员变量,方法参数的信息,表示为InjectionMetadata
  • 2.InjectionMetadata 可以完成依赖注入
  • 3.InjectionMetadata 内部根据成员变量,方法参数封装为DependencyDescriptor 类型
    1. DependencyDescriptor,利用beanFactory.doResolveDependency 方法进行基于类型的查找

AutowiredAnnotationBeanPostProcessor:解析@Value @Autowired:

public class AutowiredTest {
    public static void main(String[] args) throws Throwable {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerSingleton("bean2", new Bean2()); // 创建过程,依赖注入,初始化
        beanFactory.registerSingleton("bean3", new Bean3());
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); // @Value

        // 1. 查找哪些属性、方法加了 @Autowired, 这称之为 InjectionMetadata
        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(beanFactory);

        Bean1 bean1 = new Bean1();
        System.out.println("未解析之前:"+bean1);
        // 执行依赖注入:解析 @Autowired @Value 注解
        processor.postProcessProperties(null, bean1, "bean1");
        System.out.println("解析之后:"+ bean1);
    }
}
未解析之前:Bean1{bean2=null, bean3=null, home='null'}
[DEBUG] 10:21:28.092 [main] com.hcx.springdemo.Bean1            - @Value 生效: ${JAVA_HOME} 
[DEBUG] 10:21:28.101 [main] com.hcx.springdemo.Bean1            - @Autowired 生效: com.hcx.springdemo.Bean2@2eda0940 
解析之后:Bean1{bean2=com.hcx.springdemo.Bean2@2eda0940, bean3=com.hcx.springdemo.Bean3@3578436e, home='${JAVA_HOME}'}

分析

processor.postProcessProperties源码分析:

    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
        InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass(), pvs);

        try {
            metadata.inject(bean, beanName, pvs);
            return pvs;
        } catch (BeanCreationException var6) {
            throw var6;
        } catch (Throwable var7) {
            throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", var7);
        }
    }

1.findAutowiringMetadata查找加了autowired注解的元数据:

public class AutowiredTest {
    public static void main(String[] args) throws Throwable {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerSingleton("bean2", new Bean2()); // 创建过程,依赖注入,初始化
        beanFactory.registerSingleton("bean3", new Bean3());
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); // @Value

        // 1. 查找哪些属性、方法加了 @Autowired, 这称之为 InjectionMetadata
        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(beanFactory);
        
        Method findAutowiringMetadata = AutowiredAnnotationBeanPostProcessor.class.getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        findAutowiringMetadata.setAccessible(true);
        // 获取 Bean1 上加了 @Value @Autowired 的成员变量,方法参数信息
        InjectionMetadata metadata = (InjectionMetadata) findAutowiringMetadata.invoke(processor, "bean1", Bean1.class, null);
        System.out.println(metadata);
image.png
  1. inject真正执行
public class AutowiredTest {
    public static void main(String[] args) throws Throwable {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerSingleton("bean2", new Bean2()); // 创建过程,依赖注入,初始化
        beanFactory.registerSingleton("bean3", new Bean3());
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); // @Value

        // 1. 查找哪些属性、方法加了 @Autowired, 这称之为 InjectionMetadata
        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(beanFactory);

        Bean1 bean1 = new Bean1();
        System.out.println("未解析之前:"+bean1);

        Method findAutowiringMetadata = AutowiredAnnotationBeanPostProcessor.class.getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        findAutowiringMetadata.setAccessible(true);
        // 获取 Bean1 上加了 @Value @Autowired 的成员变量,方法参数信息
        InjectionMetadata metadata = (InjectionMetadata) findAutowiringMetadata.invoke(processor, "bean1", Bean1.class, null);
        System.out.println(metadata);

        metadata.inject(bean1, "bean1", null);
        System.out.println("解析之后:"+ bean1);
    }
}

inject执行按类型查找:

public class AutowiredTest {
    public static void main(String[] args) throws Throwable {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerSingleton("bean2", new Bean2()); // 创建过程,依赖注入,初始化
        beanFactory.registerSingleton("bean3", new Bean3());
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); // @Value

        // 1. 查找哪些属性、方法加了 @Autowired, 这称之为 InjectionMetadata
        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(beanFactory);

        Bean1 bean1 = new Bean1();
        System.out.println("未解析之前:"+bean1);
//        // 执行依赖注入:解析 @Autowired @Value 注解
//        processor.postProcessProperties(null, bean1, "bean1");
//        System.out.println("解析之后:"+ bean1);

        // ${} 的解析器
        beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders);

        Method findAutowiringMetadata = AutowiredAnnotationBeanPostProcessor.class.getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        findAutowiringMetadata.setAccessible(true);
        // 获取 Bean1 上加了 @Value @Autowired 的成员变量,方法参数信息
        InjectionMetadata metadata = (InjectionMetadata) findAutowiringMetadata.invoke(processor, "bean1", Bean1.class, null);
        System.out.println(metadata);
        // 2. 调用 InjectionMetadata 来进行依赖注入, 注入时按类型查找值
        metadata.inject(bean1, "bean1", null);
        System.out.println("解析之后:"+ bean1);

        //======================== inject 内部========================
        // 3. 按类型查找加了@Autowired的属性
        Field bean3 = Bean1.class.getDeclaredField("bean3");
        DependencyDescriptor dd1 = new DependencyDescriptor(bean3, false);
        Object o = beanFactory.doResolveDependency(dd1, null, null, null);
        System.out.println(o); //com.hcx.springdemo.Bean3@4516af24

       // 3. 按类型查找加了@Autowired的方法 根据方法参数的类型来查找
        Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);
        DependencyDescriptor dd2 = new DependencyDescriptor(new MethodParameter(setBean2, 0), true);
        Object o1 = beanFactory.doResolveDependency(dd2, null, null, null);
        System.out.println(o1); //com.hcx.springdemo.Bean2@587c290d

        // 3. 查找值
        Method setHome = Bean1.class.getDeclaredMethod("setHome", String.class);
        DependencyDescriptor dd3 = new DependencyDescriptor(new MethodParameter(setHome, 0), true);
        Object o2 = beanFactory.doResolveDependency(dd3, null, null, null);
        System.out.println(o2); // /Library/Java/JavaVirtualMachines/jdk1.8.0_271.jdk/Contents/Home/jre
    }
}

解析${}:EmbeddedValueResolver

public class AutowiredTest {
    public static void main(String[] args) throws Throwable {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerSingleton("bean2", new Bean2()); // 创建过程,依赖注入,初始化
        beanFactory.registerSingleton("bean3", new Bean3());
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); // @Value

        // 1. 查找哪些属性、方法加了 @Autowired, 这称之为 InjectionMetadata
        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(beanFactory);

        Bean1 bean1 = new Bean1();
        System.out.println("未解析之前:"+bean1);

        // ${} 的解析器
        beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders); 

        Method findAutowiringMetadata = AutowiredAnnotationBeanPostProcessor.class.getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        findAutowiringMetadata.setAccessible(true);
        // 获取 Bean1 上加了 @Value @Autowired 的成员变量,方法参数信息
        InjectionMetadata metadata = (InjectionMetadata) findAutowiringMetadata.invoke(processor, "bean1", Bean1.class, null);
        System.out.println(metadata);
        metadata.inject(bean1, "bean1", null);
        System.out.println("解析之后:"+ bean1);
    }
}

相关文章

网友评论

    本文标题:Bean的后置处理器

    本文链接:https://www.haomeiwen.com/subject/brkpgdtx.html