为什么要看ApplicationContextAware呢?
其实ApplicationContextAware只是Spring众多内容中的一小部分,如果只看它,其实对于你了解Spring整体的益处不算很大。对于大多数人而言,只要学会如何使用就足够了。那为什么还要看呢? 不得局部慢慢消化吗,所以先来个相对简单的。
ApplicationContextAware使用方式
去实现ApplicationContextAware接口,实现接口setApplicationContext 可以设置静态属性,这样我们就拿到了IOC的容器(getBean取的是一级缓存里已经创建好的Bean)
@Component
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(@Nullable ApplicationContext applicationContext) throws BeansException {
if(SpringUtil.applicationContext == null) {
SpringUtil.applicationContext = applicationContext;
}
}
/**
* 获取applicationContext
*
* @return
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 通过name获取 Bean
*
* @param name
* @return
*/
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
}
底层源码
调用了重写的setApplicationContext
根据调用的位置,我们简单过一下, 最下面一行的doGetBean已经是在单例方式下创建Bean对象的方法,一般来说do开头的方法都是实际干活的方法,像下图中的doGetBean doCreateBean 。
而initializeBean方法是在Bean 初始化和实例化之后,走传统意义上的Spring生命周期里面核心方法时所调用到的,这里不展开讲,就比如下列的applyBeanPostProcessorsBeforeInitialization方法,这个方法如果不太熟悉,那么postProcessBeforeInitialization这个方法你一定很熟悉,因为这个就是BeanPostProcessor bean的后置处理器的方法。至此 我们已经在方向上定位到了,setApplicationContext对于 自己创建的类的属性赋值,是在Bean的后置处理器上。
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(SpringUtil.applicationContext == null) {
SpringUtil.applicationContext = applicationContext;
}
}
会在initializeBean 在实例化和初始化之后调用, 在后置处理器的前置before方法中触发,会如下触发一系列的后置处理器的前置方法
for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
BeanPostProcessor processor = (BeanPostProcessor)var4.next();
current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
}
我们知道 ,Bean的后置处理器有很多种,不同的类的实现,最终会被所有单例对象去调用到,下列是后置处理器的唯二的方法
- postProcessBeforeInitialization
- postProcessAfterInitialization
后置处理器 ApplicationContextAwareProcessor
实际作为后置处理器的类是:
ApplicationContextAwareProcessor
org/springframework/spring-context/5.2.2.RELEASE/spring-context-5.2.2.RELEASE.jar!/org/springframework/context/support/ApplicationContextAwareProcessor.class
@Nullable
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)) {
return bean;
} else {
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged(() -> {
this.invokeAwareInterfaces(bean);
return null;
}, acc);
} else {
this.invokeAwareInterfaces(bean);
}
return bean;
}
}
可以看到,在后置处理器的前置postProcessBeforeInitialization里,对实例化和初始化完成的对象是有做到过滤的,满足条件才可以使用
bean instanceof ApplicationContextAware
大部分的bean是不会满足上述条件的,所以大部分只是走完判断,这个后置处理器的before方法就结束了。
只有满足代码中的条件 才能触发this.invokeAwareInterfaces(bean) 的核心方法
这里是实现了ApplicationContextAware if条件的最后一个条件,所以继续
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 ApplicationContextAware) {
((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
}
}
这里是核心的调用方法 setApplicationContext,最终调用到了实际的我们的业务方法!
ApplicationContextAwareProcessor的创建
还有一小块疑问,那就是Bean的后置处理器是什么时候创建的呢?继续往下看
class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
private final StringValueResolver embeddedValueResolver;
public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
}
applicationContext是构造器注入的属性,最终我们自己实现类 的setApplicationContext的入参也是从后置处理器赋值的
那什么时候初始化的后置处理器?
根据初始化的位置,我们知道,AbstractApplicationContext.refresh()是我们Spring启动的入口,在prepareBeanFactory的方法中,有下列的内容,会创建后置处理器并且添加到beanFactory中。
this.prepareBeanFactory(beanFactory);
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
这样我们也知道了ApplicationContextAwareProcessor的后置处理器是在这里创建的
注意: 并不是所有的后置处理器都是在这里创建,比如你自己创建的后置处理器,是在refresh方法中的这一步骤调用到的。
this.registerBeanPostProcessors(beanFactory);
好了,ApplicationContextAware底层原理详解这一篇我们就讲完了!
❤❤❤