Spring源码分析

其余更多java基础文章:
java基础学习(目录)java


Spring源码太大了,对于一个技术不深的我来讲,第一次啃会很艰难,因而我决定一个模块一个模块的看,而且将在学习的过程当中,以为很不错的文章记录下来。建议你们先阅读推荐博客,而后再看个人补充。当前Spring版本4.3.18spring

Spring读取自定义xml文件解析

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
复制代码

重点

整个容器的启动流程,都在AbstractApplicationContext的refresh()的模板方法中了缓存

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

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

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } } 复制代码

下面讲解的重点是obtainFreshBeanFactory()这个方法。bash

推荐博客

  • 经过源码阅读和时序图来完全弄懂Spring容器:这篇文章阅读顺序很是好,顺着代码运行的顺序,而且有时序图辅助学习,可是单看这一篇,仍是有点迷茫,主要是对一些细节方面不够,并且总结也比较粗。应配合下面文章一块儿学习。
  • Spring Ioc 源码分析(一)--Spring Ioc容器的加载:这一系列一共有四章,对细节讲述比较清楚。分红三个模块来说解,对方法的总结和大白话描述多,更易理解。缺点就是顺序不够好,常常从这跳到另外一个地方。

总结

时序图我花时间从新画了一幅,可是流程太长,整条流程保存的画质不怎么好。因此我把总体和局部时序图都画出来,方便你们对比app

时序图(整)

时序图1

时序图2

时序图3

时序图4

下面是整个时序图的流转过程文字文字补充:源码分析

SpringMain->ClassPathXmlApplicationContext: new ClassPathXmlApplicationContext("applicationContext.xml");
ClassPathXmlApplicationContext->AbstractRefreshableConfigApplicationContext: setConfigLocations()
AbstractRefreshableConfigApplicationContext->ClassPathXmlApplicationContext: return
ClassPathXmlApplicationContext->AbstractApplicationContext: refresh()
AbstractApplicationContext->AbstractApplicationContext: obtainFreshBeanFactory()
AbstractApplicationContext->AbstractRefreshableApplicationContext: refreshBeanFactory()
AbstractRefreshableApplicationContext->AbstractXmlApplicationContext: loadBeanDefinitions()
AbstractXmlApplicationContext->AbstractXmlApplicationContext: loadBeanDefinitions()
AbstractXmlApplicationContext->AbstractBeanDefinitionReader: reader.loadBeanDefinitions(configLocations);
AbstractBeanDefinitionReader->AbstractBeanDefinitionReader: counter += loadBeanDefinitions(location);
AbstractBeanDefinitionReader->AbstractBeanDefinitionReader: return loadBeanDefinitions(location, null);
AbstractBeanDefinitionReader->XmlBeanDefinitionReader: int loadCount = loadBeanDefinitions(resource);
XmlBeanDefinitionReader->XmlBeanDefinitionReader: doLoadBeanDefinitions()
XmlBeanDefinitionReader->XmlBeanDefinitionReader: registerBeanDefinitions()
XmlBeanDefinitionReader->DefaultBeanDefinitionDocumentReader: registerBeanDefinitions(doc, createReaderContext(resource));
DefaultBeanDefinitionDocumentReader->DefaultBeanDefinitionDocumentReader: doRegisterBeanDefinitions()
DefaultBeanDefinitionDocumentReader->DefaultBeanDefinitionDocumentReader: parseBeanDefinitions()
DefaultBeanDefinitionDocumentReader->DefaultBeanDefinitionDocumentReader: parseDefaultElement()
DefaultBeanDefinitionDocumentReader->DefaultBeanDefinitionDocumentReader: processBeanDefinition()
DefaultBeanDefinitionDocumentReader->BeanDefinitionParserDelegate: parseBeanDefinitionElement()
BeanDefinitionParserDelegate->BeanDefinitionParserDelegate: parseBeanDefinitionElement(ele, beanName, containingBean);
note right of BeanDefinitionParserDelegate: parsePropertyElements(ele, bd);
BeanDefinitionParserDelegate->DefaultBeanDefinitionDocumentReader: return new BeanDefinitionHolder
DefaultBeanDefinitionDocumentReader->BeanDefinitionParserDelegate: decorateBeanDefinitionIfRequired
DefaultBeanDefinitionDocumentReader->BeanDefinitionReaderUtils: registerBeanDefinition
BeanDefinitionReaderUtils->DefaultListableBeanFactory: registerBeanDefinition
note right of DefaultListableBeanFactory: this.beanDefinitionMap.put(beanName, beanDefinition);
note right of DefaultListableBeanFactory: this.beanDefinitionNames.add(beanName);
DefaultListableBeanFactory->DefaultBeanDefinitionDocumentReader: return 
DefaultBeanDefinitionDocumentReader->AbstractApplicationContext: obtainFreshBeanFactory() is over,return DefaultListableBeanFactory
复制代码
  • parsePropertyElements(ele, bd);的时候,把类属性值放入bean中,并返回BeanDefinitionHolder。
  • this.beanDefinitionNames.add(beanName);this.beanDefinitionMap.put(beanName, beanDefinition);时,前者是把beanName放到队列里,后者是把BeanDefinition放到map中,到此注册就完成了。在后面实例化的时候,就是把beanDefinitionMap中的BeanDefinition取出来,逐一实例化

