Spring IOC ApplicationContext 源码
作为Spring提供的较之 BeanFactory 更为先进的IoC容器实现, ApplicationContext 除了拥有BeanFactory 支持的所有功能之外,还进一步扩展了基本容器的功能,包括 BeanFactoryPostProcessor 、 BeanPostProcessor 以及其他特殊类型bean的自动识别、容器启动后bean实例的自动初始化、国际化的信息支持、容器内事件发布等。
ApplicationContext 继承结构
image从 ApplicationContext
的继承机构可以看到, ApplicationContext
继承了BeanFactory
,也就是说,ApplicationContext
拥有BeanFactory
的全部功能,ApplicationContext
是通过将容器的功能委派给DefaultListableBeanFactory
来实现。除了继承BeanFactory,还有ResourceLoader
、EnvironmentCapable
、ApplicationEventPublisher
、MessageSource
等接口,也就说明ApplicationContext
除了容器的功能外,还囊括了资源的处理、环境、事件发布、国际化等。
ApplicationContext 源码
创建一个常用的ApplicationContext
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");
ApplicationContext 初始化
ClassPathXmlApplicationContext
的构造函数在设置完配置文件的位置后,紧接着调用refresh()
方法。refresh方法是加载或刷新配置的信息,同时加载容器的单例。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 为刷新准备这个context。
prepareRefresh();
// 告诉子类刷新内部bean工厂。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备好bean工厂,以便在此context中使用。
prepareBeanFactory(beanFactory);
try {
// 允许在context子类中对BeanFactory进行post-processing。
postProcessBeanFactory(beanFactory);
// 调用在context中注册为bean的工厂处理器(BeanFactoryPostProcessor)。
invokeBeanFactoryPostProcessors(beanFactory);
// 注册拦截bean创建的BeanProcessor。
registerBeanPostProcessors(beanFactory);
// 为context初始化消息源。
initMessageSource();
// 为context初始化事件多播。
initApplicationEventMulticaster();
// 初始化子类context中的其他特殊bean。
onRefresh();
// 检查listener类型的bean并注册它们。
registerListeners();
// 实例化所有剩余的(non-lazy-init)单例。
finishBeanFactoryInitialization(beanFactory);
// 最后一步:发布相应的事件。
finishRefresh();
}
catch (BeansException ex) {
...
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
obtainFreshBeanFactory
obtainFreshBeanFactory()
方法核心是内部调用refreshBeanFactory()
方法并将容器内部的ConfigurableListableBeanFactory
返回,从这也看到了ApplicationContext和BeanFactory的关系:ApplicationContext内部包含一个BeanFactory,ApplicationContext所有关于BeanFactory的功能将委派给此BeanFactory处理。
AbstractRefreshableApplicationContext#refreshBeanFactory
源码:
protected final void refreshBeanFactory() throws BeansException {
// 清理之前的BeanFactory
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// createBeanFactory方法直接新建一个DefaultListableBeanFactory,也就是说内部使用的是DefaultListableBeanFactory实例
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 自定义此上下文使用的内部bean工厂
customizeBeanFactory(beanFactory);
// 将BeanDefinition加载到给定的bean工厂中,通常通过委托给一个或多个BeanDefinitionReader来实现
// 子类实现的方法,此处调用的是AbstractXmlApplicationContext的方法
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException(...);
}
}
也就是说这一步是构建ApplicationContext内部的BeanFactory,以及根据配置将BeanDefinition加载到BeanFactory中。
prepareBeanFactory
配置工厂的标准上下文特征,比如上下文的类加载器和后处理器。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 告诉内部bean工厂使用上下文的ClassLoader等。
beanFactory.setBeanClassLoader(getClassLoader());
// 使用Spring的表达式模块解析和计算Spring EL表达式
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
// 属性编辑器
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 这个在BeanFactory源码提到过的,扩展的Aware类型通过BeanPostProcessor来装配
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);
// 注册为可装配的依赖,而不是bean
// MessageSource注册为bean
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 注册early post-processor检测bean是否为applicationlistener。
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 检测LoadTimeWeaver并为织入做准备
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// 为类型匹配设置一个临时类加载器。
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// 注册默认的环境beans
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());
}
}
postProcessBeanFactory
对BeanFactory预处理,ClassPathXmlApplicationContext
未重写,WebXmlApplicationContext
有重写,这里不展开。
invokeBeanFactoryPostProcessors
在任何应用程序bean的实例化之前,实例化并调用所有已注册的BeanFactoryPostProcessor bean,如果实现了PriorityOrdered或者Ordered接口这按顺序调用。
invokeBeanFactoryPostProcessors
方法主要有两个调用:
- invokeBeanFactoryPostProcessors,调用BeanFactoryPostProcessors
- 检测LoadTimeWeaver,选择添加LoadTimeWeaverAwareProcessor,这一步在prepareBeanFactory已经做了
invokeBeanFactoryPostProcessors方法逻辑很简单
- 如果beanFactory是BeanDefinitionRegistry,则先处理BeanDefinitionRegistryPostProcessor
- 处理完ApplicationContext的BeanDefinitionRegistryPostProcessor后,实例化beanFactory的BeanDefinitionRegistryPostProcessor,按照PriorityOrdered -> Ordered -> non,顺序处理
- 按照BeanFactoryPostProcessor的方法,处理以上所有的,包括BeanDefinitionRegistryPostProcessor
- 还没完,第二步是取出beanFactory的BeanDefinitionRegistryPostProcessor,还有部分它的超类BeanFactoryPostProcessor未处理。按照2、3步处理未执行的BeanFactoryPostProcessor
registerBeanPostProcessors
在任何应用程序bean的实例化之前,按照顺序,实例化并调用所有已注册的BeanPostProcessor bean。
注册BeanPostProcessor和注册BeanFactoryPostProcessor类似,主要步骤
- 注册BeanPostProcessorChecker,当bean在BeanPostProcessor实例化过程中创建时,它记录一个信息消息
- 从beanFactory中取出按照BeanPostProcessor类型取出postProcessorNames,然后实例化,按照PriorityOrdered -> Ordered -> non的顺序依次注册到beanFactory
- 注册一个ApplicationListenerDetector用于检测实例化的bean是否为一个ApplicationListeners,是则注册listener
initMessageSource
MessageSource用于处理I18n,获取多语言信息。这一步,初始化MessageSource,如果在此context中没有定义任何值,则使用DelegatingMessageSource,实际是委派给父类的。
initApplicationEventMulticaster
初始化ApplicationEventMulticaster。如果上下文中没有定义,则使用SimpleApplicationEventMulticaster。
onRefresh
子类实现用于刷新context特殊的初始化工作,在实例化单例之前调用特定bean的初始化。
registerListeners
添加实现ApplicationListener接口,作为Listener的bean。不会影响其他Listener监听事件,添加是BeanName,而不是实例化后的Bean。Listener注册到ApplicationEventMulticaster。主要步骤:
- 注册ApplicationContext特定的Listener
- BeanFactory取出ApplicationListener的BeanNames,这里不初始化bean,而是注册Listener BeanName
- 广播earlyApplicationEvents
finishBeanFactoryInitialization
完成此上下文bean工厂的初始化,初始化所有剩余的单例bean。 与BeanFactory不同的是,ApplicationContext是eager模式,这一步主要是直接调用BeanFactory的初始化方法,完成所有non-lazy-init的bean的初始化
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 初始化Context的类型转换服务。
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// 注册一个默认的ValueResolver,主要是为了解决注解的属性值,默认用Environment的propertyResolver
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// 先初始化LoadTimeWeaverAware,用于运行时织入
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// 实例化所有剩余的(non-lazy-init)单例。
beanFactory.preInstantiateSingletons();
}
实例化所有的bean就是遍历所有的beanNames,然后挨个调用getBean(beanName),bean的初始化在BeanFactory 源码分析已经分析过了。这里还有一步是检测SmartInitializingSingleton
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
smartSingleton.afterSingletonsInstantiated();
}
也就是说bean还可以实现SmartInitializingSingleton
完成最后的init工作。
finishRefresh
完成此上下文的刷新,调用LifecycleProcessor的onRefresh()方法并发布ContextRefreshedEvent。
protected void finishRefresh() {
// 清除context级资源缓存
clearResourceCaches();
// 为这个context初始化生命周期处理器,默认为DefaultLifecycleProcessor
initLifecycleProcessor();
// 刷新LifecycleProcessor,调用所有Lifecycle的start方法
getLifecycleProcessor().onRefresh();
// 发布事件
publishEvent(new ContextRefreshedEvent(this));
// 。。。好像是对JMX支持
LiveBeansView.registerApplicationContext(this);
}
这个方法主要是对于有生命周期的bean,按照分组,调用其start方法。
ApplicationContext 使用
那么到此ApplicationContext初始化也就完成了,ApplicationContext可以作为BeanFactory、时间通知、资源管理使用
// beanFactory
UserService userService = context.getBean("userService", UserService.class);
// 事件
context.addApplicationListener(new WalkListener());
context.publishEvent(new WalkEvent(new User("Jerry")));
context.publishEvent(new WalkEvent(new User("Peter")));
// locale
context.getMessage("menu.edit", null, "Edit", Locale.US);
// ...
ApplicationContext的使用部分只需要调用内部的相应的组件即可。
总结
ApplicationContext 是Spring 的完整上下文,通过将各个功能模块委派给各个组件,完成了一个完成的环境,在ApplicationContext的构造函数中,完成各个组件的初始化,以备后期使用。