Spring 源码学习系列ApplicationContextAware#setApplicationContext 方法的调用时机
Posted 明明如月学长
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 源码学习系列ApplicationContextAware#setApplicationContext 方法的调用时机相关的知识,希望对你有一定的参考价值。
一、背景
在实际业务开发中,经常借助 ApplicationContextAware 获取 ApplicationContext 然后构造业务枚举到处理 Bean 的策略模式映射。
@Service
public class DemoService implements ApplicationContextAware
private Map<String, List<Handler>> type2HandlersMap;
public void test()
String type ="Vip";
for(Handler handler : type2HandlersMap.get(type))
handler.someThing();;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
Map<String, Handler> beansOfType = applicationContext.getBeansOfType(Handler.class);
beansOfType.forEach((k,v)->
type2HandlersMap = new HashMap<>();
String type =v.getType();
type2HandlersMap.putIfAbsent(type,new ArrayList<>());
type2HandlersMap.get(type).add(v);
);
那么,不知道大家是否都了解 setApplicationContext
的调用时机呢?
本文结合一个简单示例分析一下,这里强烈建议大家自己动手调试一下,印象会更加深刻。
二、案例分析
2.1 案例构造
定义 AwaredTestBean
实现 ApplicationContextAware
接口。
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.util.stream.Stream;
@Component
public class AwaredTestBean implements ApplicationContextAware
private ApplicationContext ctx;
public void printBeanNames()
Stream.of(ctx.getBeanDefinitionNames()).forEach(System.out::println);
@Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException
// 此处断点
this.ctx = ctx;
基于注解编写 Configuration
:
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("org.example.aware.bean")
public class AwareConfiguration
构建 AnnotationConfigApplicationContext
进行测试:
import org.example.aware.bean.AwaredTestBean;
import org.example.aware.config.AwareConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class AwareApplication
public static void main(String[] args) throws Exception
ApplicationContext ctx = new AnnotationConfigApplicationContext(AwareConfiguration.class);
AwaredTestBean atBean = ctx.getBean(AwaredTestBean.class);
atBean.printBeanNames();
源码学习的方法有很多,可以参考我的 《如何高效学习和阅读源码?》、《如何读源码更有效–直播》 等文章。
文章提到 “以设计者的角度学源码” 和 “先猜想后验证的方法”,因此我们不难猜测,ApplicationContextAware
方法的调用时机 应该是 ApplicationContext
已经准备完毕的时候。
2.2 从外到内
接下来直接断点调试,看调用栈,分析分析。
从入口往下梳理:
AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(java.lang.Class<?>...)
public AnnotationConfigApplicationContext(Class<?>... componentClasses)
this();
register(componentClasses);
refresh();
这里的 refresh 方法是 AbstractApplicationContext#refresh
方法,是 IOC 容器启动时最核心的方法:
@Override
public void refresh() throws BeansException, IllegalStateException
synchronized (this.startupShutdownMonitor)
// Prepare this context for refreshing.
//1 初始化前的准备
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//2 获取 BeanFactory,加载所有 bean 的定义信息(未实例化)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 3 BeanFactory 的预处理配置
prepareBeanFactory(beanFactory);
try
// Allows post-processing of the bean factory in context subclasses.
// 4. 准备 BeanFactory 完成后进行的后置处理
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 5. 执行 BeanFactory 创建后的后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 6. 注册 Bean 的后置处理器
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 7. 初始化MessageSource
initMessageSource();
// Initialize event multicaster for this context.
// 8. 初始化事件派发器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 9. 子类的多态 onRefresh
onRefresh();
// Check for listener beans and register them.
// 10. 监听器检查和注册
registerListeners();
// ------- BeanFactory已创建完成 --------
// Instantiate all remaining (non-lazy-init) singletons.
// 11. 初始化所有剩下的单例Bean(非懒加载的)
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 12. 完成容器的创建工作(发布相应的事件)
finishRefresh();
catch (BeansException ex)
if (logger.isWarnEnabled())
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
// Destroy already created singletons to avoid dangling resources.
// 销毁已经创建的单例避免浪费资源
destroyBeans();
// Reset 'active' flag.
// 重置 active 标记
cancelRefresh(ex);
// Propagate exception to caller.
// 异常抛给调用方
throw ex;
finally
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
//13 清理缓存
resetCommonCaches();
在 “11. 初始化所有剩下的单例Bean(非懒加载的)” 这个环节注入的 ApplicationContext, 此时 BeanFactory 已经初始化完成。
AbstractApplicationContext#finishBeanFactoryInitialization
执行到预初始化单例 bean DefaultListableBeanFactory#preInstantiateSingletons
执行 Bean 的创建 AbstractBeanFactory#getBean(java.lang.String)
创建单例 Bean DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
实际初始化 Bean 实例:
/**
* Actually create the specified bean. Pre-creation processing has already happened
* at this point, e.g. checking @code postProcessBeforeInstantiation callbacks.
* <p>Differentiates between default bean instantiation, use of a
* factory method, and autowiring a constructor.
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a new instance of the bean
* @throws BeanCreationException if the bean could not be created
* @see #instantiateBean
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
*/
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton())
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
if (instanceWrapper == null)
instanceWrapper = createBeanInstance(beanName, mbd, args);
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class)
mbd.resolvedTargetType = beanType;
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock)
if (!mbd.postProcessed)
try
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
catch (Throwable ex)
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
mbd.postProcessed = true;
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure)
if (logger.isTraceEnabled())
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
// Initialize the bean instance.
Object exposedObject = bean;
try
// bean 的属性填充
populateBean(beanName, mbd, instanceWrapper);
//【重点】执行到这里!!-> 初始化 Bean 实例
exposedObject = initializeBean(beanName, exposedObject, mbd);
catch (Throwable ex)
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName()))
throw (BeanCreationException) ex;
else
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
// 省略部分代码
// Register bean as disposable.
try
registerDisposableBeanIfNecessary(beanName, bean, mbd);
catch (BeanDefinitionValidationException ex)
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
return exposedObject;
获取并执行 BeanPostProcessor AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
@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;
执行 ApplicationContextAwareProcessor#postProcessBeforeInitialization
@Override
@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;
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
//【重点】 调用 Aware 接口
invokeAwareInterfaces(bean);
return bean;
调用Bean 实现的 Aware 接口 ApplicationContextAwareProcessor#invokeAwareInterfaces
源码:
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);
从这里可以看到,会判断当前 bean 是否实现了这些 Aware 接口,如果实现了这些接口,那么将 applicationContext 自身 或者 通过 applicationContext 获取所需的参数类型传递过去。
这里顺便说个调试技巧,可以 “Reset Frame” 或者 “Drop Frame” 回退到上一层,不断回退。
2.3 从内到外
那么问题又来了,既然执行的是 ApplicationContextAwareProcessor
,那么它又是在哪里创建的呢?
研究之前我们很容易猜出,必定是前面的某个环节构造了这个 ApplicationContextAwareProcessor,到底是哪个环节呢?
我们继续分析:
跟进去:
public List<BeanPostProcessor> getBeanPostProcessors()
return this.beanPostProcessors;
AbstractBeanFactory#addBeanPostProcessor
:
@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);
AbstractApplicationContext#prepareBeanFactory
:
/**
* Configure the factory's standard context characteristics,
* such as the context's ClassLoader and post-processors.
* @param beanFactory the BeanFactory to configure
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory)
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactorySpring读源码系列之AOP--03---aop底层基础类学习
Spring 源码学习系列BeanNameAware#setBeanName 方法的调用时机
Spring读源码系列之AOP--05---aop常用工具类学习
Spring源码深度解析学习系列注册解析的BeanDefinition
Spring 源码学习系列ApplicationContextAware#setApplicationContext 方法的调用时机
Spring 源码学习系列ApplicationContextAware#setApplicationContext 方法的调用时机