概述
相比大家在看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 销毁"); } @Override public void afterPropertiesSet() throws Exception { log.info("#################BeanLifeCycle 调用afterPropertiesSet方法, 查看属性值prop:[{}],已经被赋值", prop); log.info("#################BeanLifeCycle 调用afterPropertiesSet 初始化"); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { log.info("@@@@@@@@@@@@@@@@@@ beanFactory: [{}]", beanFactory); } @Override public void setBeanName(String beanName) { log.info("@@@@@@@@@@@@@@@@@@ beanName: [{}]", beanName); this.beanName = beanName; } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { log.info("@@@@@@@@@@@@@@@@@@ applicationContext: [{}]", applicationContext); this.applicationContext = applicationContext; } @Override public void setEnvironment(Environment environment) { log.info("@@@@@@@@@@@@@@@@@@ environment: [{}]", environment); this.environment = environment; } }
- 执行结果
执行结果中输出了awre接口执行的内容。
源码解析
现在我们从源码角度分析下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接口。