美文网首页
## Spring-Core核心逻辑源码分析

## Spring-Core核心逻辑源码分析

作者: 带上小八去旅行 | 来源:发表于2016-09-17 14:01 被阅读0次

<a></a>初始化容器

  1. 服务器容器根据配置文件(Tomcat:web.xml)加载ContextInitialListener事件:ContextLoaderListener.contextInitialized();
  2. 尝试获得parentContext;
  3. 根据parentContext [初始化ApplicationContext](#Initial ApplicationContext);
  4. ApplicationRoot为key,将context注册到servletContext中;
  5. 如果当前线程的ClassLoader为ContextClassLoader,则将context设置为currentContext;否则将context设置为perThreadContext;

<a name='Initial ApplicationContext'>初始化ApplicationContext</a>

  1. 通过BeanUtil.instantiateClass()来创建ConfigurableWebApplicationContext;
  2. 设置context的id、parent、servletContext等属性(不晓得Id有什么用,代码还费了好几行获得best possible id😂);
  3. 调用ctx.refresh()方法[构建Spring容器](#start up Spring)构建Spring容器.

通过refresh方式初始化容器而不是init的方式,而且refresh中有通过beanFactory.getBean方式获取的对象,初始化阶段BeanFactory中是没有BeanDefinition的,因此这里我怀疑和tomcat的热部署有关系。

<a name='start up Spring'>构建Spring容器</a>

  1. 根据信号startupShutdownMonitor来作同步,在同步代码块中进行refresh操作;

Spring注释对startupShutdownMonitor有如下解释:
Synchronization monitor for the "refresh" and "destroy".
即destroy方法必须等refresh方法执行完之后才能被调用;

  1. prepareRefresh():准备刷新,这里有个同步设置变量active,没看懂啥意思;
  2. obtainRefreshBeanFactory():[初始化](#init beanFactory)并获取BeanFactory;
  3. prepareBeanFactory():初始化BeanFactory的依赖,包括ignoreDependency和硬代码registerDependency;Ignore掉的依赖通常是由别的方式进行注入,比如BeanFactory对象可以由BeanFactoryAware方式注入;获取并维护系统变量和环境变量
  4. invokeBeanFactoryPostProcessor():根据BeanFactory是否为BeanDefinitionRegistry来调用BeanFactoryPostProcessor,再根据priority、order、nonOrder的顺序调用BeanPostProcessor。在服务器初始化阶段并没有注册BeanFactoryPostProcessor,也许在热部署阶段会执行吧;也就是说,BeanFactoryPostProcessor是在BeanFactory初始化之后Bean对象初始化前执行的
  5. registerBeanPostProcessor():根据BeanFactory.getBeanNamesForType()获取BeanPostProcessor,然后以Priority、Order、NonOrder的顺序注册到BeanPostProcessorList中。BeanPostProcessorList为ArrayList,因此执行顺序为:Priority>Order>NonOrder;
  6. initMessageSource():获取MessageSource对象,默认为DelegatingMessageSource;
  7. 接下来是注册广播事件监听器、调用子类的onRefresh方法、注册应用监听器;
  8. finishBeanFactoryInitialization():初始化所有not-lazy-init Bean。也是SpringCore的核心代码
  9. finishRefresh:触发加载完成事件;

<a name='init beanFactory'>初始化BeanFactory</a>

  1. 清空已加载的Bean;
  2. 创建一个内部BeanFactory;
  3. 自定义BeanFactory配置:setAllowBeanDefinitionOverriding、setAllowEagerClassLoading、setAllowCircularReferences、setAllowRawInjectionDespiteWrapping
  4. loadBeanDefinitions():遍历Resources中的Xml定义的bean加载至BeanDefinition;

<a name='loadBeanDefinition'>Bean加载</a>

  1. 根据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;

<a name='spring-core'>核心代码</a>

  1. 1.finishBeanFactoryInitialization->preInstantiateSingletons():同步获取缓存中的beanDefinitionNames,放到局部变量中;
  2. 遍历beanDefinitionName,调用[getBean()](#get bean)初始化Bean;
<a name = 'get bean'>getBean()</a>
  1. 首先尝试从singletonObjects、earlySingletonObjects的缓存中获取对象;
  2. 如果对象不为空,则调用getObjectForBeanInstance()方法通过FactoryBean或者对象本身的方式获得Bean对象;
  3. 如果对象不为空,则尝试在ParentBeanFactory中获得对象,并返回;
  4. 如果ParentBeanFactory对象中没有获得Bean对象,则读取BeanDefinistions缓存中获得该Bean的Definition对象;
  5. 拿到BeanDefinition对象后,遍历该对象的dependsOn属性,并将该BeanName与DependsOn的对象Name注册dependentBeanMap中,然后调用[getBean()](#get bean)来实例化DependsOn的对象。这里会根据dependentBeanMap来检查是否存在循环依赖,(Spring对Bean属性之间的循坏依赖是有解决方案的,不清楚这里的循坏依赖为什么会直接抛出异常);
  6. 实例化DependsOn对象后,再根据Bean的Scope属性创建对象,Singleton方式和prototype方式的区别在于Singleton对象在创建的时候首先会在缓存中取对象,如果不存在再createBean()创建一个新的对象放到singletonObjects和earlySingletonObjects中,而prototype类型的则不不会在缓存中取对象,直接创建新对象.
  7. getObjectForBeanInstance()
    :拿到Bean对象之后,确定Bean是否为FactoryBean,如果是则需要通过FactoryBean的方式获取bean,否则直接返回bean.
<a name='createBean'>createBean()</a>
  1. 在初始化前,首先调用resolveBeanClass()确保beanClass已经加载到ClassLoader里面;这里会去看BeanDefinition中是否有指定的class,如果没有,则会调用ClassUtils.forName()在ClassLoader容器中加载class;
  2. 确保class已经加载完成之后,执行resolveBeforeInstantiation(),尝试通过InstantiationAwareBeanPostProcessor来创建Bean,如果Bean创建成功,则调用applyBeanPostProcessorsAfterInitialization()应用Bean后处理器,并返回Bean对象;(InstantiationAwareBeanPostProcessor这个里面虽然可以返回null,但是返回null之后,Spring容器会认为没有创建bean,重新创建bean)
  3. 如果InstantiationAwareBeanPostProcessor返回null,调用doCreateBean()真正的创建Bean对象.(os:创建个对象前戏真长😴)
<a name='doCreateBean'>doCreateBean()</a>
  1. 通过createBeanInstance()创建Bean实例。该方法首先在resolvedConstructor的一系列变量中找到缓存的Constructor,否则找到一个FastConstructor(找最合适的过程比较冗长,这里省略这么多字),再根据是否有OverrideMethod,来选择通过Reflect的形式还是CGlib的形式创建对象;
  2. Bean实例化出来之后,调用applyMergedBeanDefinitionPostProcessors()来执行BeanPostProcessor;
  3. 这时候属性还是空的,在注入属性时会发生循环依赖的问题,因此这里会判断是否允许循环依赖,如果允许的话将bean的引用通过ObejctFactory工厂的方式暴露出去;
  4. populateBean(),遍历并且注入依赖。
  5. initializeBean(),调用Bean的初始化方法,init啦,afterPropertiesSet啦。

额外补充:实例Bean是什么时候变成Proxy的呢?

通过doCreateBean()的步骤1.出来的实例这个时候还是对象本身,而Spring暴露出来的Bean又都是以代理形式出现的,那么Spring是什么时候对实例进行代理wrap的呢,通过Debug看到在applyMergedBeanDefinitionPostProcessors()阶段,
AbstractAutoProxyCreator以BeanPostProcessor的方式对实例出来的Bean进行AutoProxy,通过判断该实例的Class对象是否有Interfaces,如果有则通过JDK Dynamic的方式代理,否则使用CGlib.

相关文章

网友评论

      本文标题:## Spring-Core核心逻辑源码分析

      本文链接:https://www.haomeiwen.com/subject/rkxwettx.html