工欲善其事,必先利其器。
—— 《论语·卫灵公》
本文将开始介绍refresh()方法。
public AnnotationConfigApplicationContext(Class>... annotatedClasses) {
this();
register(annotatedClasses);
//本节分析的步骤
refresh();
}
refresh()方法去掉catch块后的代码如下:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 为刷新容器前做准备,没什么干货,略过。
prepareRefresh();
// 简单理解为获得bean工厂DefaultListableBeanFactory对象即可。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 为bean工厂加装一些设备,使其在后续繁杂的bean制造过程中能游刃有余
prepareBeanFactory(beanFactory);
try {
// 空壳方法,为以后Spring扩展预留,略过
postProcessBeanFactory(beanFactory);
// 对BeanFactoryPostProcessor的注册和回调方法执行
invokeBeanFactoryPostProcessors(beanFactory);
// 注册bean的后置处理器,使得bean工厂可以干预bean的实例化过程
registerBeanPostProcessors(beanFactory);
// 国际化(略过)
initMessageSource();
// 初始化Application事件的广播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// 注册事件监听器
registerListeners();
// 完成non-lazy bean的实例化
finishBeanFactoryInitialization(beanFactory);
// 发布事件和完成扫尾工作
finishRefresh();
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
前面1-2步很简单,我们直接从第3步prepareBeanFactory开始分析。
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
上述过程中,StandardBeanExpressionResolver对象用于解析形如 #{...}的这种Spring表达式语言SpEL。ResourceEditorRegistrar用于注册用户自定义的PropertyEditor实现类,PropertyEditor实现类用于将外部设置值转换为bean的属性值。
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
手动添加一个ApplicationContextAwareProcessor的实例化对象到bean后置处理器链表List
org.springframework.context.EnvironmentAware org.springframework.context.EmbeddedValueResolverAware org.springframework.context.ResourceLoaderAware org.springframework.context.ApplicationEventPublisherAware org.springframework.context.MessageSourceAware org.springframework.context.ApplicationContextAware
随后通过ignoreDependencyInterface(xxx.class)方法忽略给定接口的自动装配功能。官方注释是
忽略给定依赖项接口的自动装配功能。application context通常使用它来注册以其他方式解析的依赖项,如通过BeanFactoryAware解析的BeanFactory或通过ApplicationContextAware解析的ApplicationContext。
这里有一个疑问:注册ApplicationContextAwareProcessor的作用是实例化上述6个aware类对象到bean工厂,为什么又要通过ignoreDependencyInterface接口忽略掉这6个aware类对象的自动装配呢?(待解决)
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
接下来是注册几个特殊的依赖解析器,这些解析器是为bean工厂或者说是Spring容器服务的。这几个bean有自动装配(autowired)的能力,但是他们却并不是以bean的形式出现在bean工厂中。简单说来这几玩意是由Spring自行管理的内部对象。
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
ApplicationListenerDetector通过postProcessAfterInitialization方法,从注册到bean工厂单例bean中所有实现了ApplicationListener接口的bean,放入Spring容器的applicationListeners和applicationEventMulticaster中。
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
Load Time Weaving是再AspectJ在类加载时期进行代码织入的一种技术。如果容器中存在名为"loadTimeWeaver"的bean,则添加一个作用域为loadTimeWeaver的后置处理器。
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
假如存在名为enviroment, systemProperties, systemEnviroment的几个bd对象,则将其注册到bean工厂的Map
到此,prepareBeanFactory方法就执行完成了。这一步骤为bean工厂空旷的厂房添加了几件常用的设备,后续会经常用到。
如果将00:00-7:00的时刻表映射到Sping的启动流程的话,目前的时间大致应该是在01:30左右。下一节,我们将继续分析refresh方法中的invokeBeanFactoryPostProcessors。这一步骤极为重要。我们下篇文章再见~