zoukankan      html  css  js  c++  java
  • SpringIOC源码分析总结

    大致的加载过程:

    spring ioc容器的加载,大体上经过以下几个过程: 资源文件定位、解析、注册、实例化

    1.资源文件定位:主要发生在ApplicationContext中,由于applicationContext继承于ResourceLoader,所以调用getResource()方法,将外部的资源解析成Resource类

    2.解析:主要发生在BeanDefinitionReader中完成,最常用的类是XMLBeanDefiniationReader,

    ac利用loadBeanDefininiation()方法,负责读取Resource;将Resource的解析交给XMLbeanDefiniationReader去处理,

    将XML文档解析成w3c的Document文档,BeanDefinitionDocumentReader进一步解析,BeanDefinitionDocumentReader将Document,交给BeanDefiniationParserDetegate去处理(装饰),如果是标准的NameSpace文档(import、alias、bean、beans),在内部解析,如果不是标准的文档,会委托合适的NameSpaceHander去处理进行解析,将结果封装到BeanDefiniationHolder,最后调用一个工具类来完成对BeanDefinintion的注册

    3.注册

    Bean的注册是在BeanFactory中完成的,BeanFactory最常用的一个实现类是DefaultListableBeanFactory,它实现了BeanDefinitionRegistry接口,调用了registerBeanDefinition()方法,从而对BeanDefinition进行注册.

    所谓的注册就是将BeanDefinition的name和实例保存到一个CurrentHashMap中,最常用的实现DefaultListableBeanFactory,其中的字段就是beanDefinitionMap,是一个ConcurrentHashMap

    4.实例化:

    注册也完成之后,在BeanFactory的getBean()方法之中,会完成初始化

    容器初始化的核心

    Refresh()方法

     

                //1.刷新前的预处理
    // Prepare this context for refreshing.
    prepareRefresh();
    //2.获取beanfactory
    // Tell the subclass to refresh the internal bean factory.
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    //3.beanFactory的预准备工作
    // Prepare the bean factory for use in this context.
    prepareBeanFactory(beanFactory);

    try {
    //4.为BeanFactory准备工作完成后,添加一些的后置处理器(用户自定义)
    // Allows post-processing of the bean factory in context subclasses.
    postProcessBeanFactory(beanFactory);
    //5.执行beanFacotry的后置处理器
    // Invoke factory processors registered as beans in the context.
    invokeBeanFactoryPostProcessors(beanFactory);
    //6.注册Bean的后置处理器
    // Register bean processors that intercept bean creation.
    registerBeanPostProcessors(beanFactory);
    //7.初始化消息资源管理(主要用于国际化、消息绑定、消息解析)
    // Initialize message source for this context.
    initMessageSource();
    //8.初始化事件的派发器
    // Initialize event multicaster for this context.
    initApplicationEventMulticaster();
    //9.重新刷新容器,留给子类重写该方法,进行自定义
    // Initialize other special beans in specific context subclasses.
    onRefresh();
    //10.将容器中的ApplicationListener注册进来
    // Check for listener beans and register them.
    registerListeners();
    //11.初始化所有的非懒加载的Bean实例
    // Instantiate all remaining (non-lazy-init) singletons.
    finishBeanFactoryInitialization(beanFactory);
    //12.完成BeanFactory的初始化创建工作
    // Last step: publish corresponding event.
    finishRefresh();
    //IOC容器创建完成

     

     

    1.prepareRerfresh()

    (1), initPropertySources初始化一些属性设置

    (2),getEnvironment().validateRequiredProperties();校验属性和环境的相关设置

    (3), this.earlyApplicationEvents = new LinkedHashSet<>();保存容器中的一些早期事件

    2.obtainFreshBeanFactory()

    (1)refreshBeanFactory();创建BeanFactory对象

        1.如果有BeanFactory,就清空

    2.createBeanFactory()创建DefaultListableBeanFactory对象

    3.beanFactory.setSerializationId(getId());设置标识符

    4.customizeBeanFactory()允许用户自定义一些设置

    5.loadBeanDefinitions()解析XML文件并注册成BeanDefinition对象

    <1>创建XMLBeanDefinitionReader对象,new XmlBeanDefinitionReader(beanFactory);

    beanFactory其实是BeanDefinitionRegistry对象,因为DefaultListableBeanFactory实现了

    BeanDefinitionRegistry接口                            

    <2>设置并初始化XMLBeanDefinitionReader对象

    <3>loadBeanDefinition(beanDefinitionReader)解析XML文件并注册成BeanDefinition对象

    的真正方法

    其内部: XmlBeanDefinitionReader无法直接解析配置文件,所以利用了ResourceReader

    将Location配置文件封装成Resource,然后调用重载的方法,先将Resource转换成  

    InputStream在解析成w3c的Doucment对象,最后调用RegisterBeanDefinitions()

    RegisterBeanDefinitions()内部实现:创建一个BeanDefinitionDocumentReader对象 起到路由的作用

    1.该对象会委托BeanDefinitionParserDelegate()进行真正的解析doc

    调用delegate.parseBeanDefinitionElement(ele),如果是标准的NameSpace文档

    (import、alias、bean、beans),在内部解析,如果不是标准的文档,会委托合适的

                              NameSpaceHander去处理进行解析,将结果封装到BeanDefiniationHolder

    2.调用Delegate对BeanDefinition进行装饰

      3.最后调用工具类方法,进行注册,其实调用的是DefaultListableBeanFactory中的    

                            registerBeanDefinition(),该方法主要是beanName放到队列(beanDefinitionNames)                         里,然后把BeanDefinition放到beanDefinitionMap.put(beanName, beanDefinition) <concurrentHashMap>

     

    (2)getBeanFactory() 获取BeanFactory对象,并返回ConfigurableListableBeanFactory对象

     

    3.prepareBeanFactory(beanFactory)

    4.postProcessBeanFactory(beanFactory)

    5.invokeBeanFactoryPostProcessors( beanFactory)

    执行BeanFactoryPostProcessor的方法;

    里有2个接口BeanDefinitionRegistryPostProcessor(BeanFactoryPostProcessors的子类)、BeanFactoryPostProcessors都将会执行它们的后置处理器的方法

    1.先执行BeanDefinitionRegistryPostProcessor的方法,(beanDefinition将要被加载在beanfactory中但是还没有实例化,作用是用于自己添加beanDefinition)

         1)、获取所有的BeanDefinitionRegistryPostProcessor;
    2)、看先执行实现了PriorityOrdered优先级接口的BeanDefinitionRegistryPostProcessor、
    postProcessor.postProcessBeanDefinitionRegistry(registry)
    3)、在执行实现了Ordered顺序接口的BeanDefinitionRegistryPostProcessor;
    postProcessor.postProcessBeanDefinitionRegistry(registry)
    4)、最后执行没有实现任何优先级或者是顺序接口的BeanDefinitionRegistryPostProcessors;
    postProcessor.postProcessBeanDefinitionRegistry(registry)

    2.否则的话,BeanFactoryPostProcessor的方法(beanfactory标准初始化之后,来定制beanfactory的内容,所有的beanDefinition已经保存到了beanfactory中但是还没有实例化)

    1)、获取所有的BeanFactoryPostProcessor
    2)、看先执行实现了PriorityOrdered优先级接口的BeanFactoryPostProcessor、
    postProcessor.postProcessBeanFactory()
    3)、在执行实现了Ordered顺序接口的BeanFactoryPostProcessor;
    postProcessor.postProcessBeanFactory()
    4)、最后执行没有实现任何优先级或者是顺序接口的BeanFactoryPostProcessor;
    postProcessor.postProcessBeanFactory()

    6.RegistryBeanPostProcessor

    不同接口类型的BeanPostProcessor,在Bean创建执行前后是不一样的

    BeanPostProcessor、 DestructionAwareBeanPostProcessor、 InstantiationAwareBeanPostProcessor、 SmartInstantiationAwareBeanPostProcessor、 MergedBeanDefinitionPostProcessor【internalPostProcessors】、

    (1)先获取所有的BeanPostProcessor,这些后置处理器可以通过PriorityOrdered、Ordered接口来执行优先级

    (2)先将实现了PriorityOrdered优先级接口的BeanPostProcessor注册到BeanFactory

    把每一个BeanPostProcessor注册到BeanFactory中

    beanFactory.addBeanPostProcessor(postProcessor);

    (3)在注册实现了Ordered接口的BeanPostProcessor

    (4)最后注册没有实现任何优先级接口的

    (5)、最后注册一个ApplicationContextListenerDetector的后置处理器,用于在Bean创建完成后检查是否为ApplicationContextListener,是的话,就会调用ApplicationContext.addApplicationListener((ApplicationListener<?>) bean)将其添加到容器中

    7.InitMessageSource

    1.获取BeanFactory

    2.看容器中是否有id为messageSource的,类型是MessageSource的组件

    如果没有就创建一个DelegatingMessageSource,然后把messageSource注入到容器,以后获取国际化的资源可以根据messageSource来获取

    8.InitApplcationEventMulticaster

    (基于事件派发的组件)

    1.获取BeanFactory

    2.看容器中是否有id为applicationEventMulticaster的组件

    如果没有就创建一个SimpleApplicationEventMulticaster,然后把它注入到容器.

    9.onRefresh();

    子类重写这个方法,在容器刷新的时候可以自定义逻辑;

    10.registerListeners()

    1.从容器中获取所有的ApplicationListener

    2.将每个监听器添加到事件派发器中; getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);

    11.finishBeanFactoryInitialization()

    实际上调用的是DefaultListableBeanFactory的preInstantiateSingleton()方法

    preInstantiateSingleton()

    1.遍历BeanDefinitionMap

    2.在遍历的时候,调用getMergedLocalBeanDefinition(beanName)将其转换成RootBeanDefinition

    注意:普通的Bean在Spring加载Bean定义的时候,实例化出来的是GenericBeanDefinition,而Spring上下文包括实例化所有Bean用的AbstractBeanDefinition是RootBeanDefinition,这时候就使用getMergedLocalBeanDefinition方法做了一次转化,将非RootBeanDefinition转换为RootBeanDefinition以供后续操作

    3.在遍历的时候,判断要实例化Bean1.非抽象2.是单例3.非延迟加载
    
    4.在遍历的时候,先判断当前Bean是否为FactoryBean的实现(false,直接调用getBean(beanName))在判断是否为	 
    
         SmartFactoryBean的实现,假如Bean是SmartFactoryBean的实现并且为eagerInit(渴望加载),也会调用 
    
         getBean(beanName)立即实例化该Bean
    
    	getBean(beanName)核心doGetBean()为父类AbstractBeanFactory类的doGetBean方法 
    
    	doGetBean()方法
    
    		1.先判断本地的单例缓存中是否缓存过该Bean,如果有缓存就直接从缓存中获取
    
    		2.然后进行一些基本检验,比如检查depend-on属性,用来保证具有依赖关系的Bean先被加载
    
    		3.调用createBean(beanName, mbd, args)用于创建单实例对象
    		
    
    		     1.resolveBeforeInstantiation();
    						创建bean实例前,让BeanPostProcessor先拦截,是否能返回代理对象;
    						也就是给beanPostProcessor一个返回bean的代理对象机会
    						内部是【InstantiationAwareBeanPostProcessor】这个拦截器(和AOP有关)
    						先触发:postProcessBeforeInstantiation(beanClass, beanName);
    						如果有返回值Object bean ,就不会创建bean了在调用                                                       postProcessAfterInitialization(beanClass, beanName)并返回代理bean
    						[InstantiationAwareBeanPostProcessor]没有的代理的bean调用doCreateBean()
                  
    			2.doCreateBean()
                                 	AbstractAutowireCapableBeanFactory 的doCreateBean()方法
                        <1>.创建Bean实例,并包装成BeanWrapper    
                            createBeanInstance()方法        
                                 判断当前的Bean里面使用的是空参构造还是有参数构造,然后通过反射生成Bean的实							   例。看到前面有一步makeAccessible,这意味着即使Bean的构造函数是private、							   protected的,依然不影响Bean的构造。这里被实例化出来的Bean并不会直接返回,                               而是会被包装为BeanWrapper
                        <2>.允许后置处理器对其进行修改Bean定义 
                            applyMergedBeanDefinitionPostProcessors()    
                                 会调用MergedBeanDefinitionPostProcessor的                                                         postProcessMergedBeanDefinition(mbd, beanType, beanName);
                        <3>.属性注入    
                            populateBean()方法       
                                1)、在赋值之前,拿到InstantiationAwareBeanPostProcessor后置处理器
                                    调用postProcessAfterInstantiation();    
                                2)、继续拿到InstantiationAwareBeanPostProcessor后置处理器;                               					    调用postProcessPropertyValues();    赋值操作    
                                3)、applyPropertyValues()  真正为属性赋值的方法     
                                        首先进行深拷贝(指的是深度拷贝,遍历PropertyValue然后一个一个赋值到                                     一个新的List,是为了解析Values值中的所有引用),然后在调用                                                 bw.setPropertyValues(new MutablePropertyValues(deepCopy)),遍历                                     deepcopy对象拿到对应的set方法并将方法的可见性设置为true,最后利用反                                   射的机制,对Bean通过反射调用set()方法
                                        (1)拿到写方法并将方法的可见性设置为true
    
    								(2)拿到Value值,对Bean通过反射调用写方法
                          <4>.初始化Bean    
                            initializeBean()方法        
                                1).执行Aware()方法,调用invokeMethodAware(beanName, bean)方法 ,执行								xxxAware接口的方法
                                    实现BeanNameAware/BeanClassLoaderAware/BeanFactoryAware.... 才会进行								调用,aware主要是属性赋值后获取其中的信息并且自定义修改       
                                2).执行后置处理器在初始化之前                                                                        applyBeanPostProcessorsBeforeInitialization(wrappedBean,beanName);            
                                   BeanPostProcessor.postProcessBeforeInitialization();        
                                3).执行初始化的方法invokeInitMethods(beanName, wrappedBean, mbd)            
                                    <1>、是否是InitializingBean接口的实现;执行接口规定的初始化;           
                                    <2>、尝试去拿init-method,假如有的话,通过反射,调用initMethod;            
                                    因此,两种方法各有优劣:使用实现InitializingBean接口的方式效率更高一点,因为init-method方法是通过反射进行调用的(JVM无法优化在内存中的动态对象);从另外一个角度讲,使用init-method方法之后和Spring的耦合度会更低一点        
                                 4).执行后置处理器在初始化之后applyBeanPostProcessorsAfterInitialization           	                       BeanPostProcessor.postProcessAfterInitialization();    
                          		5).注册bean的销毁方法,在容器关闭之前会自动的进行调用    
                                 registerDisposableBeanIfNecessary(beanName, bean, mbd);    
                                要注册销毁方法,Bean需要至少满足以下三个条件之一:	
                                (1)Bean是DisposableBean的实现类,此时执行DisposableBean的接口方法									destroy()
                                (2)Bean标签中有配置destroy-method属性,此时执行destroy-method配置指定的							方法
                                (3)当前Bean对应的BeanFactory中持有DestructionAwareBeanPostProcessor接口							的实现类,此时执行 DestructionAwareBeanPostProcessor的接口方法                                       postProcessBeforeDestruction 
    	4.创建好Bean后,将其添加到容器中
    	5.非单例非原型调用
    		bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);(了解)如果bean是	           				 FactoryBean的实现类的话,调用getObject()方法获取真正的对象。
    

     

    流程总结:
    

    [

    12.finishRefresh()

    1)、initLifecycleProcessor();初始化和生命周期有关的后置处理器;LifecycleProcessor 默认从容器中找是否有lifecycleProcessor的组件【LifecycleProcessor】;如果没有new

                      DefaultLifecycleProcessor();然后到加入到容器中
    
    写一个LifecycleProcessor的实现类,可以在BeanFactory刷新或者关闭的时候进行调用
    				void onRefresh();
    				void onClose();
    

    2)、 getLifecycleProcessor().onRefresh();

    	拿到前面定义的生命周期处理器(BeanFactory);回调onRefresh();
    

    3)、publishEvent(new ContextRefreshedEvent(this));发布容器刷新完成事件;

    发布事件流程:1.获取事件派发器

    2.multicastEvent派发事件

    3.获取到所有的ApplicaitonListener

    4.判断是否需要已异步还是同步的方式进行执行listener的onApplicationEvent()方法

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    codec功能简介
    dtmf原理说明
    linux的vm.overcommit_memory的内存分配参数详解
    Hibernate与Sleep的区别
    简单的读写-simple_read_from_buffer
    linux delay sleep
    Linux系统上的popen()库函数
    Linux中popen函数的作用小结
    ulimit 命令详解
    LTE Cat1有什么用?基于4G LTE打造cat1,弥补NB-IoT和5G的空缺
  • 原文地址:https://www.cnblogs.com/itxiaok/p/10356683.html
Copyright © 2011-2022 走看看