Aware接口作用
Aware 接口用于注入一些与容器相关信息
- BeanNameAware 注入 bean 的名字
- BeanFactoryAware 注入 BeanFactory 容器
- ApplicationContextAware 注入 ApplicationContext 容器
- EmbeddedValueResolverAware ${}
案例
public class MyBean implements BeanNameAware, ApplicationContextAware, InitializingBean { private static final Logger log = LoggerFactory.getLogger(MyBean.class); @Override public void setBeanName(String name) { log.debug("当前bean " + this + " 名字叫:" + name); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { log.debug("当前bean " + this + " 容器是:" + applicationContext); } @Override public void afterPropertiesSet() throws Exception { log.debug("当前bean " + this + " 初始化"); } @Autowired public void aaa(ApplicationContext applicationContext) { log.debug("当前bean " + this + " 使用@Autowired 容器是:" + applicationContext); } @PostConstruct public void init() { log.debug("当前bean " + this + " 使用@PostConstruct 初始化"); } }
注册MyBean
public class A06 { private static final Logger log = LoggerFactory.getLogger(A06.class); public static void main(String[] args) { /* 1. Aware 接口用于注入一些与容器相关信息, 例如 a. BeanNameAware 注入 bean 的名字 b. BeanFactoryAware 注入 BeanFactory 容器 c. ApplicationContextAware 注入 ApplicationContext 容器 d. EmbeddedValueResolverAware ${} */ GenericApplicationContext context = new GenericApplicationContext(); context.registerBean("myBean", MyBean.class); context.registerBean(AutowiredAnnotationBeanPostProcessor.class); context.registerBean(CommonAnnotationBeanPostProcessor.class); context.registerBean(ConfigurationClassPostProcessor.class); context.refresh(); // 1. beanFactory 后处理器, 2. 添加 bean 后处理器, 3. 初始化单例 context.close(); } }
[INFO ] 10:03:41.050 [main] o.s.c.a.ConfigurationClassEnhancer - @Bean method MyConfig1.processor1 is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean javadoc for complete details. [DEBUG] 10:03:41.062 [main] com.onethink.a06.MyConfig1 - 执行 processor1 [DEBUG] 10:03:41.099 [main] com.onethink.a06.MyBean - 当前bean com.onethink.a06.MyBean@23f5b5dc 使用@Autowired 容器是:org.springframework.context.support.GenericApplicationContext@de3a06f, started on Sun Apr 02 10:03:40 CST 2023 [DEBUG] 10:03:41.099 [main] com.onethink.a06.MyBean - 当前bean com.onethink.a06.MyBean@23f5b5dc 名字叫:myBean [DEBUG] 10:03:41.099 [main] com.onethink.a06.MyBean - 当前bean com.onethink.a06.MyBean@23f5b5dc 容器是:org.springframework.context.support.GenericApplicationContext@de3a06f, started on Sun Apr 02 10:03:40 CST 2023 [DEBUG] 10:03:41.101 [main] com.onethink.a06.MyBean - 当前bean com.onethink.a06.MyBean@23f5b5dc 使用@PostConstruct 初始化 [DEBUG] 10:03:41.101 [main] com.onethink.a06.MyBean - 当前bean com.onethink.a06.MyBean@23f5b5dc 初始化
和@Autowired 的区别
@Autowired
的解析需要用到 bean 后处理器, 属于扩展功能
- 而 Aware 接口属于内置功能, 不加任何扩展, Spring 就能识别某些情况下, 扩展功能会失效, 而内置功能不会失效
@Autowired
注入失效
例1: Aware 注入 ApplicationContext 成功, 而 @Autowired 注入 ApplicationContext 失败
@Configuration public class MyConfig1 { private static final Logger log = LoggerFactory.getLogger(MyConfig1.class); @Autowired public void setApplicationContext(ApplicationContext applicationContext) { log.debug("注入 ApplicationContext"); } @PostConstruct public void init() { log.debug("初始化"); } }
在配置类里初始化一个
BeanFactoryPostProcessor
对象@Configuration public class MyConfig1 { private static final Logger log = LoggerFactory.getLogger(MyConfig1.class); @Autowired public void setApplicationContext(ApplicationContext applicationContext) { log.debug("注入 ApplicationContext"); } @PostConstruct public void init() { log.debug("初始化"); } @Bean // beanFactory 后处理器 public BeanFactoryPostProcessor processor1() { return beanFactory -> { log.debug("执行 processor1"); }; } }
配置类 @Autowired
失效分析
context.refresh()的作用
- beanFactory 后处理器
- 添加 bean 后处理器
- 初始化单例
Java 配置类不包含 BeanFactoryPostProcessor 的情况
sequenceDiagram participant ac as ApplicationContext participant bfpp as BeanFactoryPostProcessor participant bpp as BeanPostProcessor participant config as Java配置类 ac ->> bfpp : 1. 执行 BeanFactoryPostProcessor ac ->> bpp : 2. 注册 BeanPostProcessor ac ->> +config : 3. 创建和初始化 bpp ->> config : 3.1 依赖注入扩展(如 @Value 和 @Autowired) bpp ->> config : 3.2 初始化扩展(如 @PostConstruct) ac ->> config : 3.3 执行 Aware 及 InitializingBean config -->> -ac : 3.4 创建成功
Java 配置类包含 BeanFactoryPostProcessor 的情况,
要创建其中的 BeanFactoryPostProcessor 必须提前创建 Java 配置类,而此时的 BeanPostProcessor 还未准备好,导致 @Autowired 等注解失效
sequenceDiagram participant ac as ApplicationContext participant bfpp as BeanFactoryPostProcessor participant bpp as BeanPostProcessor participant config as Java配置类 ac ->> +config : 3. 创建和初始化 ac ->> config : 3.1 执行 Aware 及 InitializingBean config -->> -ac : 3.2 创建成功 ac ->> bfpp : 1. 执行 BeanFactoryPostProcessor ac ->> bpp : 2. 注册 BeanPostProcessor
解决方法:
- 用内置依赖注入和初始化取代扩展依赖注入和初始化
- 用静态工厂方法代替实例工厂方法,避免工厂对象提前被创建
@Configuration public class MyConfig2 implements InitializingBean, ApplicationContextAware { private static final Logger log = LoggerFactory.getLogger(MyConfig2.class); @Override public void afterPropertiesSet() throws Exception { log.debug("初始化"); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { log.debug("注入 ApplicationContext"); } @Bean // beanFactory 后处理器 public BeanFactoryPostProcessor processor2() { return beanFactory -> { log.debug("执行 processor2"); }; } }
public class A06 { private static final Logger log = LoggerFactory.getLogger(A06.class); public static void main(String[] args) { /* 1. Aware 接口用于注入一些与容器相关信息, 例如 a. BeanNameAware 注入 bean 的名字 b. BeanFactoryAware 注入 BeanFactory 容器 c. ApplicationContextAware 注入 ApplicationContext 容器 d. EmbeddedValueResolverAware ${} */ GenericApplicationContext context = new GenericApplicationContext(); // context.registerBean("myConfig1", MyConfig1.class); context.registerBean("myConfig2", MyConfig2.class); context.registerBean(AutowiredAnnotationBeanPostProcessor.class); context.registerBean(CommonAnnotationBeanPostProcessor.class); context.registerBean(ConfigurationClassPostProcessor.class); context.refresh(); // 1. beanFactory 后处理器, 2. 添加 bean 后处理器, 3. 初始化单例 context.close(); } }