1. Aware 接口
Aware 接口提供了一种[内置]的注入手段,可以注入BeanFactory, ApplicationContext。内置的注入和初始化不受扩展功能的影响,总会被执行,因此Spring 框架的内部类常使用它们。
InitializingBean 接口提供了一种[内置]的初始化手段。
Aware的作用就是注入与容器相关的信息,例如:
- BeanNameAware: 注入bean的名字
- BeanFactoryAware: 注入BeanFactory容器
- ApplicationContextAware: 注入ApplicationContext 容器
- EmbededValueResolverAware: 注入解析器,解析${}
当某一个Bean实现了Aware的接口,就会在Bean的初始化之前,回调实现的方法setBean():
public class MyBean implements BeanNameAware, ApplicationContextAware, InitializingBean {
@Override
public void setBeanName(String name) {
System.out.println("当前bean"+this+"名字叫:"+name);
}
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
System.out.println("当前bean" +this+"容器是:"+context);
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("当前bean"+this+"执行初始化操作");
}
}
编写主方法运行:
public class A06ApplicationTest {
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("myBean",MyBean.class);
context.refresh();
context.close();
}
}
当前beancom.cherry.a06.MyBean@4d50efb8名字叫:myBean
当前beancom.cherry.a06.MyBean@4d50efb8容器是:org.springframework.context.support.GenericApplicationContext@6debcae2, started on Mon Jun 10 08:06:01 CST 2024
当前beancom.cherry.a06.MyBean@4d50efb8执行初始化操作
明明@Autowired和 @PostConstruct注解可以实现注入bean和初始化bean,为什么还需要实现BeanNameAware, ApplicationContextAware, InitializingBean接口来实现注入和初始化的功能?这是因为:
- @Autowired等注解解析要用到@Bean后处理器,属于扩展功能
- 而Aware接口属于内置的功能,即使不加任何功能,Spring也能识别
- 在某些情况下,扩展功能可能会失效,而内置功能并不会失效
2. @Autowired 失效分析
首先编写一个配置类:
@Configuration
public class MyConfig {
@Autowired
public void setApplicationContext(ApplicationContext context){
System.out.println("注入 ApplicationContext");
}
@PostConstruct
public void init(){
System.out.println("初始化");
}
}
编写主方法:
public class A06ApplicationTest {
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("myConfig",MyConfig.class);
context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
context.registerBean(CommonAnnotationBeanPostProcessor.class);
context.registerBean(ConfigurationClassPostProcessor.class);
context.refresh();
context.close();
}
}
运行:
注入 ApplicationContext
初始化
紧接着在MyConfig中添加一个Bean工厂后处理器:
// 添加一个Bean工厂后处理器
@Bean
public BeanFactoryPostProcessor processor1(){
return beanFactory -> {
System.out.println("执行 processor1");
};
}
运行:
08:52:42.280 [main] INFO org.springframework.context.annotation.ConfigurationClassEnhancer -- @Bean method MyConfig.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.
执行 processor1
我们发现Bean的注入和初始化功能都失效了。
这里首先了解一下context.refresh()方法的执行流程:
- 首先找到容器中所有BeanFactoryPostProcessor来执行
- 添加Bean的后处理器
- 执行初始化所有单例
首先看一下Bean单例创建流程:
Java配置类包含BeanFactoryPostProcessor的情况,因此在创建BeanFactoryPostProcessor的前提是要把配置类创建好,才能调用Bean工厂方法,才能调用BeanFactoryPostProcessor。配置类本身就是一个单例对象,而此时的BeanFactoryPostProcessor还未创建好,这就导致了@Autowired注解失效。变成了下面的执行流程:
解决方法就是直接在配置类中使用Spring内置的Bean注入和初始化方法:
如下面的配置类:
@Configuration
public class MyConfig2 implements InitializingBean, ApplicationContextAware {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("初始化");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("注入 ApplicationContext");
}
@Bean
public BeanFactoryPostProcessor processor2(){
return beanFactory -> {
System.out.println("执行 processor2");
};
}
}
修改main方法并运行:
context.registerBean("myConfig2",MyConfig2.class);
注入 ApplicationContext
初始化
13:05:55.772 [main] INFO org.springframework.context.annotation.ConfigurationClassEnhancer -- @Bean method MyConfig2.processor2 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.
执行 processor2
标签:初始化,Autowired,class,Bean,context,失效,ApplicationContext,注解,public
From: https://www.cnblogs.com/lilyflower/p/18240616