目录
1、概述
2、代码分析
DefaultBeanDefinitionDocumentReader的 doRegisterBeanDefinitions(Element root) 是真正解析 Spring配置文件的各种元素,转化成 BeanDefinition 的过程。
DefaultBeanDefinitionDocumentReader 代码如下
package org.springframework.beans.factory.xml;
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
public static final String BEAN_ELEMENT = "bean";
public static final String NESTED_BEANS_ELEMENT = "beans";
public static final String ALIAS_ELEMENT = "alias";
public static final String NAME_ATTRIBUTE = "name";
public static final String ALIAS_ATTRIBUTE = "alias";
public static final String IMPORT_ELEMENT = "import";
public static final String RESOURCE_ATTRIBUTE = "resource";
public static final String PROFILE_ATTRIBUTE = "profile";
protected final Log logger = LogFactory.getLog(this.getClass());
@Nullable
private XmlReaderContext readerContext;
@Nullable
private BeanDefinitionParserDelegate delegate;
public DefaultBeanDefinitionDocumentReader() {
}
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
this.logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
this.doRegisterBeanDefinitions(root);
}
protected final XmlReaderContext getReaderContext() {
Assert.state(this.readerContext != null, "No XmlReaderContext available");
return this.readerContext;
}
@Nullable
protected Object extractSource(Element ele) {
return this.getReaderContext().extractSource(ele);
}
// 解析各种xml元素,转换为 BeanDefinition的方法
protected void doRegisterBeanDefinitions(Element root) {
// 委托解析辅助类
BeanDefinitionParserDelegate parent = this.delegate;
// 创建委托解析辅助类
this.delegate = this.createDelegate(this.getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
// profile支持
String profileSpec = root.getAttribute("profile");
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; ");
if (!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + this.getReaderContext().getResource());
}
return;
}
}
}
// 前置空方法
this.preProcessXml(root);
// 解析方法
this.parseBeanDefinitions(root, this.delegate);
// 后置空方法
this.postProcessXml(root);
this.delegate = parent;
}
protected BeanDefinitionParserDelegate createDelegate(XmlReaderContext readerContext, Element root, @Nullable BeanDefinitionParserDelegate parentDelegate) {
BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
delegate.initDefaults(root, parentDelegate);
return delegate;
}
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
// 判断是否为Spring默认命名空间
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)) {
// 默认标签解析
this.parseDefaultElement(ele, delegate);
} else {
// 默认命名空间中夹杂的自定义标签解析
delegate.parseCustomElement(ele);
}
}
}
} else {
// 自定义标签解析
delegate.parseCustomElement(root);
}
}
// 自定义标签解析
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, "import")) {// import标签解析,实际是加载另一个Spring配置文件,然后再循环解析
this.importBeanDefinitionResource(ele);
} else if (delegate.nodeNameEquals(ele, "alias")) {// 别名解析
this.processAliasRegistration(ele);
} else if (delegate.nodeNameEquals(ele, "bean")) {// bean解析
this.processBeanDefinition(ele, delegate);
} else if (delegate.nodeNameEquals(ele, "beans")) {// beans解析,实际还是循环解析
this.doRegisterBeanDefinitions(ele);
}
}
protected void importBeanDefinitionResource(Element ele) {
String location = ele.getAttribute("resource");
if (!StringUtils.hasText(location)) {
this.getReaderContext().error("Resource location must not be empty", ele);
} else {
location = this.getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
Set actualResources = new LinkedHashSet(4);
boolean absoluteLocation = false;
try {
absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
} catch (URISyntaxException var11) {
;
}
int importCount;
if (absoluteLocation) {
try {
importCount = this.getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
}
} catch (BeanDefinitionStoreException var10) {
this.getReaderContext().error("Failed to import bean definitions from URL location [" + location + "]", ele, var10);
}
} else {
try {
Resource relativeResource = this.getReaderContext().getResource().createRelative(location);
if (relativeResource.exists()) {
importCount = this.getReaderContext().getReader().loadBeanDefinitions(relativeResource);
actualResources.add(relativeResource);
} else {
String baseLocation = this.getReaderContext().getResource().getURL().toString();
importCount = this.getReaderContext().getReader().loadBeanDefinitions(StringUtils.applyRelativePath(baseLocation, location), actualResources);
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
}
} catch (IOException var8) {
this.getReaderContext().error("Failed to resolve current resource location", ele, var8);
} catch (BeanDefinitionStoreException var9) {
this.getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]", ele, var9);
}
}
Resource[] actResArray = (Resource[])actualResources.toArray(new Resource[0]);
this.getReaderContext().fireImportProcessed(location, actResArray, this.extractSource(ele));
}
}
protected void processAliasRegistration(Element ele) {
String name = ele.getAttribute("name");
String alias = ele.getAttribute("alias");
boolean valid = true;
if (!StringUtils.hasText(name)) {
this.getReaderContext().error("Name must not be empty", ele);
valid = false;
}
if (!StringUtils.hasText(alias)) {
this.getReaderContext().error("Alias must not be empty", ele);
valid = false;
}
if (valid) {
try {
this.getReaderContext().getRegistry().registerAlias(name, alias);
} catch (Exception var6) {
this.getReaderContext().error("Failed to register alias '" + alias + "' for bean with name '" + name + "'", ele, var6);
}
this.getReaderContext().fireAliasRegistered(name, alias, this.extractSource(ele));
}
}
// bean 标签解析
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 委托类解析 bean元素 为 BeanDefinitionHolder
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 实际是调用 DefaultListableBeanFactory 实现 BeanDefinitionRegistry 的注册 Bean 方法
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
} catch (BeanDefinitionStoreException var5) {
this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
}
this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
protected void preProcessXml(Element root) {
}
protected void postProcessXml(Element root) {
}
}
注册Bean