【探索Spring底层】Aware 接口及 InitializingBean 接口
1. Aware接口的作用
Aware接口是Spring内部提供的一些注入手段
所谓内部就是不用注入一些Bean后处理器或BeanFactory就能实现某些功能
- BeanNameAware :用来注入bean的名字
- BeanFactoryAware : 用来注入BeanFactory 容器
- ApplicationContextAware :用来 注入 ApplicationContext 容器
- EmbeddedValueResolverAware :用来解析${}
这里准备一个类实现BeanNameAware 、BeanFactoryAware 和ApplicationContextAware 三个接口
- setBeanName:注入bean名字的时候被调用
- setApplicationContext:注入容器的时候被调用
- afterPropertiesSet:bean初始化的时候被调用
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 + " 初始化");
}
}
public class A06 {
private static final Logger log = LoggerFactory.getLogger(A06.class);
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("myBean", MyBean.class);
context.refresh();
context.close();
}
}
运行程序
那么,要实现这种功能使用@Autowired也能实现呀,那Aware存在的意义是什么呢?
确实如此,bean的初始化可以使用@PostConstruct实现,注入可以使用@Autowired
就像下面这样,将下面的代码添加到MyBean中,运行程序会发现,这两个方法并没有被调用
@Autowired
public void aaa(ApplicationContext applicationContext) {
log.debug("当前bean " + this + " 使用@Autowired 容器是:" + applicationContext);
}
@PostConstruct
public void init() {
log.debug("当前bean " + this + " 使用@PostConstruct 初始化");
}
这是因为@Autowired 和@PostConstruct的解析需要用到 bean 后处理器, 属于扩展功能
而 Aware 接口属于内置功能, 不加任何扩展, Spring 就能识别某些情况下, 扩展功能会失效, 而内置功能不会失效
2. 模拟扩展功能失效的场景与分析
当在Java配置类添加了bean工厂后处理器后,传统接口方式的注入和初始化仍然成功,而 @Autowired 和 @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");
};
}
}
运行程序,可以发现@Autowired 与 @PostConstruct都失效了
在分析@Autowired注解失效原因之前,需要了解初始化容器的步骤
- 首先,在容器中找到所有的BeanFacotry后处理器来执行
- 接着,添加Bean后处理器
- 最后,初始化单例
下面是容器初始化的流程图
但是,Java配置类(上面的MyConfig1就是Java配置类)包含BeanPostProcessor(Bean工厂后处理器)的话,创建其中的 BeanFactoryPostProcessor 必须提前创建 Java 配置类,而此时的 BeanPostProcessor 还未准备好,导致 @Autowired 等注解失效,Java配置类的创建是使用内置的Aware创建
@Configurationpublic 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"); }; }}
使用Aware和InitializingBean的话,就不会出现@Bean工厂失效的情况了
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/94991.html