微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Spring Bean 标签解析


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


bean 标签解析

查看 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. 解析 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<String> 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.1 创建用于属性承载的 BeanDeFinition

BeanDeFinition 是一个接口,在 Spring 中存在三种实现:RootBeanDeFinition、ChildBeanDeFinition、GenericBeanDeFinition,三种实现类均继承了 AbstractBeanDeFinition

BeanDeFinition 是配置文件 <bean> 元素标签在容器中的内部表示形式,<bean> 标签拥有 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;
}
2. 解析各种属性

当我们创建了 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;
}

注册解析的 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. 通过 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<String> 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 的缓存

2. 通过别名注册 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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