SpringIOC源码分析总结

Posted itxiaok

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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()方法

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

































































































以上是关于SpringIOC源码分析总结的主要内容,如果未能解决你的问题,请参考以下文章

springIOC源码解析之BeanDefinition的注册

Android 插件化VirtualApp 源码分析 ( 目前的 API 现状 | 安装应用源码分析 | 安装按钮执行的操作 | 返回到 HomeActivity 执行的操作 )(代码片段

spring源码分析spring ioc容器之前生今世--DefaultListableBeanFactory源码解读

Android 逆向整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmOptimizeDexFile() 方法分析 | /bin/dexopt 源码分析 )(代码片段

Android 事件分发事件分发源码分析 ( Activity 中各层级的事件传递 | Activity -> PhoneWindow -> DecorView -> ViewGroup )(代码片段

Spring IoC 依赖注入源码分析