您的位置:首页 > 编程语言 > Java开发

spring 之 import标签、alias标签、beans标签 解析

2017-09-28 13:42 661 查看
继续接着Spring 加载、解析applicationContext.xml 流程解析 import 、 alias、beans 标签。

DefaultBeanDefinitionDocumentReader.parseDefaultElement()



1. import 标签解析

标签示例

<import resource="user-appalicationContext.xml"/>


解析import 标签

入口类、方法DefaultBeanDefinitionDocumentReader.importBeanDefinitionResource();

protected void importBeanDefinitionResource(Element ele) {
// 解析 resource 属性
String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
//如果为空,不做处理
if (!StringUtils.hasText(location)) {
getReaderContext().error("Resource location must not be empty", ele);
return;
}

// 解析系统属性。比如 "${user.dir}"
location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);

Set<Resource> actualResources = new LinkedHashSet<>(4);

boolean absoluteLocation = false;
try {
// 判断 location 是绝对路径还是相对路径
absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
}catch (URISyntaxException ex) {
// cannot convert to an URI, considering the location relative
// unless it is the well-known Spring prefix "classpath*:"
}
// 绝对路径
if (absoluteLocation) {
try {
//加载xml配置文件,并解析资源
int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
if (logger.isDebugEnabled()) {
logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
}
}catch (BeanDefinitionStoreException ex) {
getReaderContext().error(
"Failed to import bean definitions from URL location [" + location + "]", ele, ex);
}
}else {
// No URL -> considering resource location as relative to the current file.
try {
int importCount;
//获取绝对路径,并解析文件
Resource relativeResource = getReaderContext().getResource().createRelative(location);
if (relativeResource.exists()) {
//加载xml文件,并解析
importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
actualResources.add(relativeResource);
}else {
// 获取URL 路径,并解析文件
String baseLocation = getReaderContext().getResource().getURL().toString();
importCount = getReaderContext().getReader().loadBeanDefinitions(
StringUtils.applyRelativePath(baseLocation, location), actualResources);
}
if (logger.isDebugEnabled()) {
logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
}
}
catch (IOException ex) {
getReaderContext().error("Failed to resolve current resource location", ele, ex);
}catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",
ele, ex);
}
}
Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);
getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}


获取resource属性

解析路径中的系统属性,格式如“${user.dir}”

判断location是绝对路径还是相对路径

如果是绝对路径,则递归调用bean的解析过程。重新执行这个流程 Spring 加载、解析applicationContext.xml 流程

如果相对路径,则把相对路径转换成绝对路径,在解析

通过监听器、解析完成

2. alias 标签解析

alias 标签示例

<bean id="user" class="cn.com.infcn.test.User"></bean>
<alias name="user" alias="myUser" />


解析 alias 标签

DefaultBeanDefinitionDocumentReader.processAliasRegistration()

protected void processAliasRegistration(Element ele) {
//获取 name属性
String name = ele.getAttribute(NAME_ATTRIBUTE);
//获取 alias 属性
String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
boolean valid = true;
//验证 name 是否为空
if (!StringUtils.hasText(name)) {
getReaderContext().error("Name must not be empty", ele);
valid = false;
}
//验证 alias 是否为空
if (!StringUtils.hasText(alias)) {
getReaderContext().error("Alias must not be empty", ele);
valid = false;
}
if (valid) {
try {
//把 alias 注册到 SimpleAliasRegistry.aliasMap 中
getReaderContext().getRegistry().registerAlias(name, alias);
}
catch (Exception ex) {
getReaderContext().error("Failed to register alias '" + alias +
"' for bean with name '" + name + "'", ele, ex);
}
getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
}
}


解析 alias 标签,获取 name 和 alias 属性值。

把 name 和 alias 注册到 SimpleAliasRegistry.aliasMap 属性中。

SimpleAliasRegistry 源码

public class SimpleAliasRegistry implements AliasRegistry {

private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);

@Override
public void registerAlias(String name, String alias) {
Assert.hasText(name, "'name' must not be empty");
Assert.hasText(alias, "'alias' must not be empty");
if (alias.equals(name)) {
this.aliasMap.remove(alias);
}else {
String registeredName = this.aliasMap.get(alias);
if (registeredName != null) {
if (registeredName.equals(name)) {
// An existing alias - no need to re-register
return;
}
if (!allowAliasOverriding()) {
throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
name + "': It is already registered for name '" + registeredName + "'.");
}
}
checkForAliasCircle(name, alias);
this.aliasMap.put(alias, name);
}
}

protected boolean allowAliasOverriding() {
return true;
}
......


3. beans 标签解析

beans标签示例

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> 
<bean id="user" class="cn.com.infcn.test.User"></bean>
<beans>
......
</beans>
</beans>


beans 标签解析 又调用了doRegisterBeanDefinitions() 方法,这个方法在Spring 加载、解析applicationContext.xml 流程中已经介绍过了。

跟import 解析都类似。又相当于重新执行解析了一边 bean 标签一样。

本人简书blog地址:http://www.jianshu.com/u/1f0067e24ff8    

点击这里快速进入简书

GIT地址:http://git.oschina.net/brucekankan/

点击这里快速进入GIT
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息