再某些情况下,我们正确加入了后处理器,任然会再一些情况下会存在注解失效,这里我们就以一个例子来梳理一下原因
失效例子代码
A06(注意,注册的bean换为了MyConfig1.claas)
package com.itheima.a06;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
/*
Aware 接口及 InitializingBean 接口
*/
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(AutowiredAnnotationBeanPostProcessor.class);
context.registerBean(CommonAnnotationBeanPostProcessor.class);
context.registerBean(ConfigurationClassPostProcessor.class);
context.refresh(); // 1. beanFactory 后处理器, 2. 添加 bean 后处理器, 3. 初始化单例
context.close();
/*
}
}
MyConfig1
package com.itheima.a06;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
@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");
}
}
运行结果发现上面两个注解没起作用,只有最后的Bean执行了(问题就处在MyConfig1的最后那个Bean,可以自行注释之后运行一下查看结果,会发现可以正常运行)
其实不光是@Autowired 会失效,一些有关扩展的配置类注解都会失效,下面我们解释一下,为什么我们加上了自己的BeanFactory后处理器会导致@Autowired 等注解失效
图解
Java 配置类不包含 BeanFactoryPostProcessor 的情况
Java 配置类包含 BeanFactoryPostProcessor 的情况,因此要创建其中的 BeanFactoryPostProcessor 必须提前创建 Java 配置类,而此时的 BeanPostProcessor 还未准备好,导致 @Autowired 等注解失效
也就是说,BeanPostProcessor 得再创建实例初始化之前注册、执行,否则扩展类的注解功能就会由于后处理器还没准备好处理不了注解而失效。
注意
解决方法:
- 用内置依赖注入和初始化取代扩展依赖注入和初始化
- 用静态工厂方法代替实例工厂方法,避免工厂对象提前被创建
下面是用内置依赖注入和初始化取代扩展依赖注入和初始化:
收获
- Aware 接口提供了一种【内置】 的注入手段, 可以注入 BeanFactory, ApplicationContext
- InitializingBean 接口提供了一种【内置】的初始化手段
- 内置的注入和初始化不受扩展功能的影响, 总会被执行, 因此 Spring 框架内部的类常用它们