先说层次架构
// 水桶和上下文类层次概要(还有如何打水)
// 当你在使用FileSystemXmlApplicationContext之类的类时,你会感觉里面的方法调用错综复杂,层次很多。
// 那么,我们先从主要类的作用和层次说起,让我们有个大体的概念和印象,便于后面的分析。
class Waterpot { // 水桶: // 顺序基本是按照继承的先后顺序 // ***************************基本接口定义分支*************************** // ==================最基本的两个接口============================= // 接口:最基本的,就是包括一些bean的获取,bean类型判断,别名数组获取等 // *org.springframework.beans.factory.BeanFactory // 接口:和他的名字Hierarchical一样,分层用的,获取父的beanFactory,和判断beanfactory是否存在指定的bean // *org.springframework.beans.factory.HierarchicalBeanFactory // ===========ConfigurableBeanFactory:bean factory的主要相关资源管理======== // 接口:HierarchicalBeanFactory的其中一种直接父接口(还包括ApplicationContext,也是HierarchicalBeanFactory的一种直接父接口) // 他的方法定义就比较多,包括(应该主要是bean factory操作需要的一些场景资源和环境指定等): // 设置beanfactory用的双亲(parentBeanFactory)、ClassLoader赋值、tempClassLoader赋值、Set // whether to cache bean metadata such as given bean definitions (in // merged fashion) and resolved bean // classes.、TypeConverter赋值、添加BeanPostProcessor等 // *org.springframework.beans.factory.config.ConfigurableBeanFactory // ===ConfigurableListableBeanFactory:对configurable、list、autowire的继承包含(主要就是对环境定义的深入整合)==== // 接口:前面做到了bean factory对bean的单个操作,这个主要是返回和操作多个返回结果 // *org.springframework.beans.factory.ListableBeanFactory // 接口:自动IoC注解的相关操作 // *org.springframework.beans.factory.config.AutowireCapableBeanFactory // 接口:主要是对前面主要接口的总结,并提供了preInstantiateSingletons方法。 // 主要还包括了,对自动装配的额外定义:忽略类型、忽略接口、指定绑定等 // *org.springframework.beans.factory.config.ConfigurableListableBeanFactory // ***************************额外特殊接口和实现分支*************************** // ====================各种bean注册============================== // 接口:别名操作的定义 // *org.springframework.core.AliasRegistry // 实现:对别名的管理(主要是维护了别名的map) // *org.springframework.core.SimpleAliasRegistry // 接口:单例方式bean的管理定义,包括注册获取和判断等 // *org.springframework.beans.factory.config.SingletonBeanRegistry // 实现:继承了别名管理实现,并实现了单例注册(自己主要实现了单例注册接口,并管理着各种类型数据的map集合) // *org.springframework.beans.factory.support.DefaultSingletonBeanRegistry // 接口:主要是对BeanDefinition的注册相关定义(BeanDefinition是bean的第二步原始数据--第一步dom解析数据) // *org.springframework.beans.factory.support.BeanDefinitionRegistry // ***************************各种接口的整合实现*************************** // =========================对各种原始数据的操作================================== // 实现:对单例的获取和维护,对DefaultSingletonBeanRegistry进行了封装 // *org.springframework.beans.factory.support.FactoryBeanRegistrySupport // 实现:实现了ConfigurableBeanFactory,也就是对资源管理的实现。且对FactoryBeanRegistrySupport继承,做了对bean获取的更进一步封装。 // 这里已经不局限于单例的获取,还包括非单例,从父工厂获取判断等 // *org.springframework.beans.factory.support.AbstractBeanFactory // 实现:对AutowireCapableBeanFactory接口的实现,并继承了AbstractBeanFactory // *org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory // 实现:我们主要的基本容器实现。(再往下走会有各种applicationContext),但是原始数据BeanDefinition的水桶和单例的水桶主要就是DefaultListableBeanFactory // *org.springframework.beans.factory.support.DefaultListableBeanFactory }
class Context { // 上下文 // =========================最底层上下文:ApplicationContext================================== // 接口:环境Environment的获取 // *org.springframework.core.env.EnvironmentCapable // 接口:参数化和国际化等消息的支持下解决的消息,策略接口。 // *org.springframework.context.MessageSource // 接口:接收ApplicationEvent // *org.springframework.context.ApplicationEventPublisher // 接口:获取资源 // *org.springframework.core.io.support.ResourcePatternResolver // 接口:上下文最基础的接口,除继承了上面的接口外,还继承了容器的ListableBeanFactory, // HierarchicalBeanFactory的两个接口 // *org.springframework.context.ApplicationContext // ==============================ConfigurableApplicationContext======================================= // 接口:The typical use case for this is to control asynchronous processing. // 很多执行控制接口都继承自本接口 // *org.springframework.context.Lifecycle // 接口:从ApplicationContext继承了上下文的基本功能外,又定义了大量的环境配置接口(包括:setEnvironment、addBeanFactoryPostProcessor、addApplicationListener、registerShutdownHook)。还有主要的入口refresh() // *org.springframework.context.ConfigurableApplicationContext // ==============================上线文基本方法实现:AbstractApplicationContext======================================= // 接口:销毁动作,销毁单例类 // *org.springframework.beans.factory.DisposableBean // 接口:加载资源的策略接口 // *org.springframework.core.io.ResourceLoader // 实现:默认的资源加载 // *org.springframework.core.io.DefaultResourceLoader // 实现:上线文基本方法实现(包括加载和刷新的入口、初始化容器开始时间等、刷新重建BeanFactory入口(具体的refreshBeanFactory留由子类完成)、准备bean // factory(主要声明了classLoader、添加BeanPostProcessor // 、自动装配忽略接口、自动装配类型匹配指定、注册各种单例等)、调用BeanFactory的后处理器,这些后处理器是在Bean定义中向容器注册的 // 、对上下文中的消息源进行初始化、初始化上下文中的事件机制、检查监听bean并且将这些bean向容器注册、实例化所有的(non-lazy-init)单例、发布容器事件,结束Refresh过程) // *org.springframework.context.support.AbstractApplicationContext // ==============================刷新和重建BeanFactory:AbstractRefreshableApplicationContext================== // 实现:比较重要的实现方法refreshBeanFactory,刷新和重建BeanFactory // *org.springframework.context.support.AbstractRefreshableApplicationContext // ==============================AbstractRefreshableConfigApplicationContext============================== // 接口:bean factory的名称 // *org.springframework.beans.factory.BeanNameAware // *org.springframework.beans.factory.InitializingBean // 实现:Config的设置 // *org.springframework.context.support.AbstractRefreshableConfigApplicationContext // ==============================AbstractXmlApplicationContext============================== // 实现:主要是loadBeanDefinitions的实现,内部指定XmlBeanDefinitionReader方式读取 // *org.springframework.context.support.AbstractXmlApplicationContext // ClassPathXmlApplicationContext、FileSystemXmlApplicationContext // 启动入口和“个性”资源加载 }
// =====================================================解析相关============================================
// 解析第一步:读取资源
class Reader { // ===================================资源读取:XmlBeanDefinitionReader=================================== // 分析下XmlBeanDefinitionReader组织层次 // 接口:读取解析的基础接口,主要就是四个loadBeanDefinitions定义,负责读取的定义,但是不包含读取后的注册定义等。 // *org.springframework.beans.factory.support.BeanDefinitionReader // 实现:简单封装实现了BeanDefinitionReader(String类型资源加载、Resource多参数遍历、各种资源的获取和赋值定义)和EnvironmentCapable两个接口。 // (具体如何读取交给了子类包含Resource参数的接口定义中去完成) // *org.springframework.beans.factory.support.AbstractBeanDefinitionReader // 实现:XML格式文件读取,最终实现提供类。具体指定了读取规则,和注册规则。(具体的读取和注册还要往下走) // *org.springframework.beans.factory.xml.XmlBeanDefinitionReader }
// 解析第二步:Document读取
// DefaultDocumentLoader,dom解析就不说了,和我们平时做dom解析应该没太大区别,我们平时可以借助很多不错的第三方框架。
// 解析第二步半:BeanDefinitionDocumentReader(资源整合,或者说功能抽取)
class MyBeanDefinitionDocumentReader { // ===================================通过Reader返回的Document获取注册匹配的BeanDefinition:BeanDefinitionDocumentReader========================= // 接口:SPI for parsing an XML document that contains Spring bean definitions. // Used by XmlBeanDefinitionReader for actually parsing a DOM document. // *org.springframework.beans.factory.xml.BeanDefinitionDocumentReader // 实现:供Reader调用。结合了DocumentLoader读取的Document和XmlReaderContext。 // *org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader }
// 解析第三步:通过Document解析成BeanDefinition
class MyBeanDefinitionParserDelegate { // 工具类:根绝规则做的各种解析方法 // *org.springframework.beans.factory.xml.BeanDefinitionParserDelegate // 然后就是通过工具类,帮助封装注册进DefaultListableBeanFactory }
再说执行过程
==============================FileSystemXmlApplicationContext==============================
*org.springframework.context.support.FileSystemXmlApplicationContext
比较常用的ApplicationContext有多种,我们选择一种FileSystemXmlApplicationContext进行入口分析。(几种ApplicationContext实现的区分基本在于资源获取方式和解析方式不同)
创建:
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super(parent); //设置资源路径,由子类AbstractRefreshableConfigApplicationContext完成 setConfigLocations(configLocations); //Load or refresh the persistent representation of the configuration, which might an XML file, properties file, or relational database schema. //进行了加载资源,销毁以前容器,创建容器,资源解析,Instantiate all remaining (non-lazy-init) singletons, if (refresh) { refresh(); } }
*1:refresh():(由最基础实现类AbstractApplicationContext提供)
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. //这里是在子类中启动refreshBeanFactory()的地方 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. //设置BeanFactory的后置处理 postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. //调用BeanFactory的后处理器,这些后处理器是在Bean定义中向容器注册的 invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. //注册Bean的后处理器,在bean的创建过程中被调用 registerBeanPostProcessors(beanFactory); // Initialize message source for this context. //对上下文中的消息源进行初始化 initMessageSource(); // Initialize event multicaster for this context. //初始化上下文中的事件机制 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. //初始化其他的特殊bean onRefresh(); // Check for listener beans and register them. //检查监听bean并且将这些bean向容器注册 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. //实例化所有的(non-lazy-init)单例 finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. //发布容器事件,结束Refresh过程 finishRefresh(); } catch (BeansException ex) { // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } } }
**1.1:容器获取、数据解析入口:obtainFreshBeanFactory()具体实现refreshBeanFactory()留给子类实现
(因为AbstractApplicationContext就是具体的通用的资源准备,具体的计息读取规则应该由各分支子类实现):
AbstractRefreshableApplicationContext---refreshBeanFactory
@Override protected final void refreshBeanFactory() throws BeansException { //这里判断,如果已经建立BeanFactory,则销毁并关闭该BeanFactory if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } //这里是创建并设置持有的DefaultListableBeanFactory的地方同时调用loadBeanDefinitions(beanFactory)再载入BeanDefinition的信息。 try { DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); //BeanFactoryAware等资源的配置 customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
***1.1.1:需要注意的是我们以后要用的BeanFactory--DefaultListableBeanFactory:
protected DefaultListableBeanFactory createBeanFactory() { (也就是水桶,具体的水桶并不由ApplicationContext提供,而是由BeanFactory分支实现提供) return new DefaultListableBeanFactory(getInternalParentBeanFactory()); }
****1.1.1.1:创建之后会赋值给AbstractRefreshableApplicationContext的变量:
/** Bean factory for this context */ private DefaultListableBeanFactory beanFactory;
****1.1.1.2:并实现了AbstractApplicationContext声明的获取方法:
@Override public final ConfigurableListableBeanFactory getBeanFactory() { synchronized (this.beanFactoryMonitor) { if (this.beanFactory == null) { throw new IllegalStateException("BeanFactory not initialized or already closed - " + "call 'refresh' before accessing beans via the ApplicationContext"); } return this.beanFactory; } }
****1.1.1.3:同步的锁:
/** Synchronization monitor for the internal BeanFactory */ private final Object beanFactoryMonitor = new Object();
***1.1.2加载解析Bean的原始封装数据:BeanDefinitions -- loadBeanDefinitions(beanFactory)
这里主要指定了读取工具类(XmlBeanDefinitionReader),和执行解析入口。因为,我们的配置可以是多种形式的,这里需要具体资源形式的子类(AbstractXmlApplicationContext)去实现。
AbstractXmlApplicationContext:
@Override protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // Create a new XmlBeanDefinitionReader for the given BeanFactory. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // Configure the bean definition reader with this context's // resource loading environment. beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // Allow a subclass to provide custom initialization of the reader, // then proceed with actually loading the bean definitions. initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); }
****1.1.2.1这里的application environment的值是由最开始FileSystemXmlApplicationContext构造器中super(parent),一路调用父类构造器,最终在
AbstractApplicationContext中实现:
public AbstractApplicationContext(ApplicationContext parent) { this.parent = parent; this.resourcePatternResolver = getResourcePatternResolver(); this.environment = this.createEnvironment(); } /** * Create and return a new {@link StandardEnvironment}. *
Subclasses may override this method in order to supply * a custom {@link ConfigurableEnvironment} implementation. */ protected ConfigurableEnvironment createEnvironment() { return new StandardEnvironment(); }
****1.1.2.2ResourceLoader是通过继承获得(AbstractApplicationContext extends DefaultResourceLoader)
****1.1.2.3EntityResolver:Allow the application to resolve external entities.
通过下面两个常量,我们可以猜是对格式规范的读取
public class DelegatingEntityResolver implements EntityResolver { /** Suffix for DTD files */ public static final String DTD_SUFFIX = ".dtd"; /** Suffix for schema definition files */ public static final String XSD_SUFFIX = ".xsd"; public DelegatingEntityResolver(ClassLoader classLoader) { this.dtdResolver = new BeansDtdResolver(); this.schemaResolver = new PluggableSchemaResolver(classLoader); } ... }
****1.1.2.4为XmlBeanDefinitionReader准备好各种所需的资源后,就开始真正解析了:
这里是对我们前面赋值的资源便利读取:
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { Resource[] configResources = getConfigResources(); if (configResources != null) { reader.loadBeanDefinitions(configResources); } String[] configLocations = getConfigLocations(); if (configLocations != null) { reader.loadBeanDefinitions(configLocations); } }
*********1.1.2.4.1目前主要是下面那个String[]数组。
赋值的地方在AbstractRefreshableConfigApplicationContext(这也是我们为什么在AbstractRefreshableApplicationContext的基础上有多了个AbstractRefreshableConfigApplicationContext原因,单独为资源赋值形式抽取封装):
public void setConfigLocations(String[] locations) { if (locations != null) { Assert.noNullElements(locations, "Config locations must not be null"); this.configLocations = new String[locations.length]; for (int i = 0; i < locations.length; i++) { this.configLocations[i] = resolvePath(locations[i]).trim(); } } else { this.configLocations = null; } }
此方法调用是在我们上面的FileSystemXmlApplicationContext构造器中。
(所以到这里,可以看到,我们上面出现了很多很多不同地方,不同形式的赋值,这些赋值在以后的解析等过程中进行了各自的作用)
到这里我们ApplicationContext关于解析的工作告一段落,然后就是XmlBeanDefinitionReader如何具体解析:
上面准备了和计算出了很多环境条件,然后接下来就是具体的如何通过Xml解析成最初的Bean类型BeanDefinition
===================================解析===================================
1、开始是一连串的AbstractBeanDefinitionReader处理,做了他可以做的事情之后,具体的又交给了父类,也就是上面指定的XmlBeanDefinitionReader
2、XmlBeanDefinitionReader也有做了一大串的判断,在doLoadBeanDefinitions方法中调用了DefaultDocumentLoader的loadDocument获取了Document
3、然后又把一些资源和Document传给了DefaultBeanDefinitionDocumentReader,DefaultBeanDefinitionDocumentReader又做了一些介于Reader和纯Document解析之间的一些工作,包括各种解析判断走向什么的。
4、然后又通过BeanDefinitionParserDelegate,BeanDefinitionParserDelegate只接收了Element,根绝我们的规则解析出了BeanDefinitionHolder
5、最后我们又通过BeanDefinitionReaderUtils,把我们解析出的BeanDefinition注解进我们的容器DefaultListableBeanFactory。