欢迎大家关注 github.com/hsfxuebao ,希望对大家有所帮助,要是觉得可以的话麻烦给点一下Star哈
Spring提供了一种机制,让bean在实例化的时候,能够感知(获取)容器中的一些组件,即Aware接口回调的方式。这种机制一般是Spring框架内部使用。
1. 常用Aware接口
Aware | 作用 |
---|---|
BeanFactoryAware | 获取当前BeanFactory,这样可以调用容器的服务 |
BeanClassLoaderAware | 获取类类加载器 |
BeanNameAware | 获取容器中Bean的名称 |
ApplicationContextAware | t同BeanFactory |
MessageSourceAware | 获取MessageSource相关文本信息 |
ApplicationEventPublisherAware | 发布事件 |
ResourceLoaderAware | 获取资源加载器,这样获取外部资源文件 |
EnvironmentAware | 环境信息 |
EmbeddedValueResolverAware | |
ApplicationStartupAware |
2. 测试用例
@Component
public class PersonAware implements ApplicationContextAware, MessageSourceAware {
// @Autowired
ApplicationContext context; //可以要到ioc容器
MessageSource messageSource;
public ApplicationContext getContext() {
return context;
}
public void setContext(ApplicationContext context) {
this.context = context;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
@Override
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}
}
在回调方法上打上debug,就可以看到整个方法的执行时机。
3. 源码分析
3.1 原理
在这些Aware中,底层实现主要分为两种:
-
invokeAwareMethods(beanName, bean);
- BeanNameAware
- BeanClassLoaderAware
- BeanFactoryAware
-
BeanPostProcessor
,bean后置处理器ApplicationContextAwareProcessor
- 剩下的7个都是通过后置处理器实现的
3.2 invokeAwareMethods(beanName, bean);
在创建bean的核心方法initializeBean()
中,创建好bean后,都会先调用invokeAwareMethods(beanName, bean);
,再进行初始化。
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// todo 组件有Aware接口,先Aware; BeanNameAware BeanClassLoaderAware BeanFactoryAware
invokeAwareMethods(beanName, bean);
}
...
return wrappedBean;
}
若这个bean为一个Aware,就去尝试调用一些回调方法。在这个方法中,有三种Aware会在这个方法中被调用:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware。
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
3.3 bean后置处理器ApplicationContextAwareProcessor
其余的Aware是由BeanPostProcessor来实现的,实现类为ApplicationContextAwareProcessor。
在Spring5源码5-Bean生命周期后置处理器,我们已经说过beanPostProcessor的前置处理都是在applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)
中被一一执行。
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//调用postProcessBeforeInitialization
Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
经过一些安全验证,最终会调用invokeAwareInterfaces(bean):
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
bean instanceof ApplicationStartupAware)) {
return bean;
}
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
// todo 执行xxxAware的回调
invokeAwareInterfaces(bean);
}
return bean;
}
逻辑也很简单,判断这个Aware是哪个Aware,就强制转换调用。
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationStartupAware) { // 利用多态的特性调用相关方法注入值
((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
那么,问题来了,ApplicationContextAwareProcessor后置处理器是在什么时候注入到容器中呢?
我们直接看refresh()
中prepareBeanFactory(beanFactory)
,该方法中会设置一些后置处理器等。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 添加一些后置处理器
// 判断当前组件是否实现xxxAware接口,准备一个处理Aware接口的后置处理器
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
...
}
参考文章
Spring5源码注释github地址
Spring源码深度解析(第2版)
spring源码解析
Spring源码深度解析笔记
Spring注解与源码分析
Spring注解驱动开发B站教程