先说层次架构
// 水桶和上下文类层次概要(还有如何打水)
// 当你在使用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}.
* <p>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。