总结来讲:

  1. ApplicationContext将解析配置文件的工做委托给BeanDefinitionReader,而后BeanDefinitionReader将配置文件读取为xml的Document文档以后,又委托给BeanDefinitionDocumentReader
  2. BeanDefinitionDocumentReader这个组件是根据xml元素的命名空间和元素名,起到一个路由的做用,实际的解析工做,是委托给BeanDefinitionParserDelegate来完成的
  3. BeanDefinitionParserDelegate的解析工做完成之后,会返回BeanDefinitionHolder给BeanDefinitionDocumentReader,在这里,会委托给DefaultListableBeanFactory完成bean的注册
  4. XmlBeanDefinitionReader(计数、解析XML文档),BeanDefinitionDocumentReader(依赖xml文档,进行解析和注册),BeanDefinitionParserDelegate(实际的解析工做)。能够看出,在解析bean的过程当中,这3个组件的分工是比较清晰的,各司其职

getBean方法

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        JSONArray person = (JSONArray) context.getBean("aaa");
复制代码

推荐博客

补充

【Spring源码学习】getBean (上)中讲了一个BeanDefinitionParseDelegate #parseBeanDefinitionAttributes方法,该方法的执行位置是在上面读取自定义xml解析的时候,运行到BeanDefinitionParserDelegate #parseBeanDefinitionElement方法时,以下图post

流程图

GetBean源码全解读这篇文章的顺序比较混乱,我花时间从新画了下时序图,配合文章阅读更容易理解:学习

时序图文字补充:ui

SpringMain-> AbstractBeanFactory: getBean
AbstractBeanFactory-> AbstractBeanFactory#doGetBean: doGetBean
AbstractBeanFactory#doGetBean-> DefaultSingletonBeanRegistry: getSingleton(beanName)
AbstractBeanFactory#doGetBean-> AbstractBeanFactory#getObjectForBeanInstance: getObjectForBeanInstance
AbstractBeanFactory#doGetBean-> AbstractBeanFactory#getMergedLocalBeanDefinition: getMergedLocalBeanDefinition
AbstractBeanFactory#getMergedLocalBeanDefinition-> AbstractBeanFactory#getMergedLocalBeanDefinition: getMergedBeanDefinition
AbstractBeanFactory#doGetBean-> DefaultSingletonBeanRegistry: registerDependentBean
AbstractBeanFactory#doGetBean-> DefaultSingletonBeanRegistry: getSingleton
DefaultSingletonBeanRegistry-> DefaultSingletonBeanRegistry: beforeSingletonCreation
AbstractBeanFactory#doGetBean-> AbstractAutowireCapableBeanFactory#createBean: createBean
AbstractAutowireCapableBeanFactory#createBean-> AbstractAutowireCapableBeanFactory#doCreateBean: doCreateBean
AbstractAutowireCapableBeanFactory#doCreateBean-> AbstractAutowireCapableBeanFactory#createBeanInstance: createBeanInstance
AbstractAutowireCapableBeanFactory#createBeanInstance-> AbstractAutowireCapableBeanFactory#instantiateBean: instantiateBean
AbstractAutowireCapableBeanFactory#instantiateBean->SimpleInstantiationStrategy: instantiate
AbstractAutowireCapableBeanFactory#doCreateBean-> AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors: applyMergedBeanDefinitionPostProcessors
AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors-> AutowiredAnnotationBeanPostProcessor: postProcessMergedBeanDefinition
AutowiredAnnotationBeanPostProcessor-> AutowiredAnnotationBeanPostProcessor: findAutowiringMetadata
AutowiredAnnotationBeanPostProcessor-> AutowiredAnnotationBeanPostProcessor: buildAutowiringMetadata
AbstractAutowireCapableBeanFactory#doCreateBean-> AbstractAutowireCapableBeanFactory#populateBean: populateBean
AbstractAutowireCapableBeanFactory#populateBean-> AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues: postProcessPropertyValues
AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues-> InjectionMetadata: inject.
note right of InjectionMetadata: @Resource
AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues-> AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement: inject
note right of AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement: @Autowired&@Value
AbstractAutowireCapableBeanFactory#populateBean-> AbstractAutowireCapableBeanFactory#populateBean: applyPropertyValues
复制代码

AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata方法中,Spring会根据注解的不一样,例如@Resource或@AutoWired,分别建立不一样的类保存返回。这里建立的不一样的类会在InjectionMetadata #inject的时候起做用,会调用不一样类的inject方法,实现属性的注入。this

循环依赖

推荐博客

总结

三层缓存

/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);

/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);

/** Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
复制代码
缓存 用途
singletonObjects 用于存放彻底初始化好的 bean,从该缓存中取出的 bean 能够直接使用
earlySingletonObjects 存放原始的 bean 对象(还没有填充属性),用于解决循环依赖
singletonFactories 存放 bean 工厂对象,用于解决循环依赖

这里分别举这样三个例子。 A 依赖 B(B不依赖A)

一级缓存 A 依赖 B && B依赖A

三级缓存 A依赖B && B依赖A + B依赖C && C 依赖 A

相关文章
相关标签/搜索