概述
相比大家在看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;
}
}
执行结果
源码解析
现在我们从源码角度分析下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