Spring IOC基本流程原理

前言:


Spring IoC 容器初始化的关键环节就在 AbstractApplicationContext#refresh() ⽅法中

@Override
publicvoidrefresh()throwsBeansException,IllegalStateException{
    synchronized(this.startupShutdownMonitor){
        StartupStepcontextRefresh=this.applicationStartup.start("spring.context.refresh");

        //刷新前的预处理
        //Preparethiscontextforrefreshing.
        prepareRefresh();

        //BeanFactory创建流程一:获取BeanFactory;默认实现是DefaultListableBeanFactory 
        //加载BeanDefition 并注册到 BeanDefitionRegistry
        //Tellthesubclasstorefreshtheinternalbeanfactory.
        ConfigurableListableBeanFactorybeanFactory=obtainFreshBeanFactory();

        //BeanFactory创建流程二:BeanFactory的预准备⼯作(BeanFactory进⾏⼀些设置,⽐如context的类加载器等)
        //Preparethebeanfactoryforuseinthiscontext.
        prepareBeanFactory(beanFactory);

        try{
            //BeanFactory创建流程三:BeanFactory准备⼯作完成后进⾏的后置处理⼯作
            //Allowspost-processingofthebeanfactoryincontextsubclasses.
            postProcessBeanFactory(beanFactory);

              StartupStepbeanPostProcess=this.applicationStartup.start("spring.context.beans.post-process");

            //BeanFactory创建流程四:实例化并调⽤实现了BeanFactoryPostProcessor接⼝的Bean
            //Invokefactoryprocessorsregisteredasbeansinthecontext.
            invokeBeanFactoryPostProcessors(beanFactory);

            //Bean创建流程一:注册BeanPostProcessor(Bean的后置处理器),在创建bean的前后等执⾏
            //Registerbeanprocessorsthatinterceptbeancreation.
            registerBeanPostProcessors(beanFactory);
            beanPostProcess.end();

            //初始化资源、事件、监听流程一:初始化MessageSource组件(做国际化功能;消息绑定,消息解析)
            //Initializemessagesourceforthiscontext.
            initMessageSource();

            //初始化资源、事件、监听流程二:初始化事件派发器
            //Initializeeventmulticasterforthiscontext.
            initApplicationEventMulticaster();

            //初始化资源、事件、监听流程三:⼦类重写这个⽅法,在容器刷新的时候可以⾃定义逻辑
            //Initializeotherspecialbeansinspecificcontextsubclasses.
            onRefresh();

            //初始化资源、事件、监听流程四:注册应⽤的监听器。就是注册实现了ApplicationListener接⼝的监听器bean
            //Checkforlistenerbeansandregisterthem.
            registerListeners();

            //Bean创建流程二:初始化所有剩下的⾮懒加载的单例bean
            //Instantiateallremaining(non-lazy-init)singletons.
            finishBeanFactoryInitialization(beanFactory);

            //完成context的刷新。主要是调⽤LifecycleProcessor的onRefresh()⽅法,并且发布事件 (ContextRefreshedEvent)
            //Laststep:publishcorrespondingevent.
            finishRefresh();
    }

    catch(BeansExceptionex){
          if(logger.isWarnEnabled()){
           logger.warn("Exceptionencounteredduringcontextinitialization-"+
"cancellingrefreshattempt:"+ex);
    }

        //Destroyalreadycreatedsingletonstoavoiddanglingresources.
        destroyBeans();

        //Reset'active'flag.
        cancelRefresh(ex);

        //Propagateexceptiontocaller.
        throwex;
    }

    finally{
        //ResetcommonintrospectioncachesinSpring'score,sincewe
        //mightnoteverneedmetadataforsingletonbeansanymore...
        resetCommonCaches();
        contextRefresh.end();
    }
}
}

可以看到会有以下主流程:

主要有几大模块:

(1)执行前的预处理与执行后的context刷新

(2)BeanFactory创建流程

(3)Bean创建流程

(4)初始化资源、事件、监听流程

 

执行顺序如下:

(1)刷新前的预处理

(2)BeanFactory创建流程一:获取BeanFactory(默认实现是DefaultListableBeanFactory) ,加载BeanDefition 并注册到 BeanDefitionRegistry

(3)BeanFactory创建流程二:BeanFactory的预准备⼯作(BeanFactory进⾏⼀些设置,⽐如context的类加载器等)

(4)BeanFactory创建流程三:BeanFactory准备⼯作完成后进⾏的后置处理⼯作

(5)BeanFactory创建流程四:实例化并调⽤实现了BeanFactoryPostProcessor接⼝的Bean

(6)Bean创建流程一:注册BeanPostProcessor(Bean的后置处理器),在创建bean的前后等执⾏

(7)初始化资源、事件、监听流程一:初始化MessageSource组件(做国际化功能;消息绑定,消息解析)

(8)初始化资源、事件、监听流程二:初始化事件派发器

(9)初始化资源、事件、监听流程三:⼦类重写这个⽅法,在容器刷新的时候可以⾃定义逻辑

(10)初始化资源、事件、监听流程四:注册应⽤的监听器。就是注册实现了ApplicationListener接⼝的监听器bean

(11)Bean创建流程二:初始化所有剩下的⾮懒加载的单例bean

(12)完成context的刷新。主要是调⽤LifecycleProcessor的onRefresh()⽅法,并且发布事件 (ContextRefreshedEvent)

 

一、BeanFactory创建流程


1.获取BeanFactory

时序图如下:

2.BeanDefinition加载解析及注册

主要有以下几步:

1Resource定位:指对BeanDefinition的资源定位过程。通俗讲就是找到定义Javabean信息的XML⽂件,并将其封装成Resource对象。

过程:

⼦流程⼊⼝在 AbstractRefreshableApplicationContext#refreshBeanFactory ⽅法中

依次调⽤多个类的 loadBeanDefinitions ⽅法 ​ —> AbstractXmlApplicationContext ​ —>AbstractBeanDefinitionReader —> XmlBeanDefinitionReader ​ ⼀直执⾏到XmlBeanDefinitionReader 的doLoadBeanDefinitions ⽅法

doLoadBeanDefinitions()方法主要内容是:读取xml,将xml中的信息保存到Document对象,并解析document对象,封装BeanDefinition对象并注册

 

2BeanDefinition载⼊ :把⽤户定义好的Javabean表示为IoC容器内部的数据结构,这个容器内部的数据结构就是BeanDefinition。

主要是XmlBeanDefinitionReader 类的 registerBeanDefinitions ⽅法(在上述doLoadBeanDefinitions()方法中)会最终调用到DefaultBeanDefinitionDocumentReader中的processBeanDefinition方法

bdHolder=delegate.decorateBeanDefinitionIfRequired(ele,bdHolder);为解析成BeanDefintionHolder对象

3)注册BeanDefinition IoC 容器

接着上述的DefaultBeanDefinitionDocumentReader中的processBeanDefinition方法

BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder,getReaderContext().getRegistry());为完成注册操作

所谓的注册就是把封装的 XML 中定义的 Bean信息封装为BeanDefinition 对象之后放⼊⼀个Map中,BeanFactory 是以 Map 的结构组织这些 BeanDefinition的。

 

二、Bean创建流程


 

 

备注:

1.lazy-init 延迟加载机制

普通 Bean 的初始化是在容器启动初始化阶段执⾏的,⽽被lazy-init=true修饰的 bean 则是在从容器⾥第⼀次进⾏context.getBean() 时进⾏触发。

(1)对于被修饰为lazy-init的bean Spring 容器初始化阶段不会进⾏ init 并且依赖注⼊,当第⼀次进⾏getBean时候才进⾏初始化并依赖注⼊

(2)对于⾮懒加载的bean,getBean的时候会从缓存⾥头获取,因为容器初始化阶段 Bean 已经初始化完成并缓存了起

 

2.Spring IoC循环依赖问题

循环依赖其实就是循环引⽤,也就是两个或者两个以上的 Bean 互相持有对⽅,最终形成闭环。

Spring中循环依赖场景有:

  • 构造器的循环依赖(构造器注⼊)
  • Field 属性的循环依赖(set注⼊)

 

循环依赖无法处理的情况

  • 单例 bean 构造器参数循环依赖(⽆法解决)
  • prototype 原型 bean循环依赖(⽆法解决)

Spring中解决循环依赖的过程

(1)BeanA对象在实例化之后立马放入三级缓存

(2)BeanB在创建过程中发现依赖A,那么去三级缓存使用尚未成型的BeanA

(3)将BeanA升级放到二级缓存

(4)BeanB创建完成之后会放入一级缓存

(5)BeanA使用一级缓存中的BeanB

 

 

 

 

 

 

相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页