欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring源码阅读(一):IOC容器的初始化

程序员文章站 2022-05-20 09:37:37
...

        一直想研究下当下流行的开源框架的代码,最近年初终于得空了看了下Spring Framework的部分源代码。Spring最核心的功能是IOC容器,其他所有功能都是在此基础上做出的内部扩展,如aop、tx等。

        首先先从web工程下经常使用的ContextLoaderListener开始阅读,可以知道Spring bean的创建过程是context-> beanFactory->bean。

  1. 初始化context

    context的作用

    • 实现统一资源读取接口用于获取spring容器配置文件的内容。
    • 调用相关工具类读取spring配置文件解析成BeanDefinitionHolder并缓存起来。
    • 实现几个beanFactory接口使得我们获取到context后即可得到目标bean,这样简化了bean获取方法(不必再去获取beanFactory)。
    • 实现了应用事件发布器接口,用于在容器内发布相应的事件。

     

    contex相关t类结构图如下:

    Spring源码阅读(一):IOC容器的初始化

           web工程中加载spring容器时使用的容器上下文是XmlWebApplicationContext,还有其他非web工程经常使用的context实现类如ClassPathXmlApplicationContext、FileSystemXmlApplicationContext等都是通过xml文件来定义spring容器的。现在还可以完全通过注解的方式定义spring容器,其实现类为AnnotationConfigApplicationContext,定义spring容器的类需要使用@Configurable、@Bean注解来定义bean。在正式项目中通常还是使用xml+注解的方式,一般都会将aop、定时任务等的相关配置放在xml中,普通的spring bean则用@Service等注解进行定义,这样后续维护的人可以清楚的了解系统中有哪些隐秘执行的程序,不至于出现问题时毫无头绪。
           纯xml定义或者纯注解的方式都容易理解,但spring如何解析xml和注解同时存在的情况?这就是spring设计的强大之处,spring内部通过实现自己提供的扩展点来实现解析的。当在xml文件中加入了<context:annotation-config>或者<context:component-scan base-package="com.jj" />时,spring会向容器中默认加入ConfigurationClassPostProcessor、CommonAnnotationBeanPostProcessor、AutowiredAnnotationBeanPostProcessor等bean实例。在下面创建beanFactory和实例化bean的伪代码中可以找到其被调用的地方,大家可以通过查看其源码来理解spring具体的实现方法。

    context解析spring xml配置文件时需要使用BeanDefinationReader,其类图如下:
    Spring源码阅读(一):IOC容器的初始化


    为了更好的理解记忆context的创建过程,整理了如下伪代码用于描述ContextLoader初始化ApplicationContext的过程:

    ContextLoaderListener.contextInitialized(ServletContextEvent event) {
    	//listener继承自ContextLoader,因此下面这句其实是执行ContextLoaderListener父类的方法
    	ContextLoader.initWebApplicationContext(event.getServletContext()){
    		this.createWebApplicationContext(ServletContext sc, ApplicationContext parent){
    			/*
    			determineContextClass方法是先从servlet上下文中获取初始化参数servletContext.getInitParameter("contextClass"),
    			如果该方法获取不到则从ContextLoader.properties获取,所以基本上我们在web中使用的都是XmlWebApplicationContext作为Spring容器上下文的实例。
    			如果我们不使用web容器,那么最常使用的是ClassPathXmlApplicationContext
    			*/
    			Class<?> contextClass = determineContextClass(sc);
    			ConfigurableWebApplicationContext wac =(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
    			//下面这句开启了beanFactory的初始化
    			wac.refresh();
    		}
    	}
    }

     

  2. 创建beanFactory

    beanFactory是实现IOC的核心,其作用如下:

    • 创建singleton类型的bean并缓存。
    • 缓存prototype类型的beanFactory对象。
    • 调用factory创建时拦截器BeanFactoryPostProcessor、bean创建时拦截器BeanPostProcessor,实现spring bean最核心的扩展点。

    其类图如下:


    Spring源码阅读(一):IOC容器的初始化

    如下伪代码描述了ApplicationContext创建BeanFactory的过程:

    AbstractApplicationContext.refresh(){
    	ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(){
    		//AbstractRefreshableApplicationContext继承自AbstractApplicationContext
    		AbstractRefreshableApplicationContext.refreshBeanFactory(){
    			//创建DefaultListableBeanFactory实例                                       ---1:创建beanFactory
    			DefaultListableBeanFactory beanFactory = createBeanFactory();
    			//根据资源配置加载bean定义                                                 ---2:加载beanDefinition并缓存起来
    			XmlWebApplicationContext.loadBeanDefinitions(beanFactory){
    				BeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
    				//如果是web工程则会通过web.xml中initParam参数查找configLocations配置
    				for (String configLocation : configLocations) {
    					//将配置文件的解析工作委托给BeanDefinitionReader
    					reader.loadBeanDefinitions(configLocation){
    						//调用实际执行解析的方法
    						reader.registerBeanDefinitions(Document doc, Resource resource){
    							//创建reader上下文,之所以创建context是为了触发bean解析后的相关注册事件
    							ReaderContext readerContext = new XmlReaderContext(reader);
    							//创建实际执行Document解析工作的BeanDefinitionDocumentReader
    							BeanDefinitionDocumentReader documentReader = new DefaultBeanDefinitionDocumentReader();
    							//调用其解析方法并将解析后的结果存储在registry(即beanFactory中,因为beanFactory实现了BeanDefinitionRegistry接口)
    							documentReader.registerBeanDefinitions(doc, readerContext){
    								Element root = doc.getDocumentElement();
    								//创建真正执行解析的工具类BeanDefinitionParserDelegate
    								BeanDefinitionParserDelegate delegate =  = new BeanDefinitionParserDelegate(readerContext);
    								documentReader.parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate){
    									for(Element ele : root.elements()){
    //判断节点类型
    										if (delegate.isDefaultNamespace(ele)) {
    											documentReader.parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate){
    												//根据ele节点类型来判断调用以下哪个方法
    												importBeanDefinitionResource(Element ele);
    												processAliasRegistration(Element ele);
    												//以bean节点的解析为例
    												processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate){
    													//解析出bdHolder对象,该对象包括beanName和beanDefinition
    													BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    													//将beanDefinition对象注册到registry bean定义缓存中
    													BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
    													//获取reader上下文执行bean解析后的监听事件
    													getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    												}
    											}
    										} else {
    											delegate.parseCustomElement(ele){
    												/*
    												 *解析各种特殊的节点如context:component-scan等
    												 *NamespaceHandlerResolver是由XmlBeanDefinitionReader.createReaderContext进行初始化,其中包含了各种自定义命名空间的处理类。
    												 *如context命名空间的解析类为ContextNamespaceHandler
    												 */
    												//此处获取handler时会调用其init方法,向handler中注册各种节点的解析器
    												NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
    												handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)){
    													//查找节点对应的解析器
    													//如component-scan对应的解析器为ComponentScanBeanDefinitionParser,此处会调用其parse方法时会调用ClassPathBeanDefinitionScanner.doScan方法扫描base-package指定的包中含有@Component注解的类并解析成beanDefinition注册到beanFactory
    													handler.findParserForElement(element, parserContext).parse(element, parserContext)
    												}
    											}
    										}
    									}
    								}
    							}
    						}
    					}
    				}
    			}
    		}
    	}
    	//可用来向beanFactory中添加自定义的拦截器, 如AbstractRefreshableWebApplicationContext中添加的ServletContextAwareProcessor
    	postProcessBeanFactory(beanFactory);
    	//从beanFactory中找到BeanFactoryPostProcessor的实现类并执行
    	invokeBeanFactoryPostProcessors(beanFactory){
    		//获取BeanDefinitionRegistryPostProcessor,该拦截器可由向beanDefineRegistry中添加bean定义
    		//spring内部有扩展该接口,如ConfigurationClassPostProcessor(当spring配置中加入了context:component-scan时,该bean会被注册到容器中)用于处理添加了@Configuration @Bean注解的bean,将其解析成beanDefine并添加到beanFactory中缓存起来
    		Map<String, BeanDefinitionRegistryPostProcessor> beanMap =
    					beanFactory.getBeansOfType(BeanDefinitionRegistryPostProcessor.class, true, false);
    		if(beanbFactory instanceOf BeanDefinitionRegistry){
    			BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry((BeanDefinitionRegistry) beanFactory);
    		} else {
    			BeanDefinitionRegistryPostProcessor.postProcessBeanFactory(beanFactory);
    		}
    	}
    	//从beanFactory中找到BeanPostProcessor的实现类实体bean定义,调用getBean方法实例化并注册到beanFactory中
    	registerBeanPostProcessors(beanFactory){
    		//BeanPostProcessor的注册顺序:首先是实现了PriorityOrdered接口的,然后是实现了Ordered 然后是没用排序接口的nonOrdered 最后是MergedBeanDefinitionPostProcessor的实现类
    		//当配置文件中加入了context:component-scan后spring会加入MergedBeanDefinitionPostProcessor的内部实现类PersistenceAnnotationBeanPostProcessor、
    		registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors);
    	}
    	//Initialize message source for this context.
    	initMessageSource();
    
    	//初始化上下文中的应用事件广播器
    	initApplicationEventMulticaster();
    	//与registerBeanPostProcessors类似,从beanFactory中获取ApplicationListener的实现类
    	registerListeners();
    	
    	//bean实例化(此时处理的基本只有用户自定义的普通bean,像BeanPostProcessor等扩展bean都已经提前实例化好了,所以在实例化普通bean时可以直接调用了)
    	finishBeanFactoryInitialization();
    }


     

  3. 实例化bean

    如下伪代码用于描述spring内部的调用顺序:

    BeanFactory实例化Bean的过程
    AbstractApplicationContext.refresh(){
    	//完成bean的实例化
    	AbstractApplicationContext.finishBeanFactoryInitialization(){
    		DefaultListableBeanFactory.preInstantiateSingletons(){
    			List<String> beanNames = new ArrayList<String>(DefaultListableBeanFactory.beanDefinitionNames);
    			//遍历bean定义集合,预先实例化singleton类型bean
    			for (String beanName : beanNames) {
    				AbstractBeanFactory.getBean(beanName){
    					AbstractBeanFactory.doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly){
    						if (RootBeanDefinition.isSingleton()) {
    							//此处可以看出spring的bean都是从ObjectFactory生产出来的,如果是singleton等非自定义的工厂对象,那么最终工厂还是会去调用beanFactory里面的方法。
    							ObjectFactory singletonFactory = new ObjectFactory() {
    								public Object getObject() throws BeansException {
    									try {
    										return AbstractBeanFactory.createBean(beanName, mbd, args);
    									}
    									catch (BeansException ex) {
    										// Explicitly remove instance from singleton cache: It might have been put there
    										// eagerly by the creation process, to allow for circular reference resolution.
    										// Also remove any beans that received a temporary reference to the bean.
    										destroySingleton(beanName);
    										throw ex;
    									}
    								}
    							}
    							//调用bean缓存器来获取bean,如果缓存中没有则需要继续调用beanFactory的createBean方法来创建bean。
    							DefaultSingletonBeanRegistry.getSingleton(String beanName, singletonFactory){
    								Object singletonObject = singletonFactory.getObject(){
    									AbstractAutowireCapableBeanFactory.createBean(String beanName, RootBeanDefinition mbd, Object[] args){
    										AbstractAutowireCapableBeanFactory.doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
    											//创建Bean对象包装器,该包装器提供setProperty等方法供后续填充bean属性及解决依赖使用
    											BeanWrapper instanceWrapper = AbstractAutowireCapableBeanFactory.createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args){
    												AbstractAutowireCapableBeanFactory.instantiateBean(final String beanName, final RootBeanDefinition mbd){
    													//实际的bean创建方式可以是直接实例化创建也可以是用cglib等代理创建的对象,此处默认用的是CglibSubclassingInstantiationStrategy
    													//将真实的创建方式进行了策略抽象,这样就可以用不同的代理框架 可以自定义实现
    													SimpleInstantiationStrategy.instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner){
    														//CglibSubclassingInstantiationStrategy.instantiateWithMethodInjection(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner){
    														//}
    														BeanUtils.instantiateClass(constructorToUse);
    													}
    												}
    											}
    											//执行AbstractApplicationContext.ApplicationListenerDetector处理器,作为后续添加到context applicationListener的先决条件
    											//调用MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition方法
    											/*
    											 *执行beanFactory创建时调用registerBeanPostProcessors方法所加入的MergedBeanDefinitionPostProcessor内部实现类,用于完善RootBeanDefinition定义
    											 *PersistenceAnnotationBeanPostProcessor用来完善jpa相关注解的解析
    											 *AutowiredAnnotationBeanPostProcessor
    											 *RequiredAnnotationBeanPostProcessor
    											 *CommonAnnotationBeanPostProcessor 解析字段和方法中的Resource webservice等注解,Resource注解字段信息会加入到externallyManagedConfigMembers中
    											 *
    											 */
    											applyMergedBeanDefinitionPostProcessors();
    											DefaultSingletonBeanRegistry.addSingletonFactory(String beanName, ObjectFactory singletonFactory);
    											//进行属性设置 依赖bean注入
    											AbstractAutowireCapableBeanFactory.populateBean(beanName, mbd, instanceWrapper){
    												//执行beanPostProcessors中InstantiationAwareBeanPostProcessor实现类的postProcessAfterInstantiation方法
    												InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(instanceWrapper.getWrappedInstance(), beanName);
    												/*
    												 *调用InstantiationAwareBeanPostProcessor.postProcessPropertyValues方法
    												 *CommonAnnotationBeanPostProcessor中会向Resource注解的字段注入相应的bean
    												 */
    												InstantiationAwareBeanPostProcessor.postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName);
    											}
    										}
    									}
    								}
    								//将创建的bean对象缓存起来
    								DefaultSingletonBeanRegistry.addSingleton(beanName, singletonObject);;
    							}
    						}
    					}
    				}
    			}
    		}
    	}
    }
    



相关标签: spring 源码