zoukankan      html  css  js  c++  java
  • spring IOC 之篇三:默认标签的解析

    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)) {
                // recurse
                doRegisterBeanDefinitions(ele);
            }
        }

    这里主要分新bean标签的处理,其他都类似

    /**
         * Process the given bean element, parsing the bean definition
         * and registering it with the registry.
         */
        protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {      
    // 首先委托 BeanDefinitionParserDelegate 类的parseBeanDefinitionElement方法进行元素的解析,返回实例BeanDefinitionHolder 对象,经过这个方法后,bdHolder实例已经包含我们配置的配置文件中的各种属性了,列如:class,id,alias之类的属性了。
            BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
            if (bdHolder != null) {
    // 当返回的BeanDefinitionHolder对象实例 bdHolder不为空的情况下若存在默认标签的字节点下再有自定义属性,还需要再次对自定义属性进行解析。
                bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
                try {
                    // Register the final decorated instance.
    //解析完成后,需要对解析后的bdHolder进行注册,同样,注册操作委托给了BeanDefinitionReaderUtils的registerBeanDefinition方法。
                    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已经加载完成了。
                getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
            }
        }

    继续深入分析 BeanDefinitionParserDelegate 类的parseBeanDefinitionElement方法:

    /**
         * Parses the supplied {@code <bean>} element. May return {@code null}
         * if there were errors during parse. Errors are reported to the
         * {@link org.springframework.beans.factory.parsing.ProblemReporter}.
         */
        public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
           // 解析id属性
            String id = ele.getAttribute(ID_ATTRIBUTE);
          // 解析name属性
            String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
           // 分隔name属性 
            List<String> aliases = new ArrayList<String>();
            if (StringUtils.hasLength(nameAttr)) {
                String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
                aliases.addAll(Arrays.asList(nameArr));
            }
    
            String beanName = id;
            if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
                beanName = aliases.remove(0);
                if (logger.isDebugEnabled()) {
                    logger.debug("No XML 'id' specified - using '" + beanName +
                            "' as bean name and " + aliases + " as aliases");
                }
            }
    
            if (containingBean == null) {
                checkNameUniqueness(beanName, aliases, ele);
            }
            // 进一步解析bean的其他属性 并封装到对象 GenericBeanDefinition对象中
            AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
            if (beanDefinition != null) {
                if (!StringUtils.hasText(beanName)) {
                    try {
                        if (containingBean != null) {
                  // 如果不存在 beanName,则使用Spring提供的命名规则默认生成beanName
                            beanName = BeanDefinitionReaderUtils.generateBeanName(
                                    beanDefinition, this.readerContext.getRegistry(), true);
                        }
                        else {
            // 如果有则获取beanName
                            beanName = this.readerContext.generateBeanName(beanDefinition);
                            // Register an alias for the plain bean class name, if still possible,
                            // if the generator returned the class name plus a suffix.
                            // This is expected for Spring 1.2/2.0 backwards compatibility.
                            String beanClassName = beanDefinition.getBeanClassName();
                            if (beanClassName != null &&
                                    beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
                                    !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                                aliases.add(beanClassName);
                            }
                        }
                        if (logger.isDebugEnabled()) {
                            logger.debug("Neither XML 'id' nor 'name' specified - " +
                                    "using generated bean name [" + beanName + "]");
                        }
                    }
                    catch (Exception ex) {
                        error(ex.getMessage(), ele);
                        return null;
                    }
                }
                String[] aliasesArray = StringUtils.toStringArray(aliases);
    // 将获取到的信息封装到
    BeanDefinitionHolder 实例中去
    return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null; }

    接下来进一步分析对其他bean标签的解析方法:

    AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);

    /**
         * Parse the bean definition itself, without regard to name or aliases. May return
         * {@code null} if problems occurred during the parsing of the bean definition.
         */
        public AbstractBeanDefinition parseBeanDefinitionElement(
                Element ele, String beanName, BeanDefinition containingBean) {
    
            this.parseState.push(new BeanEntry(beanName));
    
            String className = null;
          // 解析class属性
            if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
                className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
            }
    
            try {
                String parent = null;
              // 解析parent属性
                if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
                    parent = ele.getAttribute(PARENT_ATTRIBUTE);
                }
              // 创建用于承载bean各种标签的 GenericBeanDefinition对象
                AbstractBeanDefinition bd = createBeanDefinition(className, parent);
               // 硬编码解析bean的属性 例如:singleton、destroy-method等
                parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
              // 提取 desciption
                bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
              // 解析元数据
                parseMetaElements(ele, bd);
              // 解析lookup-method属性
                parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
            // 解析repalce-method属性
                parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
           // 解析构造函数参数
                parseConstructorArgElements(ele, bd);
         // 解析property字元素
                parsePropertyElements(ele, bd);
         // 解析qualifier子元素
                parseQualifierElements(ele, bd);
     
                bd.setResource(this.readerContext.getResource());
                bd.setSource(extractSource(ele));
    
                return bd;
            }
            catch (ClassNotFoundException ex) {
                error("Bean class [" + className + "] not found", ele, ex);
            }
            catch (NoClassDefFoundError err) {
                error("Class that bean class [" + className + "] depends on not found", ele, err);
            }
            catch (Throwable ex) {
                error("Unexpected failure during bean definition parsing", ele, ex);
            }
            finally {
                this.parseState.pop();
            }
    
            return null;
        }

    进一步分析创建属性承载的BeanDefinition对象

    BeanDefinition是一个接口,spring中三种实现形式:RootBeanDefinitionChildBeanDefinitionGenericBeanDefinition。三种实现类均继承了AbstractBeanDefinition,其中BeanDefinition<bean>标签在容器内部的表现形式,BeanDefinition<bean>的属性是一一对应的。Spring通过BeanDefinition将配置文件中的信息装换为内部的表现形式,并将这些BeanDefinition注册到BeanDefinitionRegistry中。

     至此 已经完成XML文档像GenericBeandefinition的全部装换。GenericBeandefinition只是子类实现,大部分属性封装在AbstractBeandefinition对象中,我们继续分析AbstractBeandefinition的给中属性:

    @SuppressWarnings("serial")
    public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
            implements BeanDefinition, Cloneable {
    
        /**
         * Constant for the default scope name: {@code ""}, equivalent to singleton
         * status unless overridden from a parent bean definition (if applicable).
         */
        public static final String SCOPE_DEFAULT = "";
    
        /**
         * Constant that indicates no autowiring at all.
         * @see #setAutowireMode
         */
        public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;
    
        /**
         * Constant that indicates autowiring bean properties by name.
         * @see #setAutowireMode
         */
        public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
    
        /**
         * Constant that indicates autowiring bean properties by type.
         * @see #setAutowireMode
         */
        public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
    
        /**
         * Constant that indicates autowiring a constructor.
         * @see #setAutowireMode
         */
        public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
    
        /**
         * Constant that indicates determining an appropriate autowire strategy
         * through introspection of the bean class.
         * @see #setAutowireMode
         * @deprecated as of Spring 3.0: If you are using mixed autowiring strategies,
         * use annotation-based autowiring for clearer demarcation of autowiring needs.
         */
        @Deprecated
        public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
    
        /**
         * Constant that indicates no dependency check at all.
         * @see #setDependencyCheck
         */
        public static final int DEPENDENCY_CHECK_NONE = 0;
    
        /**
         * Constant that indicates dependency checking for object references.
         * @see #setDependencyCheck
         */
        public static final int DEPENDENCY_CHECK_OBJECTS = 1;
    
        /**
         * Constant that indicates dependency checking for "simple" properties.
         * @see #setDependencyCheck
         * @see org.springframework.beans.BeanUtils#isSimpleProperty
         */
        public static final int DEPENDENCY_CHECK_SIMPLE = 2;
    
        /**
         * Constant that indicates dependency checking for all properties
         * (object references as well as "simple" properties).
         * @see #setDependencyCheck
         */
        public static final int DEPENDENCY_CHECK_ALL = 3;
    
        /**
         * Constant that indicates the container should attempt to infer the
         * {@link #setDestroyMethodName destroy method name} for a bean as opposed to
         * explicit specification of a method name. The value {@value} is specifically
         * designed to include characters otherwise illegal in a method name, ensuring
         * no possibility of collisions with legitimately named methods having the same
         * name.
         * <p>Currently, the method names detected during destroy method inference
         * are "close" and "shutdown", if present on the specific bean class.
         */
        public static final String INFER_METHOD = "(inferred)";
    
    
        private volatile Object beanClass;
       // bean的作用范围,对应bean的属性 scope
        private String scope = SCOPE_DEFAULT;
     // 是否抽象标识,默认false,对应bean的属性 abstract
        private boolean abstractFlag = false;
     // 是否延迟加载,对应bean的属性 lazy-init
        private boolean lazyInit = false;
     // 是否自动注入模式,对应bean的属性autowire
        private int autowireMode = AUTOWIRE_NO;
    // 依赖检查,spring3以后弃用这个属性
        private int dependencyCheck = DEPENDENCY_CHECK_NONE;
    // 用来表示一个bean的实例化,依赖另一个bean实例化,对应bean的属性depend-on
        private String[] dependsOn;
    // autowire-candidate属性设置为false,这样容器在查找自动装配对象的时候,将不会考虑该bean,即不会考虑该bean作为其他bean的自动装配候选者
        private boolean autowireCandidate = true;
    // 当自动装配出现多个bean,如果primary为true,则改bean作为首席候选者
        private boolean primary = false;
    // 用于记录 Qualifier 对应子元素 qualifier
        private final Map<String, AutowireCandidateQualifier> qualifiers =
                new LinkedHashMap<String, AutowireCandidateQualifier>(0);
    
        private boolean nonPublicAccessAllowed = true;
    
        private boolean lenientConstructorResolution = true;
        
    //记录构造函数注入属性,对应属性值 constructor-arg
        private ConstructorArgumentValues ArgumentValues;
    // 普通属性集合
        private MutablePropertyValues propertyValues;
    // 记录 lookup-method和replace-method属性值
        private MethodOverrides methodOverrides = new MethodOverrides();
    
        private String factoryBeanName;
    
        private String factoryMethodName;
    // 初始化方法 对应属性 init-method
        private String initMethodName;
    // 销毁方法 对应属性 destroy-method
    private String destroyMethodName;
    // 是否执行 init-method 程序设置
        private boolean enforceInitMethod = true;
    // 是否执行 destroy-method 程序设置
        private boolean enforceDestroyMethod = true;
    
       // 使用用户自定义而不是应用程序本身定义的,创建AOP时候为true
     private boolean synthetic = false;
    
        private int role = BeanDefinition.ROLE_APPLICATION;
    
    private String description; 
    // 这个bean定义的资源
        private Resource resource;

    解析完成以后,会将所有的xml属性值封装至对象 GenericBeanDefinition中,然后会进行注册。

    针对以下代码进行分析:

    BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())

    // 解析完以后,BeanDefinition对象就注册到了BeanDefinitionRegisty集合中去了。将beanName作为Key,BeanDefinition作为value

    /**
         * Register the given bean definition with the given bean factory.
         * @param definitionHolder the bean definition including name and aliases
         * @param registry the bean factory to register with
         * @throws BeanDefinitionStoreException if registration failed
         */
        public static void registerBeanDefinition(
                BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
                throws BeanDefinitionStoreException {
    
            // Register bean definition under primary name.
           // 使用beanName作为唯一注册标识
            String beanName = definitionHolder.getBeanName();
            registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    
            // Register aliases for bean name, if any.
           // 注册所有的bean的别名
            String[] aliases = definitionHolder.getAliases();
            if (aliases != null) {
                for (String alias : aliases) {
                    registry.registerAlias(beanName, alias);
                }
            }
        }

    继续深入解析:

    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

    @Override
        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 中的methodOverrides 属性,校验methodOverrides是否与工厂方法共存,或者对应的方法根本不存在
                    ((AbstractBeanDefinition) beanDefinition).validate();
                }
                catch (BeanDefinitionValidationException ex) {
                    throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                            "Validation of bean definition failed", ex);
                }
            }
    
            BeanDefinition oldBeanDefinition;
    
            oldBeanDefinition = this.beanDefinitionMap.get(beanName);
            if (oldBeanDefinition != null) {
          // 对于已经注册过的bean,如果不允许覆盖,则直接抛出异常
                if (!isAllowBeanDefinitionOverriding()) {
                    throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                            "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
                            "': There is already [" + oldBeanDefinition + "] bound.");
                }
                else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
                    // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
                    if (this.logger.isWarnEnabled()) {
                        this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
                                "' with a framework-generated bean definition: replacing [" +
                                oldBeanDefinition + "] with [" + beanDefinition + "]");
                    }
                }
                else if (!beanDefinition.equals(oldBeanDefinition)) {
                    if (this.logger.isInfoEnabled()) {
                        this.logger.info("Overriding bean definition for bean '" + beanName +
                                "' with a different definition: replacing [" + oldBeanDefinition +
                                "] with [" + beanDefinition + "]");
                    }
                }
                else {
                    if (this.logger.isDebugEnabled()) {
                        this.logger.debug("Overriding bean definition for bean '" + beanName +
                                "' with an equivalent definition: replacing [" + oldBeanDefinition +
                                "] with [" + beanDefinition + "]");
                    }
                }
                this.beanDefinitionMap.put(beanName, beanDefinition);
            }
            else {
                if (hasBeanCreationStarted()) {
                    // Cannot modify startup-time collection elements anymore (for stable iteration)
    //因为 beanDefinitionMap 是全局变量,这里会存在并发的情况
                    synchronized (this.beanDefinitionMap) {
                        this.beanDefinitionMap.put(beanName, beanDefinition);
                        List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
                        updatedDefinitions.addAll(this.beanDefinitionNames);
                        updatedDefinitions.add(beanName);
                        this.beanDefinitionNames = updatedDefinitions;
                        if (this.manualSingletonNames.contains(beanName)) {
                            Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
                            updatedSingletons.remove(beanName);
                            this.manualSingletonNames = updatedSingletons;
                        }
                    }
                }
                else {
                    // Still in startup registration phase
                 // 注册beanDefinition
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                // 记录所有的beanNames
                    this.beanDefinitionNames.add(beanName);
                    this.manualSingletonNames.remove(beanName);
                }
                this.frozenBeanDefinitionNames = null;
            }
    
            if (oldBeanDefinition != null || containsSingleton(beanName)) {
             // 重置beanName所有的对应的缓存
                resetBeanDefinition(beanName);
            }
        }

    注册完成,通知所有的监听事件:

    getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));

    这里是spring留给子类进行扩展的。

  • 相关阅读:
    Mac下Intellij IDEA Console中文是?
    MAC && Linux terminal session clone
    高扩展性网站的原则
    职场感悟
    如何保持自己 fork 的项目和原始项目同步
    统一回复一下同学们的咨询
    Can't exec "aclocal": No such file or directory at /usr/share/autoconf/Autom4te/FileUtils.pm line 326.
    checking for tgetent()... configure: error: NOT FOUND!
    Simultaneous Tag Editing in IntelliJ IDEA 14.1
    Mac 配置 vim
  • 原文地址:https://www.cnblogs.com/histlyb/p/8977554.html
Copyright © 2011-2022 走看看