Spring Bean加载探究(一)

在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 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.这种, Spring可以按照默认的解析方法解析, 如果不是, 则可能是,而这些则需要用户自定义解析器来解析

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加载探究(一))