Spring 基于ClassPathXmlApplicationContext的初始化流程02-xml默认标签解析过程

 

       上一小节中,我们最终跟踪到了DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)方法。在该方法中,进行了两部分的标签解析,一个是默认标签解析,一个是自定义标签解析,本节我们先看默认标签解析,进入到默认标签解析方法:

DefaultBeanDefinitionDocumentReader

    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        if (delegate.nodeNameEquals(ele, "import")) {
            this.importBeanDefinitionResource(ele);
        } else if (delegate.nodeNameEquals(ele, "alias")) {
            this.processAliasRegistration(ele);
        } else if (delegate.nodeNameEquals(ele, "bean")) {
            //处理<bean>标签
            this.processBeanDefinition(ele, delegate);
        } else if (delegate.nodeNameEquals(ele, "beans")) {
            this.doRegisterBeanDefinitions(ele);
        }

    }

该方法主要是对<import><alias><bean><beans>这几个默认标签进行解析,我们平时用到的最多的是<bean>标签,进入到 this.processBeanDefinition(ele, delegate)记录其具体的实现过程:

DefaultBeanDefinitionDocumentReader

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        //1、解析bean标签中的属性,将其封装成bd对象,再将bd对象和beanName、alias封装成BeanDefinitionHolder对象返回
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);

            try {
                //2、将BeanDefinitionHolder对象注册到BeanDefinitionMap容器中
                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));
        }

    }

delegate.parseBeanDefinitionElement(ele)步骤解析

       方法中的第一步,delegate.parseBeanDefinitionElement(ele)的作用是解析<bean>标签中的所有属性,将解析出来的标签属性封装成GenericBeanDefinition对象。BeanDefinition对象在Spring容器初始化过程中扮演着极其重要的角色,后面我单独用一个小节来记录BeanDefinition,这里只是简要做一些说明,GenericBeanDefinition对象包含了一个普通的JavaBean经过完整Spring生命周期变成一个SpringBean所需要的所有信息,里面包含了beanClass、scope等关键属性,这里是通过一个代理对象BeanDefinitionParserDelegate进行实际的标签解析,进入该方法:

BeanDefinitionParserDelegate

@Nullable
    public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
        //解析bean标签中的id属性
        String id = ele.getAttribute("id");
        //解析bean标签中的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);
        }

        //实际解析bean标签属性的方法,并生成BeanDefinition对象
        AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);
        if (beanDefinition != null) {
            if (!StringUtils.hasText(beanName)) {
                try {
                    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);
            //将生成的BeanDefinition对象最终再封装成一个BeanDefinitionHolder对象
            return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
        } else {
            return null;
        }
    }

进入this.parseBeanDefinitionElement(ele, beanName, containingBean),实现如下:

BeanDefinitionParserDelegate

@Nullable
    public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean) {
        this.parseState.push(new BeanEntry(beanName));
        String className = null;
        if (ele.hasAttribute("class")) {
            //获取bean标签中的class属性
            className = ele.getAttribute("class").trim();
        }

        String parent = null;
        //判断bean标签中是否包含parent属性,如果有则解析parent
        if (ele.hasAttribute("parent")) {
            parent = ele.getAttribute("parent");
        }

        try {
            AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);
            this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
            bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
            this.parseMetaElements(ele, bd);
            this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
            this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
            this.parseConstructorArgElements(ele, bd);
            this.parsePropertyElements(ele, bd);
            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;
    }

方法中的第一步,获取到<bean>标签中的class属性和parent属性(非必须),将获取到的className和parent传入this.createBeanDefinition(className, parent)方法中,返回一个GenericBeanDefinition对象。

BeanDefinitionParserDelegate

protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName) throws ClassNotFoundException {
        //通过BeanDefinitionReaderUtils工具类创建BeanDefinition
        return BeanDefinitionReaderUtils.createBeanDefinition(parentName, className, this.readerContext.getBeanClassLoader());
    }


BeanDefinitionReaderUtils

public static AbstractBeanDefinition createBeanDefinition(@Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
        //直接new出一个GenericBeanDefinition对象
        GenericBeanDefinition bd = new GenericBeanDefinition();
        bd.setParentName(parentName);
        if (className != null) {
            if (classLoader != null) {
                bd.setBeanClass(ClassUtils.forName(className, classLoader));
            } else {
                bd.setBeanClassName(className);
            }
        }

        return bd;
    }

可以看到,方法中就是直接简单粗暴的new出了一个GenericBeanDefinition对象,然后将beanClassName赋值给GenericBeanDefinition中的beanClass属性,但此时的BeanDefinition对象中的属性还都没有赋值,在后面的步骤中会依次将GenericBeanDefinition中的所有属性填充上。

第二步,this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd)方法用于解析bean标签中的所有属性,并填充GenericBeanDefinition对象

BeanDefinitionParserDelegate

public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {
        if (ele.hasAttribute("singleton")) {
            //解析singleton属性,最新版本已经去掉
            this.error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
        } else if (ele.hasAttribute("scope")) {
            //解析scope属性,如果不设置,则scope=""
            bd.setScope(ele.getAttribute("scope"));
        } else if (containingBean != null) {
            bd.setScope(containingBean.getScope());
        }

        //判断bean上是否加了abstract属性
        if (ele.hasAttribute("abstract")) {
            bd.setAbstract("true".equals(ele.getAttribute("abstract")));
        }

        //获取bean标签上的lazy-init属性,默认lazyInit="default"
        String lazyInit = ele.getAttribute("lazy-init");
        if (this.isDefaultValue(lazyInit)) {
            //如果lazyInit="default",则lazyInit = "false"
            lazyInit = this.defaults.getLazyInit();
        }

        bd.setLazyInit("true".equals(lazyInit));
        //获取bean的注入模式,默认autowire="default"
        String autowire = ele.getAttribute("autowire");
        //将注入模式转化为数字类型,依照下面的对应关系:
        //byName:1 , byType:2 , constructor:3 , autodetect:4 , default:0
        //因此,默认情况下bd.autowireMode="0"
        bd.setAutowireMode(this.getAutowireMode(autowire));
        String autowireCandidate;
        //获取bean标签的depend-on属性,非必须
        if (ele.hasAttribute("depends-on")) {
            autowireCandidate = ele.getAttribute("depends-on");
            bd.setDependsOn(StringUtils.tokenizeToStringArray(autowireCandidate, ",; "));
        }

        //获取bean标签的autowire-candidate属性,如果没有设置则为默认是"default"
        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));
        }

        //获取bean标签的primary属性,非必须
        if (ele.hasAttribute("primary")) {
            bd.setPrimary("true".equals(ele.getAttribute("primary")));
        }

        //获取bean标签上的init-method属性,非必须,init-method方法用于springbean完成生命周期后的回调
        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);
        }

        //获取bean上的destory-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);
        }

        //获取bean上的factory-method属性,该属性的作用是使用指定的工厂方法来实例化一个springbean
        if (ele.hasAttribute("factory-method")) {
            bd.setFactoryMethodName(ele.getAttribute("factory-method"));
        }

        //获取bean上的factory-bean属性,该属性的作用是使用指定bean的指定方法来实例化一个bean
        if (ele.hasAttribute("factory-bean")) {
            bd.setFactoryBeanName(ele.getAttribute("factory-bean"));
        }
        //这一步完成了bean标签中所有attribute的解析,并存入bd对应的属性中
        return bd;
    }

第三步,this.parseMetaElements(ele, bd)解析meta信息,这一步省略

第四步,调用this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides())方法,获取<bean>标签下的<lookup-method>子标签,从子标签中获取到bean属性和name属性,封装成一个LookupOverride对象,加入GenericBeanDefinitionMethodOverridesMethodOverrides中维护了一个Set集合。

BeanDefinitionParserDelegate

public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) {
        NodeList nl = beanEle.getChildNodes();

        for(int i = 0; i < nl.getLength(); ++i) {
            Node node = nl.item(i);
            if (this.isCandidateElement(node) && this.nodeNameEquals(node, "lookup-method")) {
                Element ele = (Element)node;
                String methodName = ele.getAttribute("name");
                String beanRef = ele.getAttribute("bean");
                //封装成一个LookupOverride对象,LookupOverride类是MethodOverride的子类,他们之间的继承关系:
                //public class LookupOverride extends MethodOverride
                LookupOverride override = new LookupOverride(methodName, beanRef);
                override.setSource(this.extractSource(ele));
                //overrides对应bd的methodOverrides,里面保存的是一个set集合
                overrides.addOverride(override);
            }
        }

    }

注:<lookup-method>标签的作用是可以在<bean>标签中定义一个抽象类,同时在<lookup-method>子标签的name属性中定义其抽象方法,该抽象方法返回父类对象,然后在bean属性中指定具体要实例化的子类对象,例如:

/**
* 定义一个抽象类
* 其中包含一个抽象方法getVehicle(),返回父类Vehicle对象
*/
public abstract class VehicleService {
    public abstract Vehicle getVehicle();
}

定义Vehicle的两个子类,Car和Truck

/*
* 定义一个Car子类继承Vehicle
*/
public class Car extends Vehicle {
    public Car(){
        System.out.println("This is a Car");
    }
}

/*
* 定义一个Truck子类继承Vehicle
*/
public class Truck extends Vehicle {
    public Truck(){
        System.out.println("This is a Truck");
    }
}

在spring.xml文件中加入配置:

    <!--定义car实例-->
    <bean id="car" class="com.sgcc.uvmp.beans.Car"></bean>
    <!--定义truck实例-->
    <bean id="truck" class="com.sgcc.uvmp.beans.Truck"></bean>
    <!--定义carService class指定为抽象VehicleService类型,在lookup-method标签中定义实际返回的子类为car-->
    <bean id="carService" class="com.sgcc.uvmp.beans.VehicleService">
        <lookup-method bean="car" name="getVehicle"></lookup-method>
    </bean>

    <!--定义truckService class指定为抽象VehicleService类型,在lookup-method标签中定义实际返回的子类为truck-->
    <bean id="truckService" class="com.sgcc.uvmp.beans.VehicleService">
        <lookup-method bean="truck" name="getVehicle"></lookup-method>
    </bean>

在方法中进行测试:

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");

//获取carService,调用getVehicle()方法实际得到的是car对象
VehicleService vehicleService = (VehicleService) context.getBean("carService");
vehicleService.getVehicle();

//获取truckService,调用getVehicle()方法实际得到的是truck对象
VehicleService vehicleService2 = (VehicleService) context.getBean("truckService");
vehicleService2.getVehicle();

第五步,调用this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides())方法,解析<replaced-method>标签

BeanDefinitionParserDelegate

public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) {
        NodeList nl = beanEle.getChildNodes();

        for(int i = 0; i < nl.getLength(); ++i) {
            Node node = nl.item(i);
            //解析<bean>下<replaced-method>子标签
            if (this.isCandidateElement(node) && this.nodeNameEquals(node, "replaced-method")) {
                Element replacedMethodEle = (Element)node;
                //获取到子标签中的name和replacer属性
                String name = replacedMethodEle.getAttribute("name");
                String callback = replacedMethodEle.getAttribute("replacer");
                //封装成一个ReplaceOverride对象,和LookupOverride一样,同时也是继承MethodOverride
                ReplaceOverride replaceOverride = new ReplaceOverride(name, callback);
                List<Element> argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, "arg-type");
                Iterator var11 = argTypeEles.iterator();

                while(var11.hasNext()) {
                    Element argTypeEle = (Element)var11.next();
                    String match = argTypeEle.getAttribute("match");
                    match = StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle);
                    if (StringUtils.hasText(match)) {
                        replaceOverride.addTypeIdentifier(match);
                    }
                }

                replaceOverride.setSource(this.extractSource(replacedMethodEle));
                //同样加入到bd.methodOverrides集合中
                overrides.addOverride(replaceOverride);
            }
        }

    }

注:<replaced-method>标签的作用是可以替换一个bean中的原有方法,当调用对象原来的方法时,实际调用的是被替换后的方法,例如:

public class PersonService {
    //这是替换前的方法
    public void printSex(){
        System.out.println("This is a Boy");
    }
}
/**
*   这是方法替换的类,必须要实现MethodReplacer接口,并实现reimplement方法,在reimplement方法体内部对原方法进行重写
*/
public class MethodReplace implements MethodReplacer {
    public Object reimplement(Object o, Method method, Object[] objects) throws Throwable {
        System.out.println("This is a Girl");
        return null;
    }
}
    <bean id="methodReplace" class="com.sgcc.uvmp.beans.MethodReplace"></bean>
    <bean id="person" class="com.sgcc.uvmp.beans.PersonService">
        <!--在这个标签里指定需要重写的方法名,以及替换类的id-->
        <replaced-method name="printSex" replacer="methodReplace"></replaced-method>
    </bean>
PersonService personService = context.getBean(PersonService.class);
//获取personService实例,然后调用printSex()方法,但实际调用的是MethodReplace类中的逻辑
//方法实现被替换了
personService.printSex();

第六步,调用this.parseConstructorArgElements(ele, bd)方法,解析<constructor-arg>子标签,并存入bd的ConstructorArgumentValues属性,比较简单,这里忽略。

第七步,调用this.parsePropertyElements(ele, bd)方法,解析<property>子标签,并存入bd的MutablePropertyValues属性。MutablePropertyValues类内部维护了一个List<PropertyValue>类型的集合,可以保存多个<property>子标签的值。

private final List<PropertyValue> propertyValueList;

第八步,调用this.parseQualifierElements(ele, bd)方法,解析<qualifier>子标签,并存如bd的qualifiers属性,这里不常用,我就先不记录了。

至此,this.parseBeanDefinitionElement(ele, beanName, containingBean)方法调用完成,bd中的属性都已经填充完毕,后面又将bd封装成了一个BeanDefinitionHolder对象,对象中包含了bd的实例,beanName以及aliases别名,将此对象返回。这一步操作的目的,我认为只是为了方便后面获取beanName以及通过beanName获取对应的bd实例。

BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry())方法解析

将上面步骤中封装成的BeanDefinitionHolder对象及BeanDefinitionRegistry对象传入该方法中,将bd对象加入到bd容器中,具体看方法实现

public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
        String beanName = definitionHolder.getBeanName();
        //这一步从BeanDefinitionHolder对象中取出beanName对应的bd对象,加入到BeanDefinitionRegistry注册器中
        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,可以认为这是BeanDefinition的注册器,里面注册了Spring容器启动过程中所有的BeanDefinition对象,它是一个接口,我们的Spring容器在一开始会创建一个DefaultListableBeanFactory对象,这就是常说的Bean工厂,里面维护了所有生成的Bean实例,我们常用的通过ApplicationContext.getBean()来获取Bean,其实就是从这个Bean工厂中获取的,DefaultListableBeanFactory这个类本身就实现了BeanDefinitionRegistry说白了Spring初始化容器时加载的所有BeanDefinition对象也都维护在这个Bean工厂类中,来记录一下类的集成关系。

/**
*    DefaultListableBeanFactory实现了BeanDefinitionRegistry接口
*/

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable

接下来一个重要的方法就是registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()),这个方法的作用应该就是将bd对象加入到容器中,进入方法看实现

DefaultListableBeanFactory

/**
*    该方法核心的作用就是将beanName加入到beanDefinitionNames中,同时把beanName和bd对象的映射关系加入到beanDefinitionMap集合中
*/
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);
            }
        }

        BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
        if (existingDefinition != null) {
            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 {
            if (this.hasBeanCreationStarted()) {
                Map var4 = this.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 {
                this.beanDefinitionMap.put(beanName, beanDefinition);
                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);
        }

    }

这个方法中,涉及到两个重要的集合对象,beanDefinitionNames和beanDefinitionMap,beanDefinitionNames是ArrayList类型,用于存放所有的beanName,beanDefinitionMap是ConcurrentHashMap类型,用于存放所有的beanName和bd对象的映射关系,在后面做bean实例化时,还会用到这两个集合,这里我们先记下来,在后面的记录中我们还会看到这两个对象。

到此为止,bean标签的解析过程完成。总结起来,一个bean标签的解析过程首先是从xml配置文件中将<bean>标签中的属性(Attribute)解析出来,然后将子标签中的属性解析出来,将解析出来的所有属性都对应赋值到一个Beandefinition对象的属性中,完成bd对象的封装,最终将该bd对象注册到BeanDefinitionRegistry容器中维护的beanDefinitionMap和beanDefinitionNames两个集合中,完成收集。

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值