继续接着Spring 加载、解析applicationContext.xml 流程解析 import 、 alias、beans 标签。
DefaultBeanDefinitionDocumentReader.parseDefaultElement()
<import resource="user-appalicationContext.xml"/>
入口类、方法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)); }
<bean id="user" class="cn.com.infcn.test.User"></bean> <alias name="user" alias="myUser" />
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)); } }
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; } ......
<?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 标签一样。
本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。
我来说两句