欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring IOC 加载过程(一 加载xml)

程序员文章站 2022-07-12 13:10:17
...

Spring IOC 加载过程

看过很多次Spring容器的源码,每次都没有记录,每次都看到放弃,这次下决心要学习一下源码了,所以写一篇博文来记录,也希望有各路大神来指点不足之处,话不多说,下面开始!

  1. 加载Context
  2. 创建beanFactory
  3. 加载xml

Spring容器结构图
Spring IOC 加载过程(一 加载xml)

加载Context

我是从一个web程序打断点一步一步跟代码走的,一个web程序的入口应该是web.xml文件

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring-config.xml</param-value>
</context-param>
<!-- 注册Spring ContextLoaderListener -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

web.xml中关于Spring的配置就这么简单,这里我们只看Spring的内容,暂时先不看SpringMVC(web)的内容
然后根据上面的配置进入代码(启动tomcat可以进入)

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
    public ContextLoaderListener() {
    }
    public ContextLoaderListener(WebApplicationContext context) {
        super(context);
    }
    /**
     * 初始化Spring容器入口
     */
    @Override
    public void contextInitialized(ServletContextEvent event) {
        initWebApplicationContext(event.getServletContext());
    }
    @Override
    public void contextDestroyed(ServletContextEvent event) {
        closeWebApplicationContext(event.getServletContext());
        ContextCleanupListener.cleanupAttributes(event.getServletContext());
    }

}

这里就是入口,其实就是执行了一个initWebApplicationContext(event.getServletContext())这个方法。我们进入方法来看:


    public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
        /* 
         *  WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = "org.springframework.web.context.WebApplicationContext.ROOT" servletContext中没有这个属性
         */
        if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
            throw new IllegalStateException(
                    "Cannot initialize context because there is already a root application context present - " +
                    "check whether you have multiple ContextLoader* definitions in your web.xml!");
        }

        Log logger = LogFactory.getLog(ContextLoader.class);
        servletContext.log("Initializing Spring root WebApplicationContext");
        if (logger.isInfoEnabled()) {
            logger.info("Root WebApplicationContext: initialization started");
        }
        //这里记录一个开始时间
        long startTime = System.currentTimeMillis();

        try {

            if (this.context == null) { //默认是null
                /*创建web应用上下文
                这里获取到的是默认给的 org.springframework.web.context.support.XmlWebApplicationContext这个类,
                创建web应用下文结束(创建了一个XmlWebApplicationContext对象)*/
                this.context = createWebApplicationContext(servletContext);
            }
            if (this.context instanceof ConfigurableWebApplicationContext) {
                //这里做一下转换
                ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
                if (!cwac.isActive()) {//这里初始值是false
                    if (cwac.getParent() == null) { //父容器为空,这里加载回来也是一个空,因为是初次加载还没有父容器
                        ApplicationContext parent = loadParentContext(servletContext);
                        cwac.setParent(parent);
                    }
                    //配置刷新Spring容器,这里是这个方法最重要的部分,我们后面解释
                    configureAndRefreshWebApplicationContext(cwac, servletContext);
                }
            }
            //把初始化好的Sping容器 放到 sevlet 容器中 这个属性就是上面判断的属性
           servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
            //获取类加载器
            ClassLoader ccl = Thread.currentThread().getContextClassLoader();
            if (ccl == ContextLoader.class.getClassLoader()) {
                currentContext = this.context;
            }
            else if (ccl != null) {
                currentContextPerThread.put(ccl, this.context);
            }

            if (logger.isDebugEnabled()) {
                logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +
                        WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
            }
            if (logger.isInfoEnabled()) {
                long elapsedTime = System.currentTimeMillis() - startTime;
                logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
            }

            return this.context;
        }
        catch (RuntimeException ex) {
            logger.error("Context initialization failed", ex);

            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
            throw ex;
        }
        catch (Error err) {
            logger.error("Context initialization failed", err);
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
            throw err;
        }
    }

下面我们看重点的方法configureAndRefreshWebApplicationContext(cwac, servletContext);这个方法,上代码

protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
        //这里wac.getId() 是类中id属性,内部初始化的方法就是ObjectUtils.identityToString(wac)
        if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
            // The application context id is still set to its original default value
            // -> assign a more useful id based on available information
            String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);//这里没有这个属性,为空
            if (idParam != null) {
                wac.setId(idParam);
            }
            else {
                // Generate default id...
                wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
                        ObjectUtils.getDisplayString(sc.getContextPath()));//设置一个新的id:org.springframework.web.context.WebApplicationContext:
            }
        }

        wac.setServletContext(sc);//将servletContext放入到Spring容器中
        String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
        if (configLocationParam != null) {
            wac.setConfigLocation(configLocationParam);//设置配置文件路径,classpath:spring-config.xml 这是我们在web.xml中配置的
        }
        ConfigurableEnvironment env = wac.getEnvironment();
        if (env instanceof ConfigurableWebEnvironment) {
            ((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
        }

        customizeContext(sc, wac);//这里其实什么都没干,因为没有相应的配置
        //刷新容器。
        wac.refresh();
    }

创建beanFactory

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 做准备工作. 这里对一些必要属性做了验证。
            prepareRefresh();
            // 告诉子类刷新内部bean工厂
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            //准备在这个上下文中使用bean工厂。
            prepareBeanFactory(beanFactory);
            try {
                // 允许在上下文子类中对bean工厂进行后处理。
                postProcessBeanFactory(beanFactory);
                // 调用在上下文中注册为bean的工厂处理器.
                invokeBeanFactoryPostProcessors(beanFactory);
                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);
                // 初始化此上下文的消息源.
                initMessageSource();
                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();
                // Initialize other special beans in specific context subclasses.
                onRefresh();
                // Check for listener beans and register them.
                registerListeners();
                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);
                // Last step: publish corresponding event.
                finishRefresh();
            }
            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }
                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();
                // Reset 'active' flag.
                cancelRefresh(ex);
                // Propagate exception to caller.
                throw ex;
            }
            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }

介绍obtainFreshBeanFactory()这个方法

/**
     * Tell the subclass to refresh the internal bean factory.
     * @return the fresh BeanFactory instance
     * @see #refreshBeanFactory()
     * @see #getBeanFactory()
     */
    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        //刷新beanFactory
        refreshBeanFactory();
        //获取beanFactory
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }

refreshBeanFactory()

protected final void refreshBeanFactory() throws BeansException {
        //清空原来的beanFactory(),其实这里也没有
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            //创建beanFactory,这里如果有父容器会加载父容器的beanFactory为当前beanFactory的parentBeanFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            //加载beanDefinitions 这里是对xml尽心校验并解析
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

加载xml

继续从上面的loadBeanDefinitions(beanFactory)这个方法开始

//类XmlWebApplicationContext
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // 为beanFactory创建一个beanDefinitionReader,用于读取xml,这里是xmlWebApplicatioContext类实现的这个方法,定义的是xmlBeanDefinitionReader
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

    // 设置黄建,资源加载器,资源处理类
    beanDefinitionReader.setEnvironment(getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

    // 初始化beanDefinitionReader (这个方法没有实体,留给用户自己扩展)
    initBeanDefinitionReader(beanDefinitionReader);
    // 加载资源
    loadBeanDefinitions(beanDefinitionReader);
}

//加载资源 //类XmlWebApplicationContext
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
        for (String configLocation : configLocations) {
            //根据配置文件目录加载
            reader.loadBeanDefinitions(configLocation);
        }
    }
}

//根据配置文件目录加载 类AbstractBeanDefinitionReader
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
    return loadBeanDefinitions(location, null);
}

//这里才是最终实现 类AbstractBeanDefinitionReader
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
    //前面设置的RescourceLoader() 就是XmlWebApplicationContext对象 上面的结构图中最终实现了ResourcePatternResolver类
    ResourceLoader resourceLoader = getResourceLoader();
    if (resourceLoader == null) {
        throw new BeanDefinitionStoreException(
                "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
    }

    if (resourceLoader instanceof ResourcePatternResolver) {
        // Resource pattern matching available.
        try {
            //加载资源
            Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
            //注册bean 这里对xml进行校验 解析 注册bean
            int loadCount = loadBeanDefinitions(resources);
            if (actualResources != null) {
                for (Resource resource : resources) {
                    actualResources.add(resource);
                }
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
            }
            return loadCount;
        }
        catch (IOException ex) {
            throw new BeanDefinitionStoreException(
                    "Could not resolve bean definition resource pattern [" + location + "]", ex);
        }
    }
    else {
        // Can only load single resources by absolute URL.
        Resource resource = resourceLoader.getResource(location);
        int loadCount = loadBeanDefinitions(resource);
        if (actualResources != null) {
            actualResources.add(resource);
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
        }
        return loadCount;
    }

加载xml资源 对xml 校验解析 返回Document

//类AbstractBeanDefinitionReader
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
    Assert.notNull(resources, "Resource array must not be null");
    int counter = 0;
    for (Resource resource : resources) {
        counter += loadBeanDefinitions(resource);
    }
    return counter;
}
/*
* 类XmlBeanDefinitionReader 这里对资源进行了编码 转换为EncodeResource 
* Resource接口和EncodeResource类 都实现了InputStreamSource接口
*/
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    return loadBeanDefinitions(new EncodedResource(resource));
}
/*
* 类XmlBeanDefinitionReader  
*/
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
        Assert.notNull(encodedResource, "EncodedResource must not be null");
        if (logger.isInfoEnabled()) {
            logger.info("Loading XML bean definitions from " + encodedResource.getResource());
        }

        Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
        //初始化一个Set集合,设置到当前对象中
        if (currentResources == null) {
            currentResources = new HashSet<EncodedResource>(4);
            this.resourcesCurrentlyBeingLoaded.set(currentResources);
        }
        //将encodedResource放到上面初始化的集合中
        if (!currentResources.add(encodedResource)) {
            throw new BeanDefinitionStoreException(
                    "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
        }
        try {
            InputStream inputStream = encodedResource.getResource().getInputStream();
            try {
                InputSource inputSource = new InputSource(inputStream);
                if (encodedResource.getEncoding() != null) {
                    inputSource.setEncoding(encodedResource.getEncoding());
                }
                //这里对xml转化的流读取解析
                return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
            }
            finally {
                inputStream.close();
            }
        }
        catch (IOException ex) {
            throw new BeanDefinitionStoreException(
                    "IOException parsing XML document from " + encodedResource.getResource(), ex);
        }
        finally {
            currentResources.remove(encodedResource);
            if (currentResources.isEmpty()) {
                this.resourcesCurrentlyBeingLoaded.remove();
            }
        }
    }
/*
* 类XmlBeanDefinitionReader 这里只有两个方法,下面都是处理的异常
*/
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
            throws BeanDefinitionStoreException {
    try {
        Document doc = doLoadDocument(inputSource, resource);
        return registerBeanDefinitions(doc, resource);
    }
    catch (BeanDefinitionStoreException ex) {
        throw ex;
    }
    catch (SAXParseException ex) {
        throw new XmlBeanDefinitionStoreException(resource.getDescription(),
                "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
    }
    catch (SAXException ex) {
        throw new XmlBeanDefinitionStoreException(resource.getDescription(),
                "XML document from " + resource + " is invalid", ex);
    }
    catch (ParserConfigurationException ex) {
        throw new BeanDefinitionStoreException(resource.getDescription(),
                "Parser configuration exception parsing XML from " + resource, ex);
    }
    catch (IOException ex) {
        throw new BeanDefinitionStoreException(resource.getDescription(),
                "IOException parsing XML document from " + resource, ex);
    }
    catch (Throwable ex) {
        throw new BeanDefinitionStoreException(resource.getDescription(),
                "Unexpected exception parsing XML document from " + resource, ex);
    }
}
/*
* 类XmlBeanDefinitionReader 这里是把xml解析成Document
* 这个方法传的参数很多。包括上面传过来的inputSource 当前对象的资源处理器,错误处理器,xml验证模式,
* 还有一个默认为false的boolean,暂且不管他是干什么的
*/
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
    return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
            getValidationModeForResource(resource), isNamespaceAware());
}
/*
* 类XmlBeanDefinitionReader
* 获取验证模式
* VALIDATION_AUTO = 1 
*/
protected int getValidationModeForResource(Resource resource) {
    //这里获取的是validationMode这个属性 private int validationMode = VALIDATION_AUTO;默认为1
    int validationModeToUse = getValidationMode();
    if (validationModeToUse != VALIDATION_AUTO) {
        return validationModeToUse;
    }
    int detectedMode = detectValidationMode(resource);//这里根据配置文件获取验证模式
    if (detectedMode != VALIDATION_AUTO) {
        return detectedMode;
    }
    // Hmm, we didn't get a clear indication... Let's assume XSD,
    // since apparently no DTD declaration has been found up until
    // detection stopped (before finding the document's root tag).
    return VALIDATION_XSD;
}

/*
* 类XmlBeanDefinitionReader
* 根据配置文件获取验证模式
*/
protected int detectValidationMode(Resource resource) {
    if (resource.isOpen()) {
        throw new BeanDefinitionStoreException(
                "Passed-in Resource [" + resource + "] contains an open stream: " +
                "cannot determine validation mode automatically. Either pass in a Resource " +
                "that is able to create fresh streams, or explicitly specify the validationMode " +
                "on your XmlBeanDefinitionReader instance.");
    }

    InputStream inputStream;
    try {
        inputStream = resource.getInputStream();
    }
    catch (IOException ex) {
        throw new BeanDefinitionStoreException(
                "Unable to determine validation mode for [" + resource + "]: cannot open InputStream. " +
                "Did you attempt to load directly from a SAX InputSource without specifying the " +
                "validationMode on your XmlBeanDefinitionReader instance?", ex);
    }

    try {
        //根据xml内容 如果第一行有“DOCTYPE”则DTD 否则XSD
        return this.validationModeDetector.detectValidationMode(inputStream);
    }
    catch (IOException ex) {
        throw new BeanDefinitionStoreException("Unable to determine validation mode for [" +
                resource + "]: an error occurred whilst reading from the InputStream.", ex);
    }
}
/*
* 类DefaultDocumentLoader 这里就是解析xml了 最终返回一个Document
*/
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
            ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {

    DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
    if (logger.isDebugEnabled()) {
        logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
    }
    DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
    return builder.parse(inputSource);
}

下面是注册Bean加载到容器中 重点 重点 重点

/*
* 类XmlBeanDefinitionReader
*/
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    //创建一个DefaultBeanDefinitionDocumentReader对象 实现了BeanDefinitionDocumentReader 接口
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    //getRegistry()这个方法是获取当前对象的beanFactory 
    // getBeanDefinitionCount() 获取beanFactory中beanDefinitionMap()(ConcurrentHashMap) 的size,初始化之前为0
    //这里是获取之前注册的bean
    int countBefore = getRegistry().getBeanDefinitionCount();
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    //返回这次注册的对象的数量
    return getRegistry().getBeanDefinitionCount() - countBefore;
}
/*
* 类DefaultBeanDefinitionDocumentReader
* 注册bean
*/
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    this.readerContext = readerContext;
    logger.debug("Loading bean definitions");
    //获取根节点
    Element root = doc.getDocumentElement();
    //注册bean
    doRegisterBeanDefinitions(root);
}
/*
*类DefaultBeanDefinitionDocumentReader
* 到这里是不是觉得读到根节点了 终于要开始了? 呵呵 你小看他了,还有延伸
*/
protected void doRegisterBeanDefinitions(Element root) {
    BeanDefinitionParserDelegate parent = this.delegate; //上面方法刚实例化出来,这个属性还是null
    //这里创建一个对象,你可以理解为这个类是真正解析Element的工作类(确实是这样的)
    //创建这个对象的方法后面再看,这里先往下面走
    this.delegate = createDelegate(getReaderContext(), root, parent);
    //刚才创建对象的时候 把root传进去了,这里获取到的值是true
    if (this.delegate.isDefaultNamespace(root)) {
        //PROFILE_ATTRIBUTE = "profile" root节点里没有这个属性 返回false
        String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
        if (StringUtils.hasText(profileSpec)) {
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                    profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                if (logger.isInfoEnabled()) {
                    logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                            "] not matching: " + getReaderContext().getResource());
                }
                return;
            }
        }
    }
    //准备解析xml方法,这个方法是空的 留给用户自己扩展
    preProcessXml(root);
    //解析xml (这里才是重点!!)
    parseBeanDefinitions(root, this.delegate);
    //解析完成,下一步流程 也是空的,留给用户自己扩展
    postProcessXml(root);
    //设置当前对象内的解析对象属性为当前对象的parent 默认为空
    this.delegate = parent;
}

然后我们看这个方法createDelegate(getReaderContext(), root, parent)

/*
* 类DefaultBeanDefinitionDocumentReader 创建解析类
*/
protected BeanDefinitionParserDelegate createDelegate(
    XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) {

    BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
    delegate.initDefaults(root, parentDelegate);
    return delegate;
}

/*
* BeanDefinitionParserDelegate 初始默认值
*
public void initDefaults(Element root, BeanDefinitionParserDelegate parent) {
    populateDefaults(this.defaults, (parent != null ? parent.defaults : null), root);
    this.readerContext.fireDefaultsRegistered(this.defaults);
}

/*
* BeanDefinitionParserDelegate 设置一些默认值,这里我们都没有配置,基本都是默认的,后面解析的时候会用到
*/
protected void populateDefaults(DocumentDefaultsDefinition defaults, DocumentDefaultsDefinition parentDefaults, Element root) {
    //从参数根节点即<beans>节点中获取default-lazy-init参数  
    String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE);
    ////如果lazyInit的值为default,如果parentDefaults不为null则侧其中获取lazyInit,否则设置为false  
    if (DEFAULT_VALUE.equals(lazyInit)) {
        // Potentially inherited from outer <beans> sections, otherwise falling back to false.
        lazyInit = (parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE);
    }
    defaults.setLazyInit(lazyInit);

    String merge = root.getAttribute(DEFAULT_MERGE_ATTRIBUTE);
    if (DEFAULT_VALUE.equals(merge)) {
        // Potentially inherited from outer <beans> sections, otherwise falling back to false.
        merge = (parentDefaults != null ? parentDefaults.getMerge() : FALSE_VALUE);
    }
    defaults.setMerge(merge);

    String autowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE);
    if (DEFAULT_VALUE.equals(autowire)) {
        // Potentially inherited from outer <beans> sections, otherwise falling back to 'no'.
        autowire = (parentDefaults != null ? parentDefaults.getAutowire() : AUTOWIRE_NO_VALUE);
    }
    defaults.setAutowire(autowire);

    // Don't fall back to parentDefaults for dependency-check as it's no longer supported in
    // <beans> as of 3.0. Therefore, no nested <beans> would ever need to fall back to it.
    defaults.setDependencyCheck(root.getAttribute(DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE));

    if (root.hasAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)) {
        defaults.setAutowireCandidates(root.getAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE));
    }
    else if (parentDefaults != null) {
        defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates());
    }

    if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) {
        defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE));
    }
    else if (parentDefaults != null) {
        defaults.setInitMethod(parentDefaults.getInitMethod());
    }

    if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) {
        defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE));
    }
    else if (parentDefaults != null) {
        defaults.setDestroyMethod(parentDefaults.getDestroyMethod());
    }

    defaults.setSource(this.readerContext.extractSource(root));
}

解析的方法parseBeanDefinitions(root, this.delegate);

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        if (delegate.isDefaultNamespace(root)) {//这里是true 按根节点来解析
            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;
                    if (delegate.isDefaultNamespace(ele)) {//节点是否是默认命名空间
                        parseDefaultElement(ele, delegate);//具体解析 默认命名空间 标签<bean>
                    }
                    else {
                        delegate.parseCustomElement(ele);//具体解析 自定义标签 <context:...
                    }
                }
            }
        }
        else {
            delegate.parseCustomElement(root);
        }
    }

具体解析,后面再写。

相关标签: Spring IOC