<a></a>初始化容器
- 服务器容器根据配置文件(Tomcat:web.xml)加载ContextInitialListener事件:
ContextLoaderListener.contextInitialized()
; - 尝试获得parentContext;
- 根据parentContext [初始化ApplicationContext](#Initial ApplicationContext);
- 将
ApplicationRoot
为key,将context注册到servletContext中; - 如果当前线程的ClassLoader为ContextClassLoader,则将context设置为currentContext;否则将context设置为perThreadContext;
<a name='Initial ApplicationContext'>初始化ApplicationContext</a>
- 通过
BeanUtil.instantiateClass()
来创建ConfigurableWebApplicationContext; - 设置context的id、parent、servletContext等属性(不晓得Id有什么用,代码还费了好几行获得best possible id😂);
- 调用
ctx.refresh()
方法[构建Spring容器](#start up Spring)构建Spring容器.
通过refresh方式初始化容器而不是init的方式,而且refresh中有通过beanFactory.getBean方式获取的对象,初始化阶段BeanFactory中是没有BeanDefinition的,因此这里我怀疑和tomcat的热部署有关系。
<a name='start up Spring'>构建Spring容器</a>
- 根据信号
startupShutdownMonitor
来作同步,在同步代码块中进行refresh操作;
Spring注释对startupShutdownMonitor有如下解释:
Synchronization monitor for the "refresh" and "destroy".
即destroy方法必须等refresh方法执行完之后才能被调用;
-
prepareRefresh()
:准备刷新,这里有个同步设置变量active,没看懂啥意思; -
obtainRefreshBeanFactory()
:[初始化](#init beanFactory)并获取BeanFactory; -
prepareBeanFactory()
:初始化BeanFactory的依赖,包括ignoreDependency和硬代码registerDependency;Ignore掉的依赖通常是由别的方式进行注入,比如BeanFactory对象可以由BeanFactoryAware方式注入;获取并维护系统变量和环境变量 -
invokeBeanFactoryPostProcessor()
:根据BeanFactory是否为BeanDefinitionRegistry来调用BeanFactoryPostProcessor,再根据priority、order、nonOrder的顺序调用BeanPostProcessor。在服务器初始化阶段并没有注册BeanFactoryPostProcessor,也许在热部署阶段会执行吧;也就是说,BeanFactoryPostProcessor是在BeanFactory初始化之后Bean对象初始化前执行的 -
registerBeanPostProcessor()
:根据BeanFactory.getBeanNamesForType()
获取BeanPostProcessor,然后以Priority、Order、NonOrder的顺序注册到BeanPostProcessorList中。BeanPostProcessorList为ArrayList,因此执行顺序为:Priority>Order>NonOrder; -
initMessageSource()
:获取MessageSource对象,默认为DelegatingMessageSource; - 接下来是注册广播事件监听器、调用子类的onRefresh方法、注册应用监听器;
-
finishBeanFactoryInitialization()
:初始化所有not-lazy-init Bean。也是SpringCore的核心代码; -
finishRefresh
:触发加载完成事件;
<a name='init beanFactory'>初始化BeanFactory</a>
- 清空已加载的Bean;
- 创建一个内部BeanFactory;
- 自定义BeanFactory配置:setAllowBeanDefinitionOverriding、setAllowEagerClassLoading、setAllowCircularReferences、setAllowRawInjectionDespiteWrapping
-
loadBeanDefinitions()
:遍历Resources中的Xml定义的bean加载至BeanDefinition;
<a name='loadBeanDefinition'>Bean加载</a>
- 根据Resource生成Document对象;根据Document的Element的nodeName属性来处理Bean:
- 如果nodeName为Import,则执行
importBeanDefinitionResource
操作加载import-resource定义的bean: - 如果nodeName为Alias,则将BeanName与Alias关联注册;
- 如果nodeName为Bean,则根据属性解析Element生成BeanHolder,将BeanName与BeanDefinition注册到BeanDefinitions缓存中;
- 如果nodeName为Beans,则跳至1.处理Beans中的Bean;
- 如果nodeName为Import,则执行
<a name='spring-core'>核心代码</a>
- 1.
finishBeanFactoryInitialization
->preInstantiateSingletons()
:同步获取缓存中的beanDefinitionNames
,放到局部变量中; - 遍历beanDefinitionName,调用[getBean()](#get bean)初始化Bean;
<a name = 'get bean'>getBean()</a>
- 首先尝试从singletonObjects、earlySingletonObjects的缓存中获取对象;
- 如果对象不为空,则调用
getObjectForBeanInstance()
方法通过FactoryBean或者对象本身的方式获得Bean对象; - 如果对象不为空,则尝试在ParentBeanFactory中获得对象,并返回;
- 如果ParentBeanFactory对象中没有获得Bean对象,则读取BeanDefinistions缓存中获得该Bean的Definition对象;
- 拿到BeanDefinition对象后,遍历该对象的dependsOn属性,并将该BeanName与DependsOn的对象Name注册dependentBeanMap中,然后调用[getBean()](#get bean)来实例化DependsOn的对象。这里会根据dependentBeanMap来检查是否存在循环依赖,(Spring对Bean属性之间的循坏依赖是有解决方案的,不清楚这里的循坏依赖为什么会直接抛出异常);
- 实例化DependsOn对象后,再根据Bean的Scope属性创建对象,Singleton方式和prototype方式的区别在于Singleton对象在创建的时候首先会在缓存中取对象,如果不存在再createBean()创建一个新的对象放到singletonObjects和earlySingletonObjects中,而prototype类型的则不不会在缓存中取对象,直接创建新对象.
-
getObjectForBeanInstance()
:拿到Bean对象之后,确定Bean是否为FactoryBean,如果是则需要通过FactoryBean的方式获取bean,否则直接返回bean.
<a name='createBean'>createBean()</a>
- 在初始化前,首先调用
resolveBeanClass()
确保beanClass已经加载到ClassLoader里面;这里会去看BeanDefinition中是否有指定的class,如果没有,则会调用ClassUtils.forName()
在ClassLoader容器中加载class; - 确保class已经加载完成之后,执行
resolveBeforeInstantiation()
,尝试通过InstantiationAwareBeanPostProcessor
来创建Bean,如果Bean创建成功,则调用applyBeanPostProcessorsAfterInitialization()
应用Bean后处理器,并返回Bean对象;(InstantiationAwareBeanPostProcessor
这个里面虽然可以返回null,但是返回null之后,Spring容器会认为没有创建bean,重新创建bean) - 如果
InstantiationAwareBeanPostProcessor
返回null,调用doCreateBean()真正的创建Bean对象.(os:创建个对象前戏真长😴)
<a name='doCreateBean'>doCreateBean()</a>
- 通过
createBeanInstance()
创建Bean实例。该方法首先在resolvedConstructor的一系列变量中找到缓存的Constructor,否则找到一个FastConstructor(找最合适的过程比较冗长,这里省略这么多字),再根据是否有OverrideMethod,来选择通过Reflect的形式还是CGlib的形式创建对象; - Bean实例化出来之后,调用
applyMergedBeanDefinitionPostProcessors()
来执行BeanPostProcessor; - 这时候属性还是空的,在注入属性时会发生循环依赖的问题,因此这里会判断是否允许循环依赖,如果允许的话将bean的引用通过
ObejctFactory
工厂的方式暴露出去; -
populateBean()
,遍历并且注入依赖。 -
initializeBean()
,调用Bean的初始化方法,init啦,afterPropertiesSet啦。
额外补充:实例Bean是什么时候变成Proxy的呢?
通过doCreateBean()的步骤1.出来的实例这个时候还是对象本身,而Spring暴露出来的Bean又都是以代理形式出现的,那么Spring是什么时候对实例进行代理wrap的呢,通过Debug看到在applyMergedBeanDefinitionPostProcessors()
阶段,
AbstractAutoProxyCreator以BeanPostProcessor的方式对实例出来的Bean进行AutoProxy,通过判断该实例的Class对象是否有Interfaces,如果有则通过JDK Dynamic的方式代理,否则使用CGlib.