概述
前面我们介绍了BeanDefinition的载入和解析的过程,将我们定义好的Bean资源文件载入并转换成了Document对象,然后Document对象通过BeanDefinitionDocumentReader来解析,这些动作完成以后,用户自定义的BeanDefinition信息已经在IOC容器内建立起了自己的数据结构,以及相应的数据表示,但这些数据还不能在IOC容器中直接使用,需要在IOC容器中对这些BeanDefinition进行注册。这个注册为IOC容器提供了更友好的使用方式。在DefaultListableBeanDactory
中是使用一个Map对象载入并持有这些BeanDefinition
的,代码如下所示:
/** Map of bean definition objects, keyed by bean name. */
/**持有BeanDefinition的map容器**/
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
源码解析
1.核心流程时序图:
从源码实现的角度我们可以分析得到上图的调用关系。我们可以跟踪源码具体看一下注册实现,在
DefaultListableBeanFactory
中实现了BeanDefinitionRegistry
的接口,这个接口的实现完成了BeanDefinition
向容器注册。注册过程就是将解析得到的BeanDefinition
设置到Map中去,但是如果遇到同名的BeanDefinition
,进行处理的时候需要依据allowBeanDefinitionOverriding
的配置来完成。下面我们就BeanDefinition
的注册逻辑展开分析。
2.源代码分析
-
registerBeanDefinitions核心流程代码解析:
/** * 通过解析Document解析注册BeanDefinition * Register the bean definitions contained in the given DOM document. * Called by {@code loadBeanDefinitions}. * <p>Creates a new instance of the parser class and invokes * {@code registerBeanDefinitions} on it. * @param doc the DOM document * @param resource the resource descriptor (for context information) * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of parsing errors * @see #loadBeanDefinitions * @see #setDocumentReaderClass * @see BeanDefinitionDocumentReader#registerBeanDefinitions */ public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { // 获取BeanDefinition的Document解析器 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); // 获取已经注册的BeanDefinition的个数 int countBefore = getRegistry().getBeanDefinitionCount(); // 创建XmlRederContext,解析Document并注册BeanDefinition documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); // 计算新注册的BeanDefinition的数量 return getRegistry().getBeanDefinitionCount() - countBefore; }
-
registerBeanDefinitions的处理逻辑解析:
/** * This implementation parses bean definitions according to the "spring-beans" XSD (or DTD, historically). * document中element的解析并注册BeanDefinition· * <p>Opens a DOM Document; then initializes the default settings * specified at the {@code <beans/>} level; then parses the contained bean definitions. */ @Override public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; doRegisterBeanDefinitions(doc.getDocumentElement()); }
-
doRegisterBeanDefinitions处理逻辑解析
/** * Register each bean definition within the given root {@code <beans/>} element. */ @SuppressWarnings("deprecation") // for Environment.acceptsProfiles(String...) protected void doRegisterBeanDefinitions(Element root) { // Any nested <beans> elements will cause recursion in this method. In // 从<beans />配置中注册每一个bean,如果有嵌套的beans,那么递归执行这个方法。 // order to propagate and preserve <beans> default-* attributes correctly, // keep track of the current (parent) delegate, which may be null. Create // the new (child) delegate with a reference to the parent for fallback purposes, // then ultimately reset this.delegate back to its original (parent) reference. // this behavior emulates a stack of delegates without actually necessitating one. // 在递归的时候,跟踪父级delegate,新的递归调用引用上个方法的delegate BeanDefinitionParserDelegate parent = this.delegate; // 创建 BeanDefinitionParserDelegate 对象,并进行设置到 delegate this.delegate = createDelegate(getReaderContext(), root, parent); // 检查 <beans /> 根标签的命名空间是否为空,或者是 http://www.springframework.org/schema/beans【1】 if (this.delegate.isDefaultNamespace(root)) { // 处理 profile 属性。可参见《Spring3自定义环境配置 <beans profile="">》 【2】 String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); // We cannot use Profiles.of(...) since profile expressions are not supported // in XML config. See SPR-12458 for details. // 判定环境参数是否满足,无效则不注册 if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { if (logger.isDebugEnabled()) { logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + getReaderContext().getResource()); } return; } } } // 解析前处理目前是空处理,可以继承,由子类去实现 preProcessXml(root); // 解析xml为BeanDefinition并向容器注册生成的BeanDefinition【3】 parseBeanDefinitions(root, this.delegate); // 解析后处理,目前为空执行,子类可继承处理 postProcessXml(root); // 设置为最初的BeanDefinitionParserDelegate this.delegate = parent; }
【1】 检查
<beans />
根标签的命名空间是否为空,或者是http://www.springframework.org/schema/beans
【2】检查beans标签的是否指定profile环境注册,若profile参数是不满足条件,则不注册
【3】解析element(<beans />
)下的<bean/>
元素并注册到BeanDefinition的map容器中。
说明:createDelegate
方法执行主要是创建代理,然后代理首先初始化一些默认的属性,DocumentDefaultsDefinition是存储默认配置的对象:default-lazy-init
、default-merge
、default-autowire
、default-dependency-check
、default-autowire-candidates
、default-init-method
、default-destroy-method
。 -
parseBeanDefinitions处理逻辑解析
/** * Parse the elements at the root level in the document: "import", "alias", "bean". * * @param root the DOM root element of the document */ protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { // 如果该节点使用默认命名空间,执行默认解析【1】 if (delegate.isDefaultNamespace(root)) { // root节点下的子节点【2】 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; // 如果该节点使用默认命名空间,执行默认解析【3】 if (delegate.isDefaultNamespace(ele)) { parseDefaultElement(ele, delegate); } else { // 如果该节点非默认命名空间,执行自定义解析【4】 delegate.parseCustomElement(ele); } } } } else {// 如果根节点非默认命名空间,执行自定义解析【5】 delegate.parseCustomElement(root); } }
【1】如果该节点使用默认命名空间,执行默认解析
【2】root节点下的子节点
【3】如果该节点使用默认命名空间,执行默认解析
【4】如果该节点非默认命名空间,执行自定义解析
【5】如果该节点非默认命名空间,执行自定义解析 -
parseDefaultElement处理逻辑解析
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { // import标签 if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele); // alias 解析 } else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele); //bean 解析 } else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { processBeanDefinition(ele, delegate); // beans元素解析 } else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { //递归解析beans doRegisterBeanDefinitions(ele); } }
-
processBeanDefinition处理逻辑解析
/** * Process the given bean element, parsing the bean definition and registering it with the registry. */ protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { // 委托BeanDefinition类的parseBeanDefinitionElement方法进行元素解析,返回Beandefinition 【1】 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { // 当返回的bdHolder 不为空的情况下,若存在默认标签的子节点下再有自定义属性,还需要再次对自定义标签进行解析.【2】 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // Register the final decorated instance. // 最终执行注册逻辑【3】 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } // Send registration event. // 下发注册事件,通知相关的监听器,这个bean已经加载完成【4】 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }
【1】委托BeanDefinition类的parseBeanDefinitionElement方法进行元素解析,返回Beandefinition ,此时的bdHolder实例已经包含了我们配置文件中的各种属性了,例如 : class,name,id,alias
【2】当返回的bdHolder 不为空的情况下,若存在默认标签的子节点下再有自定义属性,还需要再次对自定义标签进行解析.
【3】最终执行BeanDefinition注册逻辑
【4】下发注册事件,通知相关的监听器,这个bean已经加载完成
-
registryBeanDefinition的注册逻辑分析
从代码上分析我们的registryBeanDefinition的最终执行是在是通过
public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
,注册的过程是在解析xml过程中完成注册逻辑的。//--------------------------------------------------------------------- // Implementation of BeanDefinitionRegistry interface //--------------------------------------------------------------------- // 注册BeanDefinition @Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { // 校验 beanName 与 beanDefinition 非空 Assert.hasText(beanName, "Bean name must not be empty"); Assert.notNull(beanDefinition, "BeanDefinition must not be null"); if (beanDefinition instanceof AbstractBeanDefinition) { try { // 【1】 校验BeanDefinition,这也是注册前的最后一次校验了,主要是对属性 methodOverrides 进行校验。 ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex); } } //【2】从缓存中获取指定beanName的 BeanDefinition,主要 判断bean name下是否已经注册过BeanDefinition BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName); //【3】如果改BenDefinition已经注册,如果不允许覆盖的话,则抛出异常 if (existingDefinition != null) { if (!isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); } // 当前要注册的BeanDefinition的role 大于 已经注册过的BeanDefinition 打印info 日志 else if (existingDefinition.getRole() < beanDefinition.getRole()) { // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE if (logger.isInfoEnabled()) { logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } // 当前要注册的BeanDefinition与已被覆盖的BeanDefinition不是一个对象,打印Debug日志信息 else if (!beanDefinition.equals(existingDefinition)) { if (logger.isDebugEnabled()) { logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } // 打印 trace日志信息 else { if (logger.isTraceEnabled()) { logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } // 覆盖已经注册的bean信息 this.beanDefinitionMap.put(beanName, beanDefinition); } // 【4】未注册执行注册逻辑 else { // 判断Bean的创建阶段是否已经开启,开启的话需要对beanDefinitionMap进行线程保护 if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) // beanDefinitionMap为全局变量,加锁保护,防止创建阶段和注册阶段的并发问题 synchronized (this.beanDefinitionMap) { // 添加到BeanDefinition的map 容器中 this.beanDefinitionMap.put(beanName, beanDefinition); // 添加BeanName到 beanDefinitionNames中去(beanDefinitionNames初始化限制了大小为256,所以变更的时候需要引入一个中间变量-主要是扩容问题) List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1); // 更新最新的beanDefinitionNames updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; // 从 manualSingletonNames 移除 beanName removeManualSingletonName(beanName); } } else { // Still in startup registration phase // 添加到 BeanDefinition 到 beanDefinitionMap 中。 this.beanDefinitionMap.put(beanName, beanDefinition); // 添加 beanName 到 beanDefinitionNames 中 this.beanDefinitionNames.add(beanName); // 从 manualSingletonNames 移除 beanName removeManualSingletonName(beanName); } this.frozenBeanDefinitionNames = null; } // 【5】重新设置beanName对应的缓存 if (existingDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } }
【1】对
BeanDefinition
进行校验,这也是注册过程中最后一次校验了,主要是针对AbstractBeanDefinition
的methodOverride
属性进行校验。
【2】根据beanName从缓存中获取BeanDefinition。
【3】如果缓存中已经存在,则根据allowBeanDefinitionOverriding标签判断是否允许覆盖,如果不允许覆盖,则抛出BeanDefinitionStoreException
异常。
【4】若缓存中没有beanName 的BeanDefinition
对象,则判断当前阶段是否已经开始了Bean的创建阶段,如果是则对仅限并发保护,对BeanDefinitionMap
进行加锁并发控制。否则直接设置即可。
【5】若缓存存在改beanName或者单例bean集合中存在该beanName,则调用#resetBeanDefinition(beanName)
方法,充值BeanDefinition缓存。整个阶段的核心流程其实就是对beanDefinitionMap的操作,只要核心在于
this.beanDefinitionMap.put(beanName, beanDefinition)
方法,而BeanDefinition的存储其实就是定义了个map,key为beanName,value为BeanDefinition。
小结
网友评论