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 用静态工厂方法代替实例工厂方法,避免工厂对象提前被创建
暂时略过