1、Aware 接口
Aware 接口用于注入一些与容器相关信息,例如:
- BeanNameAware 注入 bean 的名字
- BeanFactoryAware 注入 BeanFactory 容器
- ApplicationContextAware 注入 ApplicationContext 容器
- EmbeddedValueResolverAware ${}
主启动类
public class A06Application {
private static final Logger log = LoggerFactory.getLogger(A06Application.class);
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("mybean", MyBean.class);
context.refresh();
context.close();
}
}
MyBean类
InitializingBean 接口提供了一种【内置】的初始化手段
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 + " 初始化");
}
}
结果:
[main] com.itheima.a06.MyBean - 当前bean com.itheima.a06.MyBean@43a0cee9 名字叫:mybean
[main] com.itheima.a06.MyBean - 当前bean com.itheima.a06.MyBean@43a0cee9 容器是:org.springframework.context.support.GenericApplicationContext@97e1986, started on Thu Nov 03 13:55:31 CST 2022
[main] com.itheima.a06.MyBean - 当前bean com.itheima.a06.MyBean@43a0cee9 初始化
为什么要使用 Aware 接口?
简单地说:
- @Autowired 的解析需要用到 bean 后处理器,属于扩展功能
- 而 Aware 接口属于内置功能,不加任何扩展,Spring 就能识别
- 某些情况下, 扩展功能会失效, 而内置功能不会失效
例如下面这个例子:你会发现用 Aware 注入 ApplicationContext 成功,而 @Autowired 注入 ApplicationContext 失败要想生效就得加处理器。
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 初始化");
}
}
结果: @Autowired 和 @PostConstruct 失效
[main] com.itheima.a06.MyBean - 当前bean com.itheima.a06.MyBean@43a0cee9 名字叫:mybean
[main] com.itheima.a06.MyBean - 当前bean com.itheima.a06.MyBean@43a0cee9 容器是:org.springframework.context.support.GenericApplicationContext@97e1986, started on Thu Nov 03 13:55:31 CST 2022
[main] com.itheima.a06.MyBean - 当前bean com.itheima.a06.MyBean@43a0cee9 初始化
如果想让@Autowire,和@PostConstruct生效,就得添加后处理器
context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
context.registerBean(CommonAnnotationBeanPostProcessor.class);
??对比:
2、配置类 @Autowired 失效分析
配置类MyConfig1
@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");
};
}
}
主启动类
public class A06Application {
private static final Logger log = LoggerFactory.getLogger(A06Application.class);
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("myConfig1", MyConfig1.class);
context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
context.registerBean(CommonAnnotationBeanPostProcessor.class);
context.registerBean(ConfigurationClassPostProcessor.class);
//执行顺序: 1. beanFactory 后处理器, 2. 添加 bean 后处理器, 3. 初始化单例
context.refresh();
context.close();
}
}
?结果:@Autowired,@PostConstruct注解失效
[main] com.itheima.a06.MyConfig1 - 执行 processor1
Java 配置类不包含 BeanFactoryPostProce

Java 配置类包含 BeanFactoryPostProcessor 的情况,因此要创建其中的 BeanFactoryPostProcessor 必须提前创建 Java 配置类,而此时的 BeanPostProcessor 还未准备好,导致 @Autowired 等注解失效

解决办法
@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 A06Application {
private static final Logger log = LoggerFactory.getLogger(A06Application.class);
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("myConfig2", MyConfig2.class);
context.registerBean(ConfigurationClassPostProcessor.class);
context.refresh();
context.close();
}
}
结果:
[main] com.itheima.a06.MyConfig2 - 注入 ApplicationContext
[main] com.itheima.a06.MyConfig2 - 初始化
[main] com.itheima.a06.MyConfig2 - 执行 processor2
|