一、背景
在实际业务开发中,经常借助 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
的调用时机呢?
本文结合一个简单示例分析一下,这里强烈建议大家自己动手调试一下,印象会更加深刻。
二、案例分析
定义 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();
}
}
源码学习的方法有很多,可以参考我的 《如何高效学习和阅读源码?》、《如何读源码更有效--直播》 等文章。
本文直接断点调试,看调用栈。
从入口往下梳理: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” 回退到上一层,不断回退。
三、总结
纸上得来终觉浅,觉知此事需躬行。
希望大家可以参考本文的简单 Demo ,亲自动手调试,理解才能更深刻。
学习贵能举一反三。大家能够结合本节所学的方法自行分析 BeanNameAware
方法的调用时机呢?
本文并没有对 IOC容器启动时的最核心方法 AbstractApplicationContext
中的 refresh
进行彻底的剖析,只是结合一个具体案例从某个切面去学习其中的某个环节,大家可以通过更多案例讲整个 refresh
核心方法都串起来,理解会越来越深入。
创作不易,如果本文对你有帮助,欢迎点赞、收藏加关注,你的支持和鼓励,是我创作的最大动力。