question:Aware接口和InitializingBean接口的作用都可以用例如@Autowired @PostConstruct注解来实现,那么其相比较于注解的实现,优势是什么呢?
早期的Spring中并不存在注解开发,注解开发是在后期的Spring中引入,并广泛应用的
注解只是一个标记,其不起任何作用,起作用的是对注解解析的类和方法,在Spring中,对各类注解解析的类主要是xxBeanFactoryPostProcessor,xxBeanPostProcessor类
也就是说,如果对注解解析的扩展功能如果失效了,那么注解自然是起不到作用了
首先,从例1,我们可以直观的看到注解生效的原因
从例2,我们可以看到其扩展功能失效的一个场景
参考视频:bilibili
@Component
public class MyBean implements ApplicationContextAware, InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("当前bean " + this + "初始化");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("当前bean " + this + " 容器是:" + applicationContext);
}
@Autowired
public void addApplicationContext(ApplicationContext applicationContext){
System.out.println("当前bean " + this + " 使用@Autowired 容器是:" + applicationContext);
}
@PostConstruct
public void init(){
System.out.println("当前bean " + this + " 使用@PostConstruct 初始化");
}
}
public class InvalidAutowiredApplication {
public static void main(String[] args) {
// GenericApplicationContext 是一个【干净】的容器,其不会自动添加默认的 BeanPostProcessor
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("myBean", MyBean.class);
// 你依次尝试注册BeanPostProcessor 和不注册,你会得到什么输出
context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
context.registerBean(CommonAnnotationBeanPostProcessor.class);
context.registerBean(ConfigurationClassPostProcessor.class);
context.refresh();
context.close();
}
}
例2:
@Configuration
public class MyConfig {
@Autowired
public void setApplicationContext(ApplicationContext applicationContext){
System.out.println("当前bean " + this + " 使用@Autowired 容器是:" + applicationContext);
}
@PostConstruct
public void init(){
System.out.println("当前bean " + this + " 使用@PostConstruct");
}
@Bean
public BeanFactoryPostProcessor processor(){
return beanFactory ->{
System.out.println("当前bean " + this + " 使用@Bean BeanFactoryPostProcessor");
};
}
}
// 你会观察到,其实你注入了相关的BeanPostProcessor,MyConfig中的@Autowired 和 @PostConstruct也不会生效
public class InvalidAutowiredApplication {
public static void main(String[] args) {
// GenericApplicationContext 是一个【干净】的容器,其不会自动添加默认的 BeanPostProcessor
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();
}
}
解析:
对于context.refresh(),其主要按以下顺序执行了三件事
-执行BeanFactory后置处理器
-添加Bean后置处理器
-创建和初始化单例
当 Java 配置类中定义了 BeanFactoryPostProcessor 时,如果要创建配置类中的 BeanFactoryPostProcessor 就必须 提前 创建和初始化 Java 配置类。
在创建和初始化 Java 配置类时,由于 BeanPostProcessor 还未准备好,无法解析配置类中的 @Autowired 等注解,导致 @Autowired 等注解失效: