在项目中大家都知道通过实现ApplicationContextAware接口可以获得ApplicationContext里的所有信息,从而拿到我们想要的Bean。但是对其中的具体过程一直不太明白,找了很多文章大多数也只是说明了怎么用的问题。俗话说前人栽树后人乘凉,找不到栽树的人,只能自己硬着头皮上了。奥利给!
ApplicationContextAware:
public interface ApplicationContextAware extends Aware {
/**
* Set the ApplicationContext that this object runs in.
* Normally this call will be used to initialize the object.
* <p>Invoked after population of normal bean properties but before an init callback such
* as {@link org.springframework.beans.factory.InitializingBean#afterPropertiesSet()}
* or a custom init-method. Invoked after {@link ResourceLoaderAware#setResourceLoader}
*/
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
特意保留了一段注释,就是因为这段注释中给了一点提示。我这个LB英语水平属实有点困难,翻译后大致明白:这个方法是在初始化这个Bean并将属性填充之后调用的。不得不让人想到后置处理器,是不是跟这有关。查阅了一些资料后发现确实如此,既然涉及到Bean的初始化就不得不从AbstractApplicationContext中的refresh方法开始寻找线索。
AbstractApplicationContext:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean(7)
prepareBeanFactory(beanFactory);
从代码注释中不难看出正是在prepareBeanFactory方法中添加了BeanPostProcessor。点进去看看具体都做了什么
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置 BeanFactory 的类加载器,我们知道 BeanFactory 需要加载类,也就需要类加载器,
// 这里设置为加载当前 ApplicationContext 类的类加载器
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 这里我们可以看到向beanFactory添加了ApplicationContextAware处理器
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
先进入到ApplicationContextAwareProcessor看下其实例化过程做了什么:
class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
private final StringValueResolver embeddedValueResolver;
/**
* Create a new ApplicationContextAwareProcessor for the given context.
*/
public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
}
//实例化之前进行的处理,这个暂时不说后面会被回调
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
。。。。。。
}
private void invokeAwareInterfaces(Object bean) {
。。。。。。
}
ApplicationContextAwareProcessor只有一个构造方法,在我们调用addBeanPostProcessor方法实例化时传入了,this。而this此时正是当前spring的当前环境上下文。其余等下面回调时再回来分析。继续回到addBeanPostProcessor方法。
代码中清晰的看到向ConfigurableListableBeanFactory 中添加了后置处理器,可是点进ConfigurableListableBeanFactory 接口中发现并没有对addBeanPostProcessor进行实现。没得办法只能到它的儿子DefaultListableBeanFactory中找这个一定有,汗!WTFK和想象中不太一样
既然本类没有那只剩最后一种可能从它的父类AbstractAutowireCapableBeanFactory继承过来了。果真最后在他爷爷AbstractBeanFactory中找到了实现。继续看看这个方法到底做了什么:
/** BeanPostProcessors to apply in createBean. */
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
// Remove from old position, if any
this.beanPostProcessors.remove(beanPostProcessor);
// Track whether it is instantiation/destruction aware
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true;
}
// Add to end of list
this.beanPostProcessors.add(beanPostProcessor);
}
前面学后面忘就很难受,第一时间只能想到一个写时复制这里面先不细究,我们可以看到这里创建了一个线程安全的list容器来存放我们的后置处理器。到这里前面做了什么我们基本明白了下面我们就需要到调用后置处理器的地方看看具体是怎么回事,中间Bean的实例化过程太过复杂不细说了,在doCreateBean中执行完populateBean进行属性设值后会执行AbstractAutowireCapableBeanFactory#initializeBean方法在这个方法中进行后置处理:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 如果 bean 实现了 BeanNameAware、BeanClassLoaderAware 或 BeanFactoryAware 接口,回调
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 调用我们bean的后置处理器的PostProcessorsAfterInitialization方法
// BeanPostProcessor 的 postProcessBeforeInitialization 回调
// 第七次调用后置处理器,处理AOP
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
。。。。。。
}
可以看到在initializeBean中执行了
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
public List<BeanPostProcessor> getBeanPostProcessors() {
return this.beanPostProcessors;
}
/** BeanPostProcessors to apply in createBean. */
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
拿到我们之前的CopyOnWriteArrayList容器,将前面放入的applicationContext取出来执行postProcessBeforeInitialization方法,
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// true取反false继续向下执行
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
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 {
invokeAwareInterfaces(bean);
}
return bean;
}
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的接口,spring都将调用其setApplicationContext,将applicationContext注入到当前bean对象。
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
到此整个流程就完全下来了。。。真的九曲十八弯,简单总结下大体流程。
总结:
1.在初始化Bean时, prepareBeanFactory(ConfigurableListableBeanFactory beanFactory)首先将当前ApplicationContex注入到App lication ContextAwareProcessor内置的后置处理器中
2. 执行AbstractBeanFactory#addBeanPostProcessor(BeanPostProcessor beanPostProcessor)将当上述Application ContextAwareProce s sor对象放入CopyOnWriteArrayList容器,这个容器里存放着后置处理器在后面实例化时回调。
3. 在Bean属性注入完成后,initializeBean方法中进行后置处理AbstractAutowireCapableBeanFactory #applyBeanPost ProcessorsBeforeIn itialization(wrappedBean, beanName)
4.调用父类AbstractBeanFactory#getBeanPostProcessors()拿到存放后置处理器对象的CopyOnWriteArrayList容器,在applyBean Post Proc essorsAfterInitialization中遍历执行postProcessAfterInitialization(result, beanName),此处进行回调
5.ApplicationContextAwareProcessor#invokeAwareInterfaces,调用setApplicationContext将从list中取出的ApplicationContext注入当前Bean.这样Bean就有了ApplicationContext属性。
到这里一切就清晰了,为什么实现ApplicationContextAware就可以拿它所在的Spring容器所有的Bean,因为在实例化过程中就已经将ApplicationContext注入倒了当前Bean