从FileSystemXmlApplicationContext开始
ApplicationContext applicationContext = new FileSystemXmlApplicationContext(xmlPath);
由上面的入口进入到构造方法中
public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public FileSystemXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
//从此处开始IOC容器的初始化
refresh();
}
}
设置好配置资源的路径之后,就会调用refresh()方法进行容器的初始化
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
/**
* 加载或刷新一个持久化的配置,可能是XML文件、属性文件或关系数据库模式。
* 由于这是一种启动方法,如果失败,应该销毁已经创建的单例,以避免悬空资源。
* 换句话说,在调用该方法之后,要么全部实例化,要么完全不实例化。
* @throws 如果bean工厂无法初始化,则抛出 BeansException 异常
* @throws 如果已经初始化且不支持多次刷新,则会抛出 IllegalStateException 异常
*/
@Override
public void refresh() throws BeansException, IllegalStateException {
// 给容器refresh加锁,避免容器处在refresh阶段时,容器进行了初始化或者销毁的操作
synchronized (this.startupShutdownMonitor) {
// 调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识,具体方法
prepareRefresh();
//告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从
//子类的refreshBeanFactory()方法启动,里面有抽象方法
//针对xml配置,最终创建内部容器,该容器负责 Bean 的创建与管理,此步会进行BeanDefinition的注册
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 注册一些容器中需要的系统Bean.例如classloader,beanfactoryPostProcessor等
prepareBeanFactory(beanFactory);
try {
//允许容器的子类去注册postProcessor ,钩子方法
postProcessBeanFactory(beanFactory);
// 激活在容器中注册为bean的BeanFactoryPostProcessors
//对于注解容器,org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
//方法扫描应用中所有BeanDefinition并注册到容器之中
invokeBeanFactoryPostProcessors(beanFactory);
// 注册拦截bean创建过程的BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// 找到“messageSource”的Bean提供给ApplicationContext使用,
// 使得ApplicationContext具有国际化能力。
initMessageSource();
// 初始化ApplicationEventMulticaster该类作为事件发布者,
// 可以存储所有事件监听者信息,并根据不同的事件,通知不同的事件监听者。
initApplicationEventMulticaster();
// 预留给 AbstractApplicationContext 的子类用于初始化其他特殊的 bean,
// 该方法需要在所有单例 bean 初始化之前调用
// 比如Web容器就会去初始化一些和主题展示相关的Bean(ThemeSource)
onRefresh();
// 注册监听器(检查监听器的bean并注册它们)
registerListeners();
//设置自定义的类型转化器ConversionService,
// 设置自定义AOP相关的类LoadTimeWeaverAware,
// 清除临时的ClassLoader
// ,实例化所有的类(懒加载的类除外)
finishBeanFactoryInitialization(beanFactory);
// 初始化容器的生命周期事件处理器,(默认使用DefaultLifecycleProcessor),调用扩展了SmartLifecycle接口的start方法
// 当Spring容器加载所有bean并完成初始化之后,会接着回调实现该接口的类中对应的方法(start()方法)
// 并发布容器刷新完毕事件ContextRefreshedEvent给对应的事件监听者
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.
//销毁已创建的Bean
destroyBeans();
// Reset 'active' flag.
//取消refresh操作,重置容器的同步标识
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// 重置Spring内核中的共用的缓存,因为我们可能再也不需要单例bean的元数据了……
resetCommonCaches();
}
}
}
}
AbstractApplicationContext的refresh()方法是容器刷新都会执行的方法,在refresh()方法里面配置的解析逻辑都在obtainFreshBeanFactory()方法中进行。
跟进obtainFreshBeanFactory方法
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//调用子类容器的refreshBeanFactory()刷新子类容器
refreshBeanFactory();
return getBeanFactory();
}
跟进refreshBeanFactory()方法,该方法由其子类AbstractRefreshableApplicationContext提供
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
@Override
protected final void refreshBeanFactory() throws BeansException {
//如果已经有容器,销毁容器中的bean,关闭容器
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
//创建容器
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
//对容器进行定制化,默认主要设置是否允许BeanDefinition的重复注册,
// Bean之间是否允许循环引用等,此外还可以设置启动参数,开启注解的自动装配等
customizeBeanFactory(beanFactory);
//加载BeanDefinition,for xml,使用了委派模式
loadBeanDefinitions(beanFactory);
//将 BeanFactory 设置为 Spring 容器的内部 BeanFactory
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
}
xml方式加载BeanDefinition,跟进loadBeanDefinitions(beanFactory)
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
// 1、为给定的BeanFactory创建一个新的XmlBeanDefinitionReader
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
// 2、设置 BeanDefinitionReader 的相关属性
// 2.1.设置 Environment,即环境,与容器的环境一致
beanDefinitionReader.setEnvironment(this.getEnvironment());
// 2.2.设置 ResourceLoader,即资源加载器,因为容器实现了该接口,具体加载资源的功能
beanDefinitionReader.setResourceLoader(this);
// 2.3.设置 EntityResolver,即实体解析器,这里用于解析资源加载器加载的资源内容
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
// 3.初始化 BeanDefinitionReader ,空方法,允许子类提供阅读器的自定义初始化
// 钩子方法,允许子类在加载bean definition之前进一步设置XmlBeanDefinitionReader
// ->比如,更改XmlBeanDefinitionReader自己提供的DocumentLoader
// 或者BeanDefinitionDocumentReader等默认对象
initBeanDefinitionReader(beanDefinitionReader);
// 4.通过 BeanDefinitionReader 加载 Bean
loadBeanDefinitions(beanDefinitionReader);
}
}
观察代码,该方法的主要目的是创建了BeanDefinitionReader ,并由它去加载 Bean。其过程如下:
- 创建 BeanDefinitionReader
- 设置 BeanDefinitionReader 的相关属性
- 初始化 BeanDefinitionReader
- 通过 BeanDefinitionReader 加载 Bean
通过 BeanDefinitionReader 加载 Bean
在创建完 BeanDefinitionReader 后,则就需要通过它来 加载 Bean,接着跟进loadBeanDefinitions(beanDefinitionReader)方法
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {
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);
}
}
}
接着跟进reader.loadBeanDefinitions(configLocations)
public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader, EnvironmentCapable {
@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
int count = 0;
for (String location : locations) {
count += loadBeanDefinitions(location);
}
return count;
}
}
根据locations逐个调用loadBeanDefinitions(location)加载
通过 Location 加载 Bean
加载的 Bean 的责任被交给了 BeanDefinitionReader ,下面来看看该类的 loadBeanDefinitions 方法。在跟进loadBeanDefinitions(String location)方法
public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader, EnvironmentCapable {
@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
// 1.取得资源加载器,即容器本身
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
}
// 判断资源加载器类型
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
// 说明该 ResourceLoader 可以基于路径加载多个资源
try {
// 2.加载资源
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
// 3.通过 Resource 加载 Bean
int count = loadBeanDefinitions(resources);
if (actualResources != null) {
Collections.addAll(actualResources, resources);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
}
return count;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// Can only load single resources by absolute URL.
// 表示 ResourceLoader 只能加载一个资源
Resource resource = resourceLoader.getResource(location);
int count = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
}
return count;
}
}
}
该方法的工作流程:
- 取得资源加载器
- 加载资源,通过 location 利用 ResourcePatternResolver加载
- 通过 Resource 加载 Bean
接着在跟进loadBeanDefinitions(resources)方法
public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader, EnvironmentCapable {
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int count = 0;
for (Resource resource : resources) {
count += loadBeanDefinitions(resource);
}
return count;
}
}
通过 Resource 加载 Bean
在得到资源(Resource)后,该方法对它进行了封装,使其变成一个 EncodedResource 对象。
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
// EncodedResource 表示编码类型的资源
return loadBeanDefinitions(new EncodedResource(resource));
}
}
通过 EncodedResource 加载 Bean
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Loading XML bean definitions from " + encodedResource);
}
// 1.取得[已加载的资源]的集合,用于存在已加载的资源。空,则创建。
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
// 2.将当前资源加入集合
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
// 3.将资源转换成流
try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
//5.通过流创建 InputSource ,并设置编码
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
//6.调用同类方法,通过 InputSource 加载 Bean
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
// 移除已完成解析的资源
currentResources.remove(encodedResource);
// 集合为空,则一并删除
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
}
加载步骤:
- 1、取得已加载的资源集合
- 2、将当前资源添加到集合
- 3、将资源转换成流
- 4、通过流创建 InputSource ,并设置编码
- 5、通过 InputSource 加载 Bean
通过 InputSource 加载 Bean
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 1.解析 XML 文件
//创建Document对象,XML的文档对象,就是dom树
// 使用这个Document可以获取XML文件中的节点并且创建节点
// SAX XML
//将InputSource转换为DOM对象,解析过程由documentLoader实现
Document doc = doLoadDocument(inputSource, resource);
// 2.注册 Bean
//解析dom树,即解析出一个个属性,将其保存到BeanDefinition当中
//并向容器注册BeanDefinition
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (SAXParseException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
}
catch (SAXException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"XML document from " + resource + " is invalid", ex);
}
catch (ParserConfigurationException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Parser configuration exception parsing XML from " + resource, ex);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"IOException parsing XML document from " + resource, ex);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}
}
解析并注册 BeanDefinitions
将文件装换为Document以后,接下来的提取以及注册Bean就是我们的重头戏。
上一步中 XmlBeanDefinitionReader 已经取得了 XML 的 Document 对象,完成了资源的解析过程。
下一步就是 Bean 的注册过程。
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//创建BeanDefinitionDocumentReader,这个是实际从XML的DOM树中读取BeanDefiniton
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//获取注册表beanDefinitionMap的在本次加载前的BeanDefinition数量
int countBefore = getRegistry().getBeanDefinitionCount();
//加载并注册
//这里使用到了单一职责原则,将逻辑处理委托给单一的类进行处理,这个逻辑处理类就是 BeanDefinitionDocumentReader 对象
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
//本次加载注册后容器里BeanDefinition的数量减去先前的,即本次加载的BeanDefinition数量
return getRegistry().getBeanDefinitionCount() - countBefore;
}
}
继续深入registerBeanDefinitions方法:
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
doRegisterBeanDefinitions(doc.getDocumentElement());
}
}
继续深入doRegisterBeanDefinitions方法:doRegisterBeanDefinitions算开始真正解析XML文件了。
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
protected void doRegisterBeanDefinitions(Element root) {
// Any nested <beans> elements will cause recursion in this method. In
// order to propagate and preserve <beans> default-* attributes correctly,
// keep track of the current (parent) delegate, which may be null. Create
// the new (child) delegate with a reference to the parent for fallback purposes,
// then ultimately reset this.delegate back to its original (parent) reference.
// this behavior emulates a stack of delegates without actually necessitating one.
//BeanDefinition解析委托类
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
//判断这个根节点是否是默认的命名空间
//底层就是判断这个根节点的NamespaceUrl=="http://www.springframework.org/schema/beans"
if (this.delegate.isDefaultNamespace(root)) {
//获取这个profile属性的值,表示剖面,用于设置环境
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
//根据分隔符换换成数组
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
// We cannot use Profiles.of(...) since profile expressions are not supported
// in XML config. See SPR-12458 for details.
//判断这个切面是否是激活的环境,如果不是直接返回,表示这个配置文件不是当前运行环境的配置文件
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
//在解析xml之前做的准备工作,其实什么也没做
//空代码留给子类去实现 模板设计模式 继承 DefaultBeanDefinitionDocumentReader 的子类在XML解析前做一些处理,可以实现此方法
preProcessXml(root);
//调用这个方法,解析
parseBeanDefinitions(root, this.delegate);
//后续处理的
//空代码留给子类去实现 模板设计模式 继承 DefaultBeanDefinitionDocumentReader 的子类在XML解析后做一些处理,可以实现此方法
postProcessXml(root);
this.delegate = parent;
}
}
继续深入parseBeanDefinitions(root, this.delegate),进入到真正的解析逻辑里面对BeanDefinition进行解析
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//如果是默认的命名空间
if (delegate.isDefaultNamespace(root)) {
//获取根节点下的所有子节点
NodeList nl = root.getChildNodes();
//遍历所有的子节点
for (int i = 0; i < nl.getLength(); i++) {
//取出节点
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
//Bean定义的Document对象使用了Spring默认的XML命名空间,如http://www.springframework.org/schema/beans
if (delegate.isDefaultNamespace(ele)) {
//若是则按照spring原有的逻辑进行解析
parseDefaultElement(ele, delegate);
}
else {
//否则使用扩展的自定义代理类进行解析
delegate.parseCustomElement(ele);
}
}
}
}
else {
//使用扩展的自定义代理类进行解析
delegate.parseCustomElement(root);
}
}
}
继续深入parseDefaultElement(ele, delegate),此方法会完成对标签的解析
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
//如果元素节点是<Import>导入元素,进行导入解析
//<import resource="classpath:applicationContext-datasource.xml" />
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
//如果元素节点是<Alias>别名元素,进行别名解析
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
//元素节点既不是导入元素,也不是别名元素,即普通的<Bean>元素,
//按照Spring的Bean规则解析元素
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
//解析beans,递归调用doRegisterBeanDefinitions
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
}
继续深入processBeanDefinition(ele, delegate),此方法会真正解析出BeanDefinition
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// BeanDefinitionHolder是对BeanDefinition的封装,即Bean定义的封装类
//对Document对象中<Bean>元素的解析由BeanDefinitionParserDelegate实现
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
//向Spring IOC容器注册解析得到的BeanDefinition,这是BeanDefinition向IOC容器注册的入口
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
// 在完成BeanDefinition注册之后,往容器发送注册完成的事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
}
- 由BeanDefinitionParserDelegate将解析出来的BeanDefinition封装到BeanDefinitionHolder中。
- 由BeanDefinitionReaderUtils的registerBeanDefinition方法将BeanDefinition注册到Spring IOC容器中。
- 最终调用DefaultListableBeanFactory类的registerBeanDefinition方法将beanDefinition注册到beanDefinitionMap中。
以上便是资源定位、加载、解析、注册的整个流程。
XML配置方式的BeanDefinition注册流程:
- 1、在FileSystemXmlApplicationContext的构造函数中设置配置资源的路径,接着调用refresh()方法进行容器的初始化。
- 2、refresh方法中的obtainFreshBeanFactory()方法进行配置的解析逻辑。
- 3、调用子类容器的refreshBeanFactory()刷新子类容器。
- 4、在AbstractRefreshableApplicationContext类的refreshBeanFactory方法中创建DefaultListableBeanFactory实例。
- 5、将DefaultListableBeanFactory实例作为参数传入到loadBeanDefinitions方法中。
- 6、在loadBeanDefinitions方法中通过DefaultListableBeanFactory创建XmlBeanDefinitionReader实例。
- 7、在loadBeanDefinitions方法中设置ResourceLoader用于加载资源,(即容器实例,容器实现了ResourceLoader接口)
- 8、通过BeanDefinitionReader加载Bean资源。
- 9、通过ResourcePatternResolver来加载资源,并通过EncodedResource包装资源实例。
- 10、XmlBeanDefinitionReader类的doLoadBeanDefinitions通过 InputSource加载Bean。
- 11、XmlBeanDefinitionReader类的doLoadDocument方法将xml解析成Document对象。
- 12、XmlBeanDefinitionReader类的registerBeanDefinitions方法创建BeanDefinitionDocumentReader实例。
- 13、在BeanDefinitionDocumentReader类的registerBeanDefinitions方法中,从Document对象中解析并注册BeanDefiniton。
- 14、DefaultBeanDefinitionDocumentReader类中的parseBeanDefinitions方法通过参数BeanDefinitionParserDelegate解析BeanDefinition。
- 15、DefaultBeanDefinitionDocumentReader类的parseDefaultElement按照spring原有的逻辑进行解析。
- 16、通过BeanDefinitionParserDelegate的parseBeanDefinitionElement解析出包含了BeanDefinition实例的BeanDefinitionHolder包装实例。
- 17、通过BeanDefinitionReaderUtils类的registerBeanDefinition方法将BeanDefinition实例注册到容器中,如果BeanDefinition是单例的化,之前已经注册过了的,就需要清空之前的注册信息。
- 18、使用beanName做唯一标识注册到DefaultListableBeanFactory类中的beanDefinitionMap中,有别名注册别名。
网友评论