SpringIOC容器启动流程分析
Spring IOC 容器启动流程分析
使⽤ Spring 时,XML 和注解是使⽤得最多的两种配置⽅式,虽然是两种完全不同的配置⽅式,但对于 IOC 容器来说,两种⽅式的不同主要是在 BeanDefinition 的解析上。⽽对于核⼼的容器启动流程,仍然是⼀致的。
AbstractApplicationContext 的 refresh ⽅法实现了 IOC 容器启动的主要逻辑,启动流程中的关键步骤在源码中也可以对应到独⽴的⽅法。接下来以 AbstractApplicationContext 的实现类 ClassPathXmlApplicationContext 为主 ,并对⽐其另⼀个实现类AnnotationConfigApplicationContext, 解读 IOC 容器的启动过程。
@Override
public void refresh()throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor){
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory =obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try{
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
/
/ Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
// ...
}
}
ApplicationContext 和 BeanFactory 的关系
ClassPathXmlApplicationContext 和 AnnotationConfigApplicationContext 的继承树如下所⽰。两者都继承⾃ AbstractApplicationContext。
ApplicationContext 继承树()
BeanFactory 继承树()
ApplicationContext 是 IOC 容器的承载体,⽽ BeanFactory 是操作这个容器的⼯具,两者关系紧密,相互协作。refresh ⽅法实现了ApplicationContext 和 BeanFactory 相互协作的主要过程,不同之处主要在⼦类 AbstractRefreshableApplicationContext 和GenericApplicationContext 中实现,两者使⽤的 BeanFactory 都为 DefaultListableBeanFactory,DefaultListableBeanFactory 的定义如下:
DefaultListableBeanFactory:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable
可见 DefaultListableBeanFactory 实现了 ConfigurableListableBeanFactory,意味着是可配置,可遍历的,⾄于为什么可以,让我们继续往下寻答案。
BeanDefinition 的获取
DefaultListableBeanFactory 中使⽤ Map 结构保存所有的 BeanDefinition 信息:
DefaultListableBeanFactory:
private final Map<String, BeanDefinition> beanDefinitionMap =new ConcurrentHashMap<>(256); ClassPathXmlApplicationContext 中的解析
使⽤ BeanDefinitionDocumentReader(可参看 DefaultBeanDefinitionDocumentReader.processBeanDefinition⽅法) 将 xml 中的 bean 解析为BeanDefinition, 然后由 BeanDefinitionRegistry 注册到 BeanFactory 中。
⼊⼝:freshBeanFactory(在 refresh 中调⽤)
AnnotationConfigApplicationContext 中的解析
通过 BeanDefinitionScanner 扫描 Bean 声明,解析为 BeanDefinition 并由 BeanDefinitionRegistry 注册到 BeanFactory 中。
⼊⼝:AnnotationConfigApplicationContext 的构造函数。
为什么 ClassPathXmlApplicationContext 的⼊⼝是在 refreshBeanFactory ⽅法中?
AbstractApplicationContext:
protected abstract void refreshBeanFactory()throws BeansException, IllegalStateException
可见是⼀个抽象⽅法,具体实现在⼦类中。只有 “Refreshable” 的 BeanFactory 才会在该⽅法中实现具体操作,如AbstractRefreshableApplicationContext:
AbstractRefreshableApplicationContext:
@Override
protected final void refreshBeanFactory()throws BeansException {
if(hasBeanFactory()){
destroyBeans();
closeBeanFactory();
}
try{
DefaultListableBeanFactory beanFactory =createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized(this.beanFactoryMonitor){
this.beanFactory = beanFactory;spring ioc注解
}
}
catch(IOException ex){
throw new ApplicationContextException("I/O error parsing bean definition source for "+getDisplayName(), ex);
}
}
可见 AbstractRefreshableApplicationContext.``refreshBeanFactory ⽅法会检查 BeanFactory 是否已经存在(hasBeanFactory),已经存在就先销毁所有的 Bean(destoryBeans)并关闭(closeBeanFactory) BeanFactory,然后再创建(createBeanFactory)新的。
⽽ freshBeanFactory中会检查是否为第⼀次调⽤,不是就抛出异常,不执⾏其他逻辑,即GenericApplicationContext 不是 "Refreshable"的。
主流程分析
refresh ⽅法在 AbstractApplicationContext 中定义,其中的 obtainFreshBeanFactory ⽅法调⽤了 getBeanFactory ⽅法,该⽅法⽤于获取BeanFactory,这⾥为 DefaultListableBeanFactory,接下来⽆特别说明,⼤部分的⽅法和变量都将取⾃ AbstractApplicationContext 和DefaultListableBeanFactory。
BeanPostProcessor
BeanPostProcessor 接⼝让开发者在 IOC 容器对 Bean 进⾏实例化时收到回调(postProcessAfterInitialization 和 postProcessBeforeInitialization ⽅法)。spring 框架内部的许多通知(Aware)就是通过这个接⼝实现,如 ApplicationContextAwareProcessor, ServletContextAwareProcessor,他们的实现会在 postProcessBeforeInitialization ⽅法中进⾏检查,若实现了特定接⼝,就会调⽤ Aware 的回调⽅法,给予通知:
ServletContextAwareProcessor:
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)throws BeansException {
if(getServletContext()!= null && bean instanceof ServletContextAware){
((ServletContextAware) bean).setServletContext(getServletContext());
}
if(getServletConfig()!= null && bean instanceof ServletConfigAware){
((ServletConfigAware) bean).setServletConfig(getServletConfig());
}
return bean;
}
在 postProcessBeanFactory ⽅法中,⼦类可以通过 beanFactory.addBeanPostProcessor ⽅法添加⾃⼰的 BeanPostProcessor 到 beanFactory 中,最终将保存到 BeanFactory 的 beanPostProcessors(实为CopyOnWriteArrayList) 中。prepareBeanFactory 和 registerBeanPostProcessors ⽅法是集中实例化并添加这些 Bean 的地⽅。
BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor
从"BeanDefinition 的获取"的介绍可以知道 BeanDefinitionRegistry ⽤于将 BeanDefinition 注册到 BeanFactory
中,GenericApplicationContext 和 DefaultListableBeanFactory 都实现了该接⼝,GenericApplicationContext 中的实现直接调⽤了 beanFactory 的实现。
BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor 与 BeanPostProcessor 类似,但从他们的命名就可以看出,所针对的⽬标不同,分别是 BeanFactory 和 BeanDefinitionRegistry:
1 BeanFactoryPostProcessor 回调让开发者有机会在 BeanFactory 已经初始化好的情况下对 BeanFactory 的⼀些属性进⾏覆盖,或是对beanDefinitionMap 中的 BeanDefinition 进⾏修改。
2 BeanDefinitionRegistryPostProcessor 则让开发者可以继续添加 BeanDefinition 到 BeanFactory 中。
具体逻辑在 invokeBeanFactoryPostProcessors 中实现,这⾥⾸先会将所有实现了 BeanFactoryPostProcessors的 Bean 实例化,然后调⽤其回调⽅法(postProcessBeanDefinitionRegistry 或 postProcessBeanFactory ⽅法)。
对于这部分 Bean 的实例化和进⾏回调有⼀定的优先级规则。PriorityOrdered 继承⾃ Ordered 接⼝,实现了 PriorityOrdered 的BeanDefinitionRegistryPostProcessor 将最先被实例化并调⽤,然后同样的规则来回调实现了 BeanFactoryPostProcessor 的 Bean:PriorityOrdered > Ordered > 未实现 Ordered 的
在 registerBeanPostProcessors ⽅法中对 BeanPostProcessor 的实例化也有这样的优先级规则:
PriorityOrdered > Ordered > 未实现 Ordered 的 > MergedBeanDefinitionPostProcessor
ApplicationEventMulticaster
在 initApplicationEventMulticaster 中会对 ApplicationEventMulticaster 进⾏初始化: ⾸先会检查是否已经有了ApplicationEventMulticaster 的BeanDefinition(在 beanDefinitionMap 中检查),有就让容器进⾏实例化,没有就使⽤框架默认的 ApplicationEventMulticaster (即SimpleApplicationEventMulticaster),先实例化,然后注册到容器中(MessageSource 在 initMessageSource ⽅法中也是同样的⽅式进⾏初始化)。
事件的起始发送处将事件包装为 ApplicationEvent ,并通过 ApplicationEventPublisher 提交给
ApplicationEventMulticaster,ApplicationEventMulticaster 会将事件⼴播给 ApplicationListener,处理最终的分发。
AbstractApplicationEventMulticaster 中的 applicationListeners(实为 LinkedHashSet<ApplicationListener>) 变量保存了所有的⼴播接收
者,registerListeners ⽅法会将所有的 ApplicationListener 添加到该集合中。
finishRefresh ⽅法中有⼀个对 ContextRefreshedEvent 事件的⼴播可以作为参考,最终事件会由 multicastEvent ⽅法处理: SimpleApplicationEventMulticaster.multicastEvent
@Override
public void multicastEvent(final ApplicationEvent event,@Nullable ResolvableType eventType){
ResolvableType type =(eventType != null ? eventType :resolveDefaultEventType(event));
Executor executor =getTaskExecutor();
for(ApplicationListener<?> listener :getApplicationListeners(event, type)){
if(executor != null){
}
else{
invokeListener(listener, event);
}
}
}
那么在我们⾃⼰的 Bean 中如何得到这个 ApplicationEventPublisher 呢?
ApplicationContext 的定义如下:
ApplicationContext:
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
可见 ApplicationContext 继承了 ApplicationEventPublisher,这就说明 AbstractApplicationContext 也是⼀个 ApplicationEventPublisher。在我们⾃⼰的 Bean 中通过实现 ApplicationEventPublisherAware,我们就能通过 setApplicationEventPublisher 回调得到 ApplicationEventPublisher。
上⾯我们提到 spring 的许多 Aware 是通过 BeanPostProcessor 实现的,ApplicationEventPublisherAware 也不例外: ApplicationContextAwareProcessor:
@Override
@Nullable
public Object postProcessBeforeInitialization(final Object bean, String beanName)throws BeansException {
// ...
if(bean instanceof Aware){
if(bean instanceof EnvironmentAware){
((EnvironmentAware) bean).setEnvironment(Environment());
}
if(bean instanceof EmbeddedValueResolverAware){
((EmbeddedValueResolverAware) bean).beddedValueResolver);
}
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);
}
}
// ...
}
IOC 容器在实例化我们的 Bean 时会调⽤ ApplicationContextAwareProcessor.postProcessBeforeInitialization ⽅法,该⽅法会检查我们的Bean,我们的 Bean 如果实现了 ApplicationEventPublisherAware,那么就会回调 setApplicationEventPublisher ⽅法将applicationContext(即ApplicationEventPublisher) 传给我们,我们就能够发布事件。
BeanFactory 的⼏个重载了的 getBean ⽅法是 Bean 最终进⾏实例化的地⽅,registerBeanPostProcessors, invokeBeanFactoryPostProcessors 和 finishBeanFactoryInitialization ⽅法都调⽤了 getBean ⽅法对⼀些特定 Bean 进⾏了实例化。
finishBeanFactoryInitialization 中通过调⽤ BeanFactory 的 preInstantiateSingletons 对单例 Bean 进⾏实例化。BeanFactory 和 BeanDefinition 都具有⽗⼦的概念,在⼦级不到指定的 Bean 时将⼀直往上(⽗级),到就进⾏实例化
总结
spring IOC 容器的启动步骤可总结如下:
1 初始化 ApplicationContext
环境属性的初始化和验证,启动时间记录和相关标记设置,应⽤事件和监听者的初始化。
2 准备好容器中的 BeanDefinition (eager-initializing beans)
对 BeanDefinition 的解析、扫描和注册,BeanDefinition 的扫描和注册⼤致可以分为 XML 和注解两种,两种⽅式各⾃使⽤的组件有所不同,该步骤的时间也可以在最前⾯。
3 初始化 BeanFactory
准备好 BeanFactory 以供 ApplicationContext 进⾏使⽤,对接下来将要使⽤到的 Bean 进⾏实例化,资源进⾏准备,属性进⾏设置。
4 注册 BeanPostProcessors
BeanPostProcessors 是进⾏扩展的关键组件,需要在该步骤中进⾏注册,可分为两种类型: ⼀种是框架使⽤者提供的,⽤于特定业务功能的,另⼀种是框架开发者提供的,⽤于扩展框架功能。
5 调⽤ BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor 是⼀种功能增强,可以在这个步骤添加新的 BeanDefinition 到 BeanFactory 中。
6 调⽤ BeanFactoryPostProcessor
BeanFactoryPostProcessor 是⼀种功能增强,可以在这个步骤对已经完成初始化的 BeanFactory 进⾏属性覆盖,或是修改已经注册到BeanFactory 的 BeanDefinition。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论