• Spring Bean 标签解析



    上一篇文章讲到了标签在 parseDefaultElement 方法中进行解析,本篇文章将讲解这部分内容


    1|0bean 标签解析

    查看 processBeanDefinition 方法,针对各个操作作具体分析:

    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { // 1.解析 BeanDefinition BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { 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)); } }

    1|01. 解析 BeanDefinition

    首先从元素解析及信息提取开始,进入 parseBeanDefinitionElement 方法

    public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) { return this.parseBeanDefinitionElement(ele, (BeanDefinition)null); } public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) { // 1.1 解析id属性 String id = ele.getAttribute("id"); // 1.2 解析name属性 String nameAttr = ele.getAttribute("name"); List aliases = new ArrayList(); if (StringUtils.hasLength(nameAttr)) { String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; "); aliases.addAll(Arrays.asList(nameArr)); } String beanName = id; if (!StringUtils.hasText(id) && !aliases.isEmpty()) { beanName = (String)aliases.remove(0); if (this.logger.isTraceEnabled()) { this.logger.trace("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases"); } } if (containingBean == null) { this.checkNameUniqueness(beanName, aliases, ele); } // 2. 解析其他属性 AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) { if (!StringUtils.hasText(beanName)) { try { // 3. 如果不存在beanName就根据Spring提供的命名规则为当前bean生成对应的beanName if (containingBean != null) { beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true); } else { beanName = this.readerContext.generateBeanName(beanDefinition); String beanClassName = beanDefinition.getBeanClassName(); if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { aliases.add(beanClassName); } } if (this.logger.isTraceEnabled()) { this.logger.trace("Neither XML 'id' nor 'name' specified - using generated bean name [" + beanName + "]"); } } catch (Exception var9) { this.error(var9.getMessage(), ele); return null; } } String[] aliasesArray = StringUtils.toStringArray(aliases); // 4. 封装到 BeanDefinitionHolder 的实例 return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } else { return null; } }
    折叠

    该方法完成的主要工作包括以下内容:

    1. 提取元素中的 id 以及 name 属性
    2. 进一步解析其他属性并统一封装至 GenericBeanDefinition 类型的实例中
    3. 如果检测到 bean 没有指定 beanName,那么使用默认规则为此 Bean 生成 beanName
    4. 将获取到的信息封装到 BeanDefinitionHolder 的实例中

    进一步查看步骤二对标签的其他属性的解析过程:

    public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean) { this.parseState.push(new BeanEntry(beanName)); String className = null; // 解析class属性 if (ele.hasAttribute("class")) { className = ele.getAttribute("class").trim(); } // 解析parent属性 String parent = null; if (ele.hasAttribute("parent")) { parent = ele.getAttribute("parent"); } try { // 创建用于承载属性的AbstractBeanDefinition类型的GenericBeanDefinition实例 AbstractBeanDefinition bd = this.createBeanDefinition(className, parent); // 硬编码解析默认bean的各种属性 this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); // 提取description bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description")); // 解析元数据 this.parseMetaElements(ele, bd); // 解析lookup-method属性 this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); // 解析replaced-method属性 this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); // 解析构造函数参数 this.parseConstructorArgElements(ele, bd); // 解析property子元素 this.parsePropertyElements(ele, bd); // 解析qualifier子元素 this.parseQualifierElements(ele, bd); bd.setResource(this.readerContext.getResource()); bd.setSource(this.extractSource(ele)); AbstractBeanDefinition var7 = bd; return var7; } catch (ClassNotFoundException var13) { this.error("Bean class [" + className + "] not found", ele, var13); } catch (NoClassDefFoundError var14) { this.error("Class that bean class [" + className + "] depends on not found", ele, var14); } catch (Throwable var15) { this.error("Unexpected failure during bean definition parsing", ele, var15); } finally { this.parseState.pop(); } return null; }
    折叠

    接下来,我们继续一些复杂标签属性的解析:

    1|01.1 创建用于属性承载的 BeanDefinition

    BeanDefinition 是一个接口,在 Spring 中存在三种实现:RootBeanDefinition、ChildBeanDefinition、GenericBeanDefinition,三种实现类均继承了 AbstractBeanDefinition

    BeanDefinition 是配置文件 元素标签在容器中的内部表示形式, 标签拥有 class、scope、lazy-init 等配置属性,BeanDefinition 就提供了对应的 beanClass、scope、lazyInit 属性

    由此可见,要解析属性首先要创建用于承载属性的实例,也就是创建 GenericBeanDefinition 类型的实例,createBeanDefinition 方法的作用就是实现此功能

    public static AbstractBeanDefinition createBeanDefinition(@Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException { GenericBeanDefinition bd = new GenericBeanDefinition(); bd.setParentName(parentName); if (className != null) { // 如果classLoader不为空,则使用传入的classLoader加载对象 // 否则就只是记录className if (classLoader != null) { bd.setBeanClass(ClassUtils.forName(className, classLoader)); } else { bd.setBeanClassName(className); } } return bd; }
    1|02. 解析各种属性

    当我们创建了 bean 信息的承载实例后,便可以进行 bean 信息的各种属性解析了,parseBeanDefinitionAttributes 方法是对 element 所有元素属性进行解析:

    public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) { // 解析scope属性 if (ele.hasAttribute("singleton")) { this.error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele); } else if (ele.hasAttribute("scope")) { bd.setScope(ele.getAttribute("scope")); } else if (containingBean != null) { bd.setScope(containingBean.getScope()); } // 解析singleton属性 if (ele.hasAttribute("abstract")) { bd.setAbstract("true".equals(ele.getAttribute("abstract"))); } // 解析lazy-init属性 String lazyInit = ele.getAttribute("lazy-init"); if (this.isDefaultValue(lazyInit)) { lazyInit = this.defaults.getLazyInit(); } // 若没有设置或设置成其他字符都会被设置为false bd.setLazyInit("true".equals(lazyInit)); String autowire = ele.getAttribute("autowire"); bd.setAutowireMode(this.getAutowireMode(autowire)); String autowireCandidate; if (ele.hasAttribute("depends-on")) { autowireCandidate = ele.getAttribute("depends-on"); bd.setDependsOn(StringUtils.tokenizeToStringArray(autowireCandidate, ",; ")); } // 解析autowire属性 autowireCandidate = ele.getAttribute("autowire-candidate"); String destroyMethodName; if (this.isDefaultValue(autowireCandidate)) { destroyMethodName = this.defaults.getAutowireCandidates(); if (destroyMethodName != null) { String[] patterns = StringUtils.commaDelimitedListToStringArray(destroyMethodName); bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName)); } } else { bd.setAutowireCandidate("true".equals(autowireCandidate)); } // 解析primary属性 if (ele.hasAttribute("primary")) { bd.setPrimary("true".equals(ele.getAttribute("primary"))); } // 解析init-method属性 if (ele.hasAttribute("init-method")) { destroyMethodName = ele.getAttribute("init-method"); bd.setInitMethodName(destroyMethodName); } else if (this.defaults.getInitMethod() != null) { bd.setInitMethodName(this.defaults.getInitMethod()); bd.setEnforceInitMethod(false); } // 解析destroy-method属性 if (ele.hasAttribute("destroy-method")) { destroyMethodName = ele.getAttribute("destroy-method"); bd.setDestroyMethodName(destroyMethodName); } else if (this.defaults.getDestroyMethod() != null) { bd.setDestroyMethodName(this.defaults.getDestroyMethod()); bd.setEnforceDestroyMethod(false); } // 解析factory-method属性 if (ele.hasAttribute("factory-method")) { bd.setFactoryMethodName(ele.getAttribute("factory-method")); } // 解析factory-bean属性 if (ele.hasAttribute("factory-bean")) { bd.setFactoryBeanName(ele.getAttribute("factory-bean")); } return bd; }
    折叠

    2|0注册解析的 BeanDefinition

    得到 BeanDefinition 后,剩下的工作就是注册了,也就是 processBeanDefinition 方法中的

    registerBeanDefinition 方法

    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // 注册解析的 BeanDefinition 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)); } } public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // 使用beanName做唯一标识注册 String beanName = definitionHolder.getBeanName(); registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // 注册所有的别名 String[] aliases = definitionHolder.getAliases(); if (aliases != null) { String[] var4 = aliases; int var5 = aliases.length; for(int var6 = 0; var6 < var5; ++var6) { String alias = var4[var6]; registry.registerAlias(beanName, alias); } } }
    折叠

    解析的 beanDefinition 都会被注册到 BeanDefinitionRegistry 类型的实例 registry 中,而对于 beanDefinition 的注册分成两个部分:通过 beanName 注册以及通过别名注册

    1|01. 通过 beanName 注册

    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { Assert.hasText(beanName, "Bean name must not be empty"); Assert.notNull(beanDefinition, "BeanDefinition must not be null"); if (beanDefinition instanceof AbstractBeanDefinition) { try { // 注册前的最后一次校验 ((AbstractBeanDefinition)beanDefinition).validate(); } catch (BeanDefinitionValidationException var8) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var8); } } // 处理beanName已经注册的情况 BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName); if (existingDefinition != null) { // 如果对应BeanName已经注册且在配置中配置了bean不允许被覆盖,则抛出异常 if (!this.isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); } if (existingDefinition.getRole() < beanDefinition.getRole()) { if (this.logger.isInfoEnabled()) { this.logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } else if (!beanDefinition.equals(existingDefinition)) { if (this.logger.isDebugEnabled()) { this.logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } else if (this.logger.isTraceEnabled()) { this.logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } this.beanDefinitionMap.put(beanName, beanDefinition); } else { // 检查工厂是否处于bean创建阶段 if (this.hasBeanCreationStarted()) { // 因为beanDefinitionMap是全局变量,会存在并发访问的情况 synchronized(this.beanDefinitionMap) { this.beanDefinitionMap.put(beanName, beanDefinition); List updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; this.removeManualSingletonName(beanName); } } else { // 注册beanDefinition this.beanDefinitionMap.put(beanName, beanDefinition); // 记录beanName this.beanDefinitionNames.add(beanName); this.removeManualSingletonName(beanName); } this.frozenBeanDefinitionNames = null; } if (existingDefinition == null && !this.containsSingleton(beanName)) { if (this.isConfigurationFrozen()) { this.clearByTypeCache(); } } else { this.resetBeanDefinition(beanName); } }
    折叠

    在对于 bean 的注册处理方式上,主要进行了几个步骤:

    1. 对 AbstractBeanDefinition 校验
    2. 加入 map 缓存
    3. 清楚解析之前留下的对应的 beanName 的缓存

    1|02. 通过别名注册 BeanDefinition

    public void registerAlias(String name, String alias) { Assert.hasText(name, "'name' must not be empty"); Assert.hasText(alias, "'alias' must not be empty"); synchronized(this.aliasMap) { // 如果beanName和alias相同的话不记录alias,并删除对应的alias if (alias.equals(name)) { this.aliasMap.remove(alias); if (this.logger.isDebugEnabled()) { this.logger.debug("Alias definition '" + alias + "' ignored since it points to same name"); } } else { String registeredName = (String)this.aliasMap.get(alias); if (registeredName != null) { if (registeredName.equals(name)) { return; } if (!this.allowAliasOverriding()) { throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" + name + "': It is already registered for name '" + registeredName + "'."); } if (this.logger.isDebugEnabled()) { this.logger.debug("Overriding alias '" + alias + "' definition for registered name '" + registeredName + "' with new target name '" + name + "'"); } } // 检查是否存在循环指向,如A->B,A->C->B this.checkForAliasCircle(name, alias); this.aliasMap.put(alias, name); if (this.logger.isTraceEnabled()) { this.logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'"); } } } }
    折叠

    注册 alias 的步骤如下:

    1. alias 与 beanName 相同情况处理
    2. alias 循环检查
    3. 注册 alias


    __EOF__

    本文作者YeeQan
    本文链接https://www.cnblogs.com/Yee-Q/p/16487609.html
    关于博主:评论和私信会在第一时间回复。或者直接私信我。
    版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
    声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
  • 相关阅读:
    人工智能数学基础之线性代数(二)
    数据结构:顺序栈和链式栈的实现
    攻防世界之Web_python_template_injection (web进阶)
    JVM面试点汇总
    【性能学习】性能测试基础
    docker-compose安装yapi接口文档工具——筑梦之路
    硅芯思见:【145】问芯吾跬(IC设计验证常见问题汇总三)
    【Java-LangChain:使用 ChatGPT API 搭建系统-11】用 ChatGPT API 构建系统 总结篇
    Npm使用教程(详细讲解)
    【GIT】:一文快速了解什么是GIT
  • 原文地址:https://www.cnblogs.com/Yee-Q/p/16487609.html