Spring 高级 @Autowired 失效分析

一、失效演示

1、正常情况

package com.mangoubiubiu.show.a06;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

@Slf4j
@Configuration
public class MyConfig1 {

     @Autowired
     public void setApplicationContext(ApplicationContext applicationContext){
         log.info("注入 ApplicationContext");
     }

     @PostConstruct
     public void init(){
         log.debug("初始化");
     }
}
package com.mangoubiubiu.show.a06;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;

@Slf4j
public class A06Application {


    public static void main(String[] args) {

       /*
        Aware 接口提供了一种【内置】 的注入手段,例如
                * BeanNameAware 注入 bean 的名字
                * BeanFactoryAware 注入 BeanFactory 容器
                * ApplicationContextAware 注入 ApplicationContext 容器
                * EmbeddedValueResolverAware 注入 ${} 解析器
        */



        GenericApplicationContext context = new GenericApplicationContext();


        context.registerBean("myConfig1",MyConfig1.class);

//        context.registerBean("myBean",MyBean.class);
        context.registerBean(AutowiredAnnotationBeanPostProcessor.class);//解析@Autowired的后处理器
        context.registerBean(CommonAnnotationBeanPostProcessor.class);//解析@PostConstruct的后处理器
        context.registerBean(ConfigurationClassPostProcessor.class);


        /**
         * refresh 执行顺序
         * 1. beanFactory 后处理器, 2. 添加 bean 处理器    3. 初始化单列
         */

        context.refresh();//初始化容器
        context.close();//关闭容器



    }

}

正常解析到@Autowired @PostConstruct

2、失效情况

package com.mangoubiubiu.show.a06;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

@Slf4j
@Configuration
public class MyConfig1 {

     @Autowired
     public void setApplicationContext(ApplicationContext applicationContext){
         log.info("注入 ApplicationContext");
     }

     @PostConstruct
     public void init(){
         log.debug("初始化");
     }

     @Bean //BeanFactory 后处理器
    public BeanFactoryPostProcessor processor1(){
         return configurableListableBeanFactory -> {
             log.info("执行 processor1");
         };
     }

}

发现@Autowired @PostConstruct 并没有被解析到

3、失效原因分析

Java 配置类不包含 BeanFactoryPostProcessor 的情况(就是我们上面第一点的正常情况!!!)

Java 配置类包含 BeanFactoryPostProcessor 的情况,因此要创建其中的 BeanFactoryPostProcessor 必须提前创建 Java 配置类,而此时的 BeanPostProcessor 还未准备好,导致 @Autowired 等注解失效

4、失效解决方案

1 用内置依赖注入和初始化取代扩展依赖注入和初始化

package com.mangoubiubiu.show.a06;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;

@Slf4j
public class MyConfig2 implements ApplicationContextAware, InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("当前bean:{},初始化",this);

    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        log.info("使用 @Autowired 注入 当前bean:{},容器是{}",this,applicationContext);

    }

    @Bean //BeanFactory 后处理器
    public BeanFactoryPostProcessor processor1(){
        return configurableListableBeanFactory -> {
            log.info("执行 processor1");
        };
    }
}

成功执行初始化方法,取到当前容器对象。

2 用静态工厂方法代替实例工厂方法,避免工厂对象提前被创建

暂时略过

 

 

 

 

posted @ 2022-08-28 15:03  KwFruit  阅读(429)  评论(0编辑  收藏  举报