概述
相比大家在看Spring的源码看到很多实现了Aware接口的类,比如实现了BeanNameAware, BeanFactoryAware等。那这一些列的Aware接口用什么作用呢?他们又是在什么时候调用的呢?一切答案将在本篇文章中为大家揭晓。
Aware接口介绍
/*** A marker superinterface indicating that a bean is eligible to be notified by the* Spring container of a particular framework object through a callback-style method.* The actual method signature is determined by individual subinterfaces but should* typically consist of just one void-returning method that accepts a single argument.** <p>Note that merely implementing {@link Aware} provides no default functionality.* Rather, processing must be done explicitly, for example in a* {@link org.springframework.beans.factory.config.BeanPostProcessor}.* Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor}* for an example of processing specific {@code *Aware} interface callbacks.** @author Chris Beams* @author Juergen Hoeller* @since 3.1*/public interface Aware {}
上面是Aware接口的源码定义,我们先来看下他的注释,Spring的注释还是写的非常不错的,我们翻译下:
Aware 接口是一个具有标识作用的超级接口,指示 bean 是具有被 Spring 容器通知的能力,通知的方式是采用回调的方式。Aware 接口是一个空接口,具体的实现由各个子接口决定,且该接口通常只包含一个单个参数并且返回值为void的方法。可以理解就是 set 方法。该方法的命名方式为 set + 去掉接口名中的 Aware 后缀,即 XxxAware 接口,则方法定义为 setXxx(),例如 BeanNameAware(setBeanName),ApplicationContextAware(setApplicationContext)。注意,仅实现Aware接口,不会提供任何默认功能,需要明确的指定实现哪个子接口。
通俗的来说,Aware翻译过来的意思是有感知的,察觉的,如果类上实现了该接口,表明对什么有感知,比如BeanNameAware, 表示知道了自己的Bean Name。
作用
为什么要有个Aware接口?
因为我们在实际的开发过程中,有些Bean可能需要用到Spring容器本身的功能资源,所以Spring容器中的Bean此时就要意识到Spring容器的存在才能调用Spring所提供的资源。我们通过Spring提供的一系列接口Spring Aware来实现具体的功能。
内置的Aware
我们可以看到Spring内置了很多的Aware。
| 名称 | 用途 | 所属容器 | 回调点 |
|---|---|---|---|
| BeanNameAware | 获取bean名称 | BeanFactory | Bean后处理器的BeforeInitialization方法之前 |
| BeanClassLoaderAware | 获取bean的类加载器 | BeanFactory | Bean后处理器的BeforeInitialization方法之前 |
| BeanFactoryAware | 获取bean工厂(建议用下面的ApplicationContextAware) | BeanFactory | Bean后处理器的BeforeInitialization方法之前 |
| EnvironmentAware | 获取环境相关信息,如属性、配置信息等 | ApplicationContext | Bean后处理器的BeforeInitialization方法中 |
| EmbeddedValueResolverAware | 获取值解析器 | ApplicationContext | Bean后处理器的BeforeInitialization方法中 |
| ResourceLoaderAware | 获取资源加载器 | ApplicationContext | Bean后处理器的BeforeInitialization方法中 |
| ApplicationEventPublisherAware | 获取事件广播器,发布事件使用 | ApplicationContext | Bean后处理器的BeforeInitialization方法中 |
| MessageSourceAware | 获取消息资源 | ApplicationContext | Bean后处理器的BeforeInitialization方法中 |
| ApplicationContextAware | 获取ApplicationContext | ApplicationContext | Bean后处理器的BeforeInitialization方法中 |
实践案例
定义bean实现对应的aware接口
@Data@Slf4j@ToString@Accessors(chain = true)public class BeanLifeCycle implements InitializingBean, BeanNameAware, BeanFactoryAware, EnvironmentAware, ApplicationContextAware {@Value("${prop:hello}")private String prop ;private String beanName;private BeanFactory beanFactory;private ApplicationContext applicationContext;private Environment environment;public BeanLifeCycle() {log.info("#################BeanLifeCycle 实例化");}public void init() {log.info("#################BeanLifeCycle 调用init-mthod 初始化");}public void destroy() {log.info("#################BeanLifeCycle 销毁");}@Overridepublic void afterPropertiesSet() throws Exception {log.info("#################BeanLifeCycle 调用afterPropertiesSet方法, 查看属性值prop:[{}],已经被赋值", prop);log.info("#################BeanLifeCycle 调用afterPropertiesSet 初始化");}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {log.info("@@@@@@@@@@@@@@@@@@ beanFactory: [{}]", beanFactory);}@Overridepublic void setBeanName(String beanName) {log.info("@@@@@@@@@@@@@@@@@@ beanName: [{}]", beanName);this.beanName = beanName;}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {log.info("@@@@@@@@@@@@@@@@@@ applicationContext: [{}]", applicationContext);this.applicationContext = applicationContext;}@Overridepublic void setEnvironment(Environment environment) {log.info("@@@@@@@@@@@@@@@@@@ environment: [{}]", environment);this.environment = environment;}}
执行结果
源码解析
现在我们从源码角度分析下aware接口的执行时机。
通过debug追踪到执行是在创建bean的初始化阶段。
AbstractAutowireCapableBeanFactory的doCreateBean()是创建bean的入口。AbstractAutowireCapableBeanFactory的initializeBean()方法是bean的初始化入口。
我们重点关注Bean的初始化。
可以看到有两个点回执行Aware接口,我们先看下第一个方法invokeAwareMethods()。
很明显,上面标记的1,2,3分别执行BeanNameAware、BeanClassLoaderAware、BeanFactoryAware 3个接口的方法。�ApplicationContextAwareProcessor实现了BeanPostProcessor, 是Spring内置的的一个处理器,在Bean初始化化前后执行,它也是执行Aware接口的另外一个入口。

ok, 到这里我们明白了这个Aware接口的执行时机。
那ApplicationContextAwareProcessor这个处理器本身是什么时候注入到容器中的呢?
是在创建容器的时候AbstractApplicationContext#refresh()方法中调用了prepareBeanFactory方法。
总结
Bean创建时,会调用Aware接口,设置容器对应的资源属性,扩展Bean的能力。
BeanFactory初始化容器方式
在加载bean的步骤中,创建bean之后,调用bean后处理器之前,回调表格中的3个Aware接口。
ApplicationContext初始化容器方式
- 调用BeanFactory方式的3个Aware接口;
- 在加载bean之前创建一个
ApplicationContextAwareProcessor,注册在AbstractBeanFactory的beanPostProcessors属性中。然后在加载bean的步骤中,调用bean后处理器的postProcessBeforeInitialization方法过程中,回调表格中的6个Aware接口。
参考
https://blog.csdn.net/Bronze5/article/details/105902892
https://juejin.cn/post/6844903938131509256


