前言
当你凝视黑夜的时候,黑夜也在凝视着你!日日当精进,干就完了!上篇Spring IOC 源码调试二的进度,进行到了重点的AbstractBeanDefinitionReader
的loadBeanDefinitions
方法**,那这一篇接着进行。原创纯手打!实属不易!求赞!求关注!我不会因为您的不支持而低迷,但是有了您的支持我会变的亢奋!
项目结构
这是调试代码
开始调试
(重点)1.执行AbstractBeanDefinitionReader
的loadBeanDefinitions(String location, @Nullable Set actualResources)
该方法中主要操作有:
-
ResourceLoader resourceLoader = getResourceLoader()
:获取一个ResourceLoader
(资源加载器)对象此时获取到的
ResourceLoader
具体实现类是ClassPathXmlApplicationContext
对象,详情请看Spring IOC 源码调试二的2-5
部分的第3个操作。 -
int count = loadBeanDefinitions(resources)
:继续调用XmlBeanDefinitionReader
的loadBeanDefinitions(Resource... resources)
方法。此时的this对象是XmlBeanDefinitionReader
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
//初始化 XmlBeanDefinitionReader 时 设置了 setResourceLoader(this)
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.
try {
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
// 进一步调用 XmlBeanDefinitionReader的loadBeanDefinitions(Resource... resources)方法
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.
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;
}
}
(重点)2.执行XmlBeanDefinitionReader
的loadBeanDefinitions(Resource... resources)
方法
看下面代码,该方法中是对每个资源逐一解析的,但是返回值是总的bean的个数。很无奈又是层层调用XmlBeanDefinitionReader
的loadBeanDefinitions
重载方法,调用过程中有一个逻辑是把参数Resource
对象转换成了EncodeResource
对象,并且最后调用到XmlBeanDefinitionReader
的loadBeanDefinitions(EncodedResource encodedResource)
方法
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int count = 0;
for (Resource resource : resources) {
// 加载每个资源的 bean 的个数
count += loadBeanDefinitions(resource);
}
// 返回总共 bean 的个数
return count;
}
3.执行XmlBeanDefinitionReader
的loadBeanDefinitions(EncodedResource encodedResource)
方法
这个方法主要作用我认为就是获取到资源的输入流。重点是将输入流作为参数传入XmlBeanDefinitionReader
的doLoadBeanDefinitions(InputSource inputSource, Resource resource)
方法中
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);
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
// 得到资源的输入流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 真正 解析 XML 文件方法
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
4.(重点中的重点)执行XmlBeanDefinitionReader
的doLoadBeanDefinitions(InputSource inputSource, Resource resource)
方法
该方法主要就两个操作:
Document doc = doLoadDocument(inputSource, resource);
:将xml文件解析为Document
对象int count = registerBeanDefinitions(doc, resource)
:注册Beandefinition
到容器(DefaultListableBeanFatory
)中
/**将 xml文件 装载为 BeanDefinition
*/
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
Document doc = doLoadDocument(inputSource, resource);
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);
}
}
4-1Document doc = doLoadDocument(inputSource, resource)
此时的this对象依然为XmlBeanDefinitionReader
对象,所以会执行XmlBeanDefinitionReader
的doLoadDocument(InputSource inputSource, Resource resource)
方法,代码如下:
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
getValidationModeForResource(resource), isNamespaceAware());
}
代码执行的逻辑:
- 首先在
XmlBeanDefinitionReader
对象中维护了一个private DocumentLoader documentLoader = new DefaultDocumentLoader();
属性 - 执行
DefaultDocumentLoader
的loadDocument(InputSource inputSource, EntityResolver entityResolver, ErrorHandler errorHandler, int validationMode, boolean namespaceAware)
方法 - 最后调用到
DocumentBuilderImpl
的parse(InputSource is)
方法,最后执行DOM解析,返回Document
对象 - 由于DOM解析不是重点此处不进行深度跟踪。
得到xml文件的Document
对象后作为参数传给:XmlBeanDefinitionReader
对象的registerBeanDefinitions(doc, resource)
方法
4-2执行:XmlBeanDefinitionReader
对象的registerBeanDefinitions(Document doc, Resource resource)
方法
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// 获取一个`DefaultBeanDefinitionDocumentReader`对象
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
// 获取 注册Beandefinition之前 Beandefinition的数量
int countBefore = getRegistry().getBeanDefinitionCount();
// 注册 BeanDefinition
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
该方法中主要逻辑有:
4-2-1BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader()
得到一个BeanDefinitionDocumentReader
对象,真正的实现类是DefaultBeanDefinitionDocumentReader
4-2-2int countBefore = getRegistry().getBeanDefinitionCount();
:获取 注册Beandefinition之前 Beandefinition的数量
- 此时this对象为
:XmlBeanDefinitionReader
对象,调用getRegistry()
方法时是调用父类AbstractBeanDefinitionReader
的getRegistry()
方法。 - Spring IOC 源码调试二的
2-5
部分的第一个操作在实例化:XmlBeanDefinitionReader
对象的时候把DefaultListableBeanFactory
最为参数传给了:XmlBeanDefinitionReader
的构造参数,而DefaultListableBeanFactory
对象又实现了BeanDefinitionRegistry
,所以调用AbstractBeanDefinitionReader
的getRegistry()
方法得到的对象是DefaultListableBeanFactory
DefaultListableBeanFactory
的getBeanDefinitionCount()
方法就是获取beanDefinitionMap
(Bean元数据信息集合)中的个数
4-2-3 documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
:注册 BeanDefinition
4-2-3.1该方法中参数中有一个逻辑:createReaderContext(resource)
:我理解为构造:XmlBeanDefinitionReader
对象的应用上下文
大概意思就是把:XmlBeanDefinitionReader
包装一下变成XmlReaderContext
对象
public XmlReaderContext createReaderContext(Resource resource) {
return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
this.sourceExtractor, this, getNamespaceHandlerResolver());
}
4-2-3.2 (this对象变化)进入到DefaultBeanDefinitionDocumentReader
的registerBeanDefinitions(Document doc, XmlReaderContext readerContext)
方法
此时的this对象变为了DefaultBeanDefinitionDocumentReader
看到下面代码就知道三个操作
this.readerContext = readerContext;
:将上层函数传进来的XmlReaderContext
赋值给自己的属性doc.getDocumentElement()
获取Document
的节点对象- 调用
DefaultBeanDefinitionDocumentReader
的doRegisterBeanDefinitions(Element root)
方法
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
doRegisterBeanDefinitions(doc.getDocumentElement());
}
4-2-3.3 执行DefaultBeanDefinitionDocumentReader
的doRegisterBeanDefinitions(Element root)
方法
该方法注释翻译过来是:在给定的根中注册每个bean定义,我理解就是......好吧我没理解啥。
主要有两个操作
-
this.delegate = createDelegate(getReaderContext(), root, parent);
:获取BeanDefinitionParserDelegate
对象简单说一下
BeanDefinitionParserDelegate
对象:- 里面维护了Spring的xml配置文的标签常量。(比如 "bean"、"name"、“id”、"singleton"、"scope")
- 里面封装了将标签解析为
Beandefinition
的方法
-
parseBeanDefinitions(root, this.delegate);
:一看这方法就知道后面将注册又委托给了this.delegate
/**在给定的根中注册每个bean定义
* Register each bean definition within the given root {@code <beans/>} element.
*/
@SuppressWarnings("deprecation") // for Environment.acceptsProfiles(String...)
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate;
// 获取 BeanDefinitionParserDelegate 对象
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
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;
}
}
}
// 空方法
preProcessXml(root);
// 解析xml 标签
parseBeanDefinitions(root, this.delegate);
// 空方法
postProcessXml(root);
this.delegate = parent;
}
4-2-3.4 进入到DefaultBeanDefinitionDocumentReader
的parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)
方法
在该方法中,要了解一下Dom解析相关的 Node、Element等对象
因为要解析我们在xml中配置的Bean
,所以会parseDefaultElement(ele, delegate)
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;
if (delegate.isDefaultNamespace(ele)) {
// 只 解析 "import", "alias", "bean", "beans" 标签
parseDefaultElement(ele, delegate);
}
else {
// 解析 其他的标签 比如 <component-scan> 标签
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
4-2-3.5 进入到DefaultBeanDefinitionDocumentReader
的parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)
方法
因为调试项目中只配置了<bean></bean>
标签,所以只关注代码中的processBeanDefinition(ele, delegate);
方法
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
// 解析 bean 标签
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
4-2-3.6 (this对象变化)进入到DefaultBeanDefinitionDocumentReader的
processBeanDefinition(ele, delegate);方法
看代码了解到,将解析任务委托给了BeanDefinitionParserDelegate
对象
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 将 xml 配置信息封装为 Beandefinition
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
//将 Beandefinition 注册到 容器(DefaultListableBeanFactory) 中
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
该方法主要的3个操作
-
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele)
:将 xml 配置信息封装为 Beandefinition在这段代码中可以得知:
- xml配置的
id
属性就是我们Bean的名字 - 容器中bean的名字是唯一的
- 在
parseBeanDefinitionElement(ele, beanName, containingBean)
方法中还会初始化Beandefinition
的一些属性 - 最后返回
BeanDefinitionHolder
对象将Beandefinition
包装起来
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) { String id = ele.getAttribute(ID_ATTRIBUTE); String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); List<String> aliases = new ArrayList<>(); if (StringUtils.hasLength(nameAttr)) { String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); } // 定义 bean 的名字 为xml中配置的 id 属性 String beanName = id; if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { beanName = aliases.remove(0); if (logger.isTraceEnabled()) { logger.trace("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases"); } } // 校验名字是不是唯一的 if (containingBean == null) { checkNameUniqueness(beanName, aliases, ele); } // 将xml配置信息 封装成 BeanDefinition 对象 AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) { if (!StringUtils.hasText(beanName)) { try { if (containingBean != null) { beanName = BeanDefinitionReaderUtils.generateBeanName( beanDefinition, this.readerContext.getRegistry(), true); } else { beanName = this.readerContext.generateBeanName(beanDefinition); // Register an alias for the plain bean class name, if still possible, // if the generator returned the class name plus a suffix. // This is expected for Spring 1.2/2.0 backwards compatibility. String beanClassName = beanDefinition.getBeanClassName(); if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { aliases.add(beanClassName); } } if (logger.isTraceEnabled()) { logger.trace("Neither XML 'id' nor 'name' specified - " + "using generated bean name [" + beanName + "]"); } } catch (Exception ex) { error(ex.getMessage(), ele); return null; } } String[] aliasesArray = StringUtils.toStringArray(aliases); return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null; }
- xml配置的
-
注册
Beandefinition
到容器中:BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
-
getReaderContext().getRegistry()
:因为在4-2-3.1
中封装的XmlReaderContext
对象包含:XmlBeanDefinitionReader
对象的所有信息,所以这个方法获取到的对象就是容器对象DefaultListableBeanFactory
, -
该方法将第一个操作获取到的
bdHolder
(Beandefinition
对象的持有者)和 容器对象作为参数传入 -
进入方法后又调用
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition())
(此时registry就是DefaultListableBeanFactory对象)将Beandefinition
对象添加到DefaultListableBeanFactory
对象的属性Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256)
中,就算注册完成了 -
BeanDefinitionReaderUtils
的registerBeanDefinition()
方法代码public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // Register bean definition under primary name. String beanName = definitionHolder.getBeanName(); // 调用 容器对象(DefaultListableBeanFactory) 注册 Beandefinition registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Register aliases for bean name, if any. String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { registry.registerAlias(beanName, alias); } } }
-
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
该方法中还有一些逻辑,但是主流程就是将
Beandefinition
添加到beanDefinitionMap
中
-
-
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder))
该方法注释为
Send registration event
,我理解是发布一个注册事件。这块没有深入跟踪。
4-2-3.7回到DefaultBeanDefinitionDocumentReader
的parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)
方法(4-2-3.5)
此时processBeanDefinition(ele, delegate);
方法执行完毕
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
4-2-3.8回到DefaultBeanDefinitionDocumentReader
的parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)
方法(4-2-3.4)
此时 parseDefaultElement(ele, delegate);
方法执行完毕,但是此处是遍历根节点对象,意思就是多个<bean></bean>
标签的话就会遍历执行解析重复上面的过程。
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;
if (delegate.isDefaultNamespace(ele)) {
// 只 解析 "import", "alias", "bean", "beans" 标签
parseDefaultElement(ele, delegate);
}
else {
// 解析 其他的标签 比如 <component-scan> 标签
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
4-2-3.9回到DefaultBeanDefinitionDocumentReader
的doRegisterBeanDefinitions(Element root)
方法(4-2-3.3)
- 此时执行完了
parseBeanDefinitions(root, this.delegate);
方法 - 执行
this.delegate = parent
,即将this.delegate
置为null
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.
BeanDefinitionParserDelegate parent = this.delegate;
//得到一个 BeanDefinitionParserDelegate 对象
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
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;
}
}
}
// 空方法
preProcessXml(root);
// 解析xml 标签
parseBeanDefinitions(root, this.delegate);
// 空方法
postProcessXml(root);
this.delegate = parent;
}
4-2-3.10回到DefaultBeanDefinitionDocumentReader
的registerBeanDefinitions(Document doc, XmlReaderContext readerContext)
方法(4-2-3.2)
此时执行完了doRegisterBeanDefinitions(doc.getDocumentElement());
方法
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
doRegisterBeanDefinitions(doc.getDocumentElement());
}
4-2-4回到XmlBeanDefinitionReader
对象的registerBeanDefinitions(Document doc, Resource resource)
方法(4-2)
- 此时执行完了
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
方法 - 执行
getRegistry().getBeanDefinitionCount() - countBefore
计算得出该次注册BeanDefinition
的个数
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
4-2-5 回到XmlBeanDefinitionReader
的doLoadBeanDefinitions(InputSource inputSource, Resource resource)
方法(4)
- 此时执行完了
int count = registerBeanDefinitions(doc, resource);
方法 - 然后将 count 返回
/**将 xml文件 装载为 BeanDefinition
*/
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
Document doc = doLoadDocument(inputSource, resource);
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);
}
}
5 回到本文章开始AbstractBeanDefinitionReader
的loadBeanDefinitions(String location, @Nullable Set actualResources)
方法(1)
- 此时执行完了
count += loadBeanDefinitions(resource);
方法 - 因为我只配置了一个xml,所以只有一个
resource
- 此处的count为容器中总共
Beandefinition
的数量
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int count = 0;
for (Resource resource : resources) {
// 加载每个资源的 bean 的个数
count += loadBeanDefinitions(resource);
}
return count;
}
总结
loadBeanDefinitions()
方法包含了对xml文件的解析以及对Beandefinition
对象的封装和注册loadBeanDefinitions()
中最后注册是调用的DefaultListableBeanFactory
对象的方法- 解析出的
Beandefinition
对象都被维护在DefaultListableBeanFactory
对象的Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
属性中 - 函数调用太深了,但是有规律可循,基本上就是方法重载和任务委托给其他的类来执行任务,要时刻关注this对象是谁
- 该文章并没有面面俱到,尤其是最后注册那一块不够详细,但是主流程还是走通了。
欢迎扫码关注
如果喜欢请关注我公众号【程序倾听者】,说出你的故事!我在这里倾听!
文章原文地址