美文网首页
Spring Bean加载探究(一)

Spring Bean加载探究(一)

作者: IceBins | 来源:发表于2017-10-18 13:04 被阅读0次

    在Spring中,容器的加载一般是经过如下过程

    1.创建Beanfactory对象

    2.调用Beanfactory对象的initBeanDefinitionReader

    3.调用Beanfactory对象的loadBeanDefinitions

    一. initBeanDefinitionReader

    1.1   构造XmlBeanDefinitionReader,在这个对象中构造了errorHandler, validationModeDetector, resourcesCurrentlyBeingLoaded,设置当前的registry

    this.errorHandler =newSimpleSaxErrorHandler(this.logger);

    this.validationModeDetector =newXmlValidationModeDetector();

    this.resourcesCurrentlyBeingLoaded =newNamedThreadLocal("XML bean definition resources currently being loaded");

    1.2   setValidating(boolean)

    二. loadBeanDefinitions

    2.1 入口

    Resource[] configResources =this.getConfigResources();

    if(configResources !=null) {

          reader.loadBeanDefinitions(configResources);

    }

    String[] configLocations =this.getConfigLocations();

    if(configLocations !=null) {

           reader.loadBeanDefinitions(configLocations);

    }

    2.2 进一步处理流程如下

    for(int var5 = 0; var5 < var4; ++var5) {

    String location = var3[var5];

         counter += this.loadBeanDefinitions(location);

    }

    2.3 进一步处理流程如下:

    return this.loadBeanDefinitions(location,(Set)null);

    进一步处理调用流程为AbstractBeanDefinitionReader的loadBeanDefinitions(String location, Set<Resource> actualResources);

     2.3.1 在这里又会执行如下操作

     2.3.1.1 首先获得resourceLoader

     2.3.1.2 如果resource的模式不是ResourcePatternResolver, 说明是单个resource, 执行一些操作

    if(!(resourceLoaderinstanceofResourcePatternResolver)) {

        Resource var11 = resourceLoader.getResource(location);

        loadCount =this.loadBeanDefinitions((Resource)var11);

        if(actualResources !=null) {

            actualResources.add(var11);

         }

    2.3.1.3 如果resource的模式是ResourcePatternResolver, 说明是多个resource, 执行另外一些操作

    try{

        Resource[] resource = ((ResourcePatternResolver)resourceLoader).getResources(location);

        loadCount =this.loadBeanDefinitions(resource);

        if(actualResources !=null) {

        Resource[] var6 = resource;

        int var7 = resource.length;

        for(intvar8 =0;var8 < var7;++var8) {

        Resource resource1 = var6[var8];

             actualResources.add(resource1);

        }

    }

    4. 在上述的2,3操作最终都会走到XmlBeanDefinitionReader的loadBeanDefinitions(Resource resource)函数,该函数执行如下操作

    4.1. 根据Resource创建EncodedResource

    4.2  查看当前resourcesCurrentlyBeingLoaded 这个set是不是包含了正在准备加载的resource

        4.2.1 如果已经包含了,说明当前存在循环的import, 抛出异常

        4.2.2 如果没有包含,则执行正常的流程

    4.3  最终会走向doLoadBeanDefinitions函数,该函数位于XMlBeanDefinitionReader类中, 执行逻辑如下

       1.获得validationMode (XSD和DTD 后续研究) 总之就是验证类型不是dtd就是xsd

       2.执行DefaultDocumentLoader类的loadDocument函数

        在该函数中, 需要使用EntityResolver获取加载dtd/xsd文件对xml文件进行校验,该处后续详细解释.

       3.registerBeanDefinitions(document, resource)

         3.1 首先创建BeanDefinitionDocumentReader

        3.2 获取之前已经加载的bean数量

        3.3 执行最终的逻辑 doRegisterBeanDefinitions(Element root)

    3.3.1 首先获得profile属性,(root此时是根元素,一般是beans), 如果发现指定了profile,则把profile元素拆分出来,然后判断当前的环境是不是支持指定的profile

    3.3.2 方法的preProcessXml和postProcessXml是空函数,因此是为了子类继承重写而来

    3.3.3 最终执行逻辑在parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)中,执行逻辑是,1.<bean id= "" class="">这种, Spring可以按照默认的解析方法解析, 如果不是, 则可能是<tx:annotation-driven />,而这些则需要用户自定义解析器来解析

    if(delegate.isDefaultNamespace(root)) {

    NodeList nl = root.getChildNodes();

    for(inti =0; i < nl.getLength(); ++i) {

    Node node = nl.item(i);

    if(nodeinstanceofElement) {

    Element ele = (Element)node;

    if(delegate.isDefaultNamespace(ele)) {

    this.parseDefaultElement(ele, delegate);

    }else{

    delegate.parseCustomElement(ele);

    }

    }

    }else{

    delegate.parseCustomElement(root);

    }

    可见在此处,是执行parseDefaultElement或者是执行parseCustomElement走入了分歧,(DefaultBeanDefinitionDocumentReader)详见

    <<Spring Bean加载探究(二)>>

    相关文章

      网友评论

          本文标题:Spring Bean加载探究(一)

          本文链接:https://www.haomeiwen.com/subject/tropzttx.html