美文网首页
Spring4 IOC容器初始化源码

Spring4 IOC容器初始化源码

作者: sunpy | 来源:发表于2018-10-29 16:01 被阅读31次

题外话

最近打算读读spring的源码,打算深入学习下spring的IOC,AOP的思想,先找个spring的bean加载研究下。本文使用的spring源码是4.0.0的版本。

入门程序

public static void main(String[] args) {
    ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
    User user = ac.getBean("user", User.class);
    System.out.println(user.getUsername());
}

说明:第一行获取classpath下的配置文件spring.xml,然后加载所有的类;第二行获取指定的user的Bean。

源码分析

1. 设置资源的加载setConfigLocations

ClassPathXmlApplicationContext类图


ClassPathXmlApplicationContext类图.jpg

ClassPathXmlApplicationContext属性表


ClasspathXmlApplicationContext属性表.png
ClassPathXmlApplicationContext构造方法
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
    this(new String[] {configLocation}, true, null);
}

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
        throws BeansException {
    // 设置ApplicationContext为null
    super(parent);
    // 将配置文件的路径存放到字符串数组中
    setConfigLocations(configLocations);
    if (refresh) {
        // 核心方法:刷新spring的上下文
        refresh();
    }
}

public void setConfigLocations(String... locations) {
    // 如果locations数组不为null
    if (locations != null) {
        // 判断数组路径不为null
        Assert.noNullElements(locations, "Config locations must not be null");
        // configLocations开辟空间
        this.configLocations = new String[locations.length];
        // 遍历,然后为configLocations数组赋值
        for (int i = 0; i < locations.length; i++) {
            this.configLocations[i] = resolvePath(locations[i]).trim();
        }
    }
    else {
        this.configLocations = null;
    }
}

流程说明:
① super(parent);方法
设置父级上下文ApplicationContext,设置值为null。
② setConfigLocations(configLocations);
将配置文件的路径存放到字符串数组中,初始化configLocations 数组;解析给定的路径,使用properties中的属性替换占位符位置的属性值;而且我们也可以传入多个xml配置文件,使用逗号分隔。
③ refresh();
这个方法是spring加载bean的核心方法,作用就是刷新spring的上下文。


2. AbstractApplicationContext类之refresh方法刷新整个spring上下文

2.1 refresh()方法:刷新整个spring的上下文,完成整个spring上下文的加载

public void refresh() throws BeansException, IllegalStateException {  
       synchronized (this.startupShutdownMonitor) {  
           //调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识  
           prepareRefresh();  
           //告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从  
          //子类的refreshBeanFactory()方法启动  
           ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();  
           //为BeanFactory配置容器特性,例如类加载器、事件处理器等  
           prepareBeanFactory(beanFactory);  
           try {  
               //为容器的某些子类指定特殊的BeanPost事件处理器  
               postProcessBeanFactory(beanFactory);  
               //调用所有注册的BeanFactoryPostProcessor的Bean  
               invokeBeanFactoryPostProcessors(beanFactory);  
               //为BeanFactory注册BeanPost事件处理器.  
               //BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件  
               registerBeanPostProcessors(beanFactory);  
               //初始化信息源,和国际化相关.  
               initMessageSource();  
               //初始化容器事件传播器.  
               initApplicationEventMulticaster();  
               //调用子类的某些特殊Bean初始化方法  
               onRefresh();  
               //为事件传播器注册事件监听器.  
               registerListeners();  
               //初始化所有剩余的单态Bean.  
               finishBeanFactoryInitialization(beanFactory);  
               //初始化容器的生命周期事件处理器,并发布容器的生命周期事件  
               finishRefresh();  
           }  
           catch (BeansException ex) {  
               //销毁以创建的单态Bean  
               destroyBeans();  
               //取消refresh操作,重置容器的同步标识.  
               cancelRefresh(ex);  
               throw ex;  
           }  
       }  
   }

2.2 prepareRefresh()方法:准备为spring的上下文刷新

protected void prepareRefresh() {
    // 初始化spring上下文开始时间
    this.startupDate = System.currentTimeMillis();
    // spring上下文关闭的标志
    this.closed.set(false);
    // spring上下文有效的标志
    this.active.set(true);
    
    if (logger.isInfoEnabled()) {
        logger.info("Refreshing " + this);
    }

    // 初始化占位符资源
    initPropertySources();

    // 验证properties中的属性
    getEnvironment().validateRequiredProperties();

    // 初始化最早应用事件
    this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}

2.3 obtainFreshBeanFactory()方法:告诉子类刷新内部bean工厂
Bean资源文件从这步才开始真正的载入,通过refreshBeanFactory方法实现的。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    // 刷新Bean工厂
    refreshBeanFactory();
    // 获取bean工厂
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (logger.isDebugEnabled()) {
        logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
    }
    // 返回bean工厂
    return beanFactory;
}

3. AbstractRefreshableApplicationContext类之refreshBeanFactory方法实现刷新bean工厂

@Override
protected final void refreshBeanFactory() throws BeansException {
    // 如果beanFactory不为null
    if (hasBeanFactory()) {
        // 1. 获取beanFactory;如果为null,就抛出IllegalStateException.
        // 2. 销毁bean
        destroyBeans();
        // 关闭beanFactory,将序列号设置为null,将beanFactory设置为null
        closeBeanFactory();
    }
    
    try {
        // 创建父级别的DefaultListableBeanFactory(真正的IOC容器)
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        // 将beanFactory设置序列化id
        beanFactory.setSerializationId(getId());
        // 自定义上下文使用的工厂beanFactory(主要是定制化自动装配等配置)
        customizeBeanFactory(beanFactory);
        // 使用XmlBeanDefinitionReader加载bean
        loadBeanDefinitions(beanFactory);
        // 初始化beanFactory
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

流程说明:
① 首先判断BeanFactory工厂是否已经创建,如果已经创建那么就销毁关闭BeanFactory工厂。(可以发现spring每次都是建立新的IOC容器)
② 创建DefaultListableBeanFactory真正的ioc容器。
③ 调用loadBeanDefinitions方法加载Bean,实际使用XmlBeanDefinitionReader类操作的。


4. AbstractXmlApplicationContext类之loadBeanDefinitions方法读取Bean定义的资源

// 使用XmlBeanDefinitionReader加载Bean
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // 通过BeanFactory来创建一个新的XmlBeanDefinitionReader
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    // 设置资源加载的环境
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    // 设置资源加载器,而容器本身就是一个资源加载器
    beanDefinitionReader.setResourceLoader(this);
    // 设置schema、dtd解析器
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    // 当Bean读取器读取Bean定义的Xml资源文件时,启用Xml的校验机制  
    initBeanDefinitionReader(beanDefinitionReader);
    // Bean加载器真正加载Bean的方法
    loadBeanDefinitions(beanDefinitionReader);
}

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    // 获取配置文件的路径存放到字符串数组
    Resource[] configResources = getConfigResources();
    // 如果该资源对象数组不为null
    if (configResources != null) {
        // 使用AbstractBeanDefinitionReader读取定位的Bean定义资源
        reader.loadBeanDefinitions(configResources);
    }
    // 获取ClassPathXmlApplicationContext类中setConfigLocations方法设置的资源路径的数组
    String[] configLocations = getConfigLocations();
    // 如果资源路径数组不为null
    if (configLocations != null) {
        // 使用AbstractBeanDefinitionReader读取定位的Bean定义资源
        reader.loadBeanDefinitions(configLocations);
    }
} 

@Override
protected Resource[] getConfigResources() {
    return this.configResources;
}

5. AbstractBeanDefinitionReader类之loadBeanDefinitions方法读取Bean定义的资源

XmlBeanDefinitionReader.png
// 通过资源路径数组来加载Bean
@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
    Assert.notNull(locations, "Location array must not be null");
    // 计数值(加载次数)
    int counter = 0;
    // 遍历资源路径数组
    for (String location : locations) {
        counter += loadBeanDefinitions(location);
    }
    return counter;
}

// 通过单个资源路径来加载Bean
@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
    return loadBeanDefinitions(location, null);
}

// 从指定的资源位置加载bean
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
    // 获取资源加载器(根据给定的资源文件地址返回对应的Resource)
    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 {
            // 将资源文件路径解析为Spring容器支持的资源对象Resource数组
            Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
            // 最终还是委派给XmlBeanDefinitionReader来加载资源Resource
            // 返回加载次数
            int loadCount = loadBeanDefinitions(resources);
            // 如果实际资源不为空,将资源添加进去
            // 而传入的集合为null
            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 {
        // 通过URL方式加载资源
        Resource resource = resourceLoader.getResource(location);
        int loadCount = loadBeanDefinitions(resource);
        if (actualResources != null) {
            actualResources.add(resource);
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Loaded " + loadCount + " bean defintions from location [" + location + "]");
        }
        return loadCount;
    }
}

6. XmlBeanDefinitionReader类之loadBeanDefinitions方法读取Bean定义的资源

// 通过资源对象Resource数组加载Bean
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
    Assert.notNull(resources, "Resource array must not be null");
    // 计数值
    int counter = 0;
    // 遍历资源对象Resource数组
    for (Resource resource : resources) {
        counter += loadBeanDefinitions(resource);
    }
    return counter;
}

@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    // 将资源Resource包装成特殊编码的EncodedResource
    return loadBeanDefinitions(new EncodedResource(resource));
}

// XmlBeanDefinitionReader读取Bean定义的资源
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();
    if (currentResources == null) {
        currentResources = new HashSet<EncodedResource>(4);
        this.resourcesCurrentlyBeingLoaded.set(currentResources);
    }
    if (!currentResources.add(encodedResource)) {
        throw new BeanDefinitionStoreException(
                "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    }
    try {
        // 将资源文件解析为字节输入流
        InputStream inputStream = encodedResource.getResource().getInputStream();
        try {
            // 定义输入源,设置了资源文件xml的字节输入流
            InputSource inputSource = new InputSource(inputStream);
            // 如果编码不为空,那么在定义的输入源中设置编码
            if (encodedResource.getEncoding() != null) {
                inputSource.setEncoding(encodedResource.getEncoding());
            }
            // 真正读取过程
            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();
        }
    }
}

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
        throws BeanDefinitionStoreException {
    try {
        // 使用配置的文档来加载程序和加载指定文档
        // 将Resource资源(XML文件)转换为Document独享,而解析加载过程使用了documentLoader实现
        Document doc = doLoadDocument(inputSource, resource);
        // 对Bean定义解析
        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);
    }
}

// 使用配置的文档来加载程序和加载指定文档
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
    return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
            getValidationModeForResource(resource), isNamespaceAware());
}

7. DocumentLoader将Bean定义的资源转换为Document对象

// 使用JAXP来解析XML文档为Document对象
@Override
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);
    // 解析Bean定义的资源
    return builder.parse(inputSource);
}

// 创建DocumentBuilderFactory工厂实例
protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware)
        throws ParserConfigurationException {
    // 创建文档解析工厂
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(namespaceAware);
    // 设置文档校验模型,validationMode不为0
    if (validationMode != XmlValidationModeDetector.VALIDATION_NONE) {
        // 设置校验为true
        factory.setValidating(true);
        // 如果文档校验模型为XSD校验
        if (validationMode == XmlValidationModeDetector.VALIDATION_XSD) {
            // Enforce namespace aware for XSD...
            factory.setNamespaceAware(true);
            try {
                // SCHEMA_LANGUAGE_ATTRIBUTE 使用JAXP属性配置验证的语言
                // XSD_SCHEMA_LANGUAGE XSD模式语言的JAXP属性值
                factory.setAttribute(SCHEMA_LANGUAGE_ATTRIBUTE, XSD_SCHEMA_LANGUAGE);
            }
            catch (IllegalArgumentException ex) {
                ParserConfigurationException pcex = new ParserConfigurationException(
                        "Unable to validate using XSD: Your JAXP provider [" + factory +
                        "] does not support XML Schema. Are you running on Java 1.4 with Apache Crimson? " +
                        "Upgrade to Apache Xerces (or Java 1.5) for full XSD support.");
                pcex.initCause(ex);
                throw pcex;
            }
        }
    }

    return factory;
}

// 使用JAXP创建一个文档解析器DocumentBuilder,用于解析XML文档
protected DocumentBuilder createDocumentBuilder(
        DocumentBuilderFactory factory, EntityResolver entityResolver, ErrorHandler errorHandler)
        throws ParserConfigurationException {
    // 通过工厂创建文档解析器
    DocumentBuilder docBuilder = factory.newDocumentBuilder();
    if (entityResolver != null) {
        docBuilder.setEntityResolver(entityResolver);
    }
    if (errorHandler != null) {
        docBuilder.setErrorHandler(errorHandler);
    }
    return docBuilder;
}

8. XmlBeanDefinitionReader类之registerBeanDefinitions方法解析Document中的Bean定义

// 解析DOM文档Document中包含的Bean定义
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    // 创建BeanDefinitionDocumentReader用来解析Document
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    // 获取容器中注册的Bean的数量
    int countBefore = getRegistry().getBeanDefinitionCount();
    // 此处委派给了DefaultBeanDefinitionDocumentReader来实现Bean定义的解析
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    // 返回解析的Bean数量
    return getRegistry().getBeanDefinitionCount() - countBefore;
}

// 创建一个BeanDefinitionDocumentReader用来解析Document
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
    // 使用构造器通过反射来创建对象,强制类型转换为BeanDefinitionDocumentReader类型
    return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
}

9. DefaultBeanDefinitionDocumentReader类之registerBeanDefinitions方法解析Document中的Bean定义

// 根据spring-beans的XSD文件来解析bean的定义
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    // 初始化XML描述符
    this.readerContext = readerContext;
    logger.debug("Loading bean definitions");
    // 获取document的根元素
    Element root = doc.getDocumentElement();
    // 在给定的根元素root的内部注册每个Bean的定义
    doRegisterBeanDefinitions(root);
}


// 在给定的根元素的内部注册每个Bean的定义
protected void doRegisterBeanDefinitions(Element root) {
    // Any nested <beans> elements will cause recursion in this method. In
    // order to propagate and preserve <beans> default-* attributes correctly,
    // keep track of the current (parent) delegate, which may be null. Create
    // the new (child) delegate with a reference to the parent for fallback purposes,
    // then ultimately reset this.delegate back to its original (parent) reference.
    // this behavior emulates a stack of delegates without actually necessitating one.
    
    // 使用BeanDefinitionParserDelegate用于完成真正的解析过程
    BeanDefinitionParserDelegate parent = this.delegate;
    // 对BeanDefinitionParserDelegate进行初始化
    this.delegate = createDelegate(getReaderContext(), root, parent);

    if (this.delegate.isDefaultNamespace(root)) {
        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;
            }
        }
    }

    // 在解析Bean定义之前,扩展解析自定义配置
    preProcessXml(root);
    // 从Document的根元素root开始进行Bean定义的Document对象
    parseBeanDefinitions(root, this.delegate);
    // 在解析Bean定义之后,扩展解析自定义配置
    postProcessXml(root);
    
    this.delegate = parent;
}

// 对BeanDefinitionParserDelegate进行初始化
protected BeanDefinitionParserDelegate createDelegate(
        XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) {
    // 创建BeanDefinitionParserDelegate
    BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
    // 初始化Document的根元素
    // 通过给定的根元素初始化DocumentDefaultsDefinition类
    delegate.initDefaults(root, parentDelegate);
    return delegate;
}

// 解析文档中的根级别元素(import标签,alias标签,bean标签,beans元素)
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    // Bean定义的document对象使用spring的默认xml命名空间
    if (delegate.isDefaultNamespace(root)) {
        // 获取bean根元素下的所有子节点
        NodeList nl = root.getChildNodes();
        // 遍历所有子节点
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            // 判断节点是否为Element元素节点
            if (node instanceof Element) {
                // 将节点node强制类型转为Element元素
                Element ele = (Element) node;
                // 使用Spring的Bean规则解析元素节点
                if (delegate.isDefaultNamespace(ele)) {
                    parseDefaultElement(ele, delegate);
                }
                else {// 使用用户自定义的命名空间解析
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    else {
        // 根节点没有使用spring的默认命名空间,就使用用户自定义的命名空间解析
        delegate.parseCustomElement(root);
    }
}

10. DefaultBeanDefinitionDocumentReader类之解析<import>,<alias>,<bean>,<beans>元素

// 解析Document元素Element节点  
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    // 如果元素节点是<import>节点
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
        // 解析Document元素中的<import>节点
        importBeanDefinitionResource(ele);
    }
    // 如果元素节点是<alias>节点
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
        // 解析Document元素中的<alias>节点
        processAliasRegistration(ele);
    }
    // 如果元素节点是<bean>节点
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
        // 解析Document元素中的<bean>节点
        processBeanDefinition(ele, delegate);
    }
    // 如果元素节点是<beans>节点
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { 
        // 解析Document元素中的<beans>节点
        doRegisterBeanDefinitions(ele);
    }
}

11. DefaultBeanDefinitionDocumentReader类之真正解析<import>元素

// 解析<import>节点元素并且将bean定义从给定资源中加载到bean工厂
protected void importBeanDefinitionResource(Element ele) {
    // 获取导入资源的location属性
    String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
    // 如果location属性值为空,那么直接返回
    if (!StringUtils.hasText(location)) {
        getReaderContext().error("Resource location must not be empty", ele);
        return;
    }

    // 使用系统变量值来解析location属性值
    location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
    Set<Resource> actualResources = new LinkedHashSet<Resource>(4);

    // 判断location属性值的定位是否为绝对路径
    boolean absoluteLocation = false;
    try {
        absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
    }
    catch (URISyntaxException ex) {
        // cannot convert to an URI, considering the location relative
        // unless it is the well-known Spring prefix "classpath*:"
    }

    // 如果location定位为绝对路径
    if (absoluteLocation) {
        try {
            // 通过指定路径加载bean定义的资源,返回<import>节点的加载次数
            int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
            if (logger.isDebugEnabled()) {
                logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
            }
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error(
                    "Failed to import bean definitions from URL location [" + location + "]", ele, ex);
        }
    }
    else {// 否则location定位按照相对路径处理
        
        try {
            int importCount;
            // 通过指定路径获取相对路径下的资源Resource
            Resource relativeResource = getReaderContext().getResource().createRelative(location);
            // 判断相对路径对应的资源是否存在
            if (relativeResource.exists()) {
                // 使用XmlBeanDefinitionReader读取相对路径下的资源
                importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
                actualResources.add(relativeResource);
            }
            else {
                String baseLocation = getReaderContext().getResource().getURL().toString();
                importCount = getReaderContext().getReader().loadBeanDefinitions(
                        StringUtils.applyRelativePath(baseLocation, location), actualResources);
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
            }
        }
        catch (IOException ex) {
            getReaderContext().error("Failed to resolve current resource location", ele, ex);
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",
                    ele, ex);
        }
    }
    Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);
    // 在解析完<Import>元素之后,发送容器导入其他资源处理完成事件
    getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}

12. DefaultBeanDefinitionDocumentReader类之真正解析<bean>元素


// 解析Document元素中的<bean>节点 
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    // BeanDefinitionHolder类对BeanDefinition的封装
    // 使用BeanDefinitionParserDelegate解析文档Document中的<bean>元素
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            // IOC容器注册BeanDefinition
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" +
                    bdHolder.getBeanName() + "'", ele, ex);
        }
        //在完成向Spring IoC容器注册解析得到的Bean定义之后,发送注册事件  
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}

// 解析提供的Bean元素
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
    return parseBeanDefinitionElement(ele, null);
}

// 解析提供的Bean元素
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
    // 获取bean元素中的id属性
    // public static final String ID_ATTRIBUTE = "id";
    String id = ele.getAttribute(ID_ATTRIBUTE);
    // 获取bean元素中的name属性
    // public static final String NAME_ATTRIBUTE = "name";
    String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

    List<String> aliases = new ArrayList<String>();
    // 将bean元素中name属性值存放到别名中
    if (StringUtils.hasLength(nameAttr)) {
        String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
        aliases.addAll(Arrays.asList(nameArr));
    }
    
    // 如果bean设置了id,那么将id作为beanName
    // 如果别名集合不为空,那么将别名集合的第一个元素作为beanName
    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) {
        // 检查Bean元素配置的id、name或者别名是否重复
        checkNameUniqueness(beanName, aliases, ele);
    }

    // 解析bean定义本身,而不考虑名称或别名。
    AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
    if (beanDefinition != null) {
        if (!StringUtils.hasText(beanName)) {
            try {
                if (containingBean != null) {
                    // 如果bean元素没有配置id、别名或者name并且没有包含子Bean元素
                    // 那么就解析Bean生成唯一beanName并注册 
                    beanName = BeanDefinitionReaderUtils.generateBeanName(
                            beanDefinition, this.readerContext.getRegistry(), true);
                }
                else {
                    // 如果bean元素没有配置id、别名或者name并且包含子Bean元素
                    // 那么就解析Bean使用别名注册
                    beanName = this.readerContext.generateBeanName(beanDefinition);
                    // 为了保持对于Spring 1.2/2.0向后兼容性
                    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);
        return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
    }

    return null;
}

// 解析bean定义本身,而不考虑id、名称、别名(上面已经处理过了)
public AbstractBeanDefinition parseBeanDefinitionElement(
        Element ele, String beanName, BeanDefinition containingBean) {
    // 专门记录解析的Bean元素
    this.parseState.push(new BeanEntry(beanName));

    String className = null;
    
    // 获取bean元素中的class属性
    // public static final String CLASS_ATTRIBUTE = "class";
    if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
        className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    }

    
    try {
        String parent = null;
        // 获取bean元素中的parent属性
        // public static final String PARENT_ATTRIBUTE = "parent";
        if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
            parent = ele.getAttribute(PARENT_ATTRIBUTE);
        }
        
        // 为Bean元素配置的class名称和parent属性值创建BeanDefinition
        AbstractBeanDefinition bd = createBeanDefinition(className, parent);
        // 对当前的Bean元素中配置的一些属性进行解析和设置,如配置的单态(singleton)属性等  
        parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
        // 为Bean元素解析的Bean设置description信息
        bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
        // 对Bean元素的meta(元信息)属性解析  
        parseMetaElements(ele, bd);
        parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
        parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
        // 解析Bean元素的构造方法设置 
        parseConstructorArgElements(ele, bd);
        // 解析Bean元素的property属性
        parsePropertyElements(ele, bd);
        // 解析Bean元素的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;
}

13. BeanDefinitionParserDelegate类之真正解析<property>元素

// 解析Property元素及其子元素
public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
    // 获取bean元素中的子元素
    NodeList nl = beanEle.getChildNodes();
    // 遍历子元素节点
    for (int i = 0; i < nl.getLength(); i++) {
        Node node = nl.item(i);
        // 判断子元素是否<property>子元素
        if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
            // 调用解析<property>子元素方法解析
            parsePropertyElement((Element) node, bd);
        }
    }
}

// 解析Property元素
public void parsePropertyElement(Element ele, BeanDefinition bd) {
    // 获取property元素中的name属性
    // public static final String NAME_ATTRIBUTE = "name";
    String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
    // 校验属性值不为null
    if (!StringUtils.hasLength(propertyName)) {
        error("Tag 'property' must have a 'name' attribute", ele);
        return;
    }
    this.parseState.push(new PropertyEntry(propertyName));
    try {
        // 判断Bean定义中是否存在这个property元素
        if (bd.getPropertyValues().contains(propertyName)) {
            error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
            return;
        }
        // 获取property元素的值
        // 同时也解析property子元素
        Object val = parsePropertyValue(ele, bd, propertyName);
        PropertyValue pv = new PropertyValue(propertyName, val);
        // 解析property元素中的属性
        parseMetaElements(ele, pv);
        pv.setSource(extractSource(ele));
        bd.getPropertyValues().addPropertyValue(pv);
    }
    finally {
        this.parseState.pop();
    }
}

14. BeanDefinitionReaderUtils类之registerBeanDefinition将BeanDefinition在IOC容器中注册

// 将Bean定义注册到Bean工厂
// BeanDefinitionHolder包括了BeanDefinition和bean的别名
public static void registerBeanDefinition(
        BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
        throws BeanDefinitionStoreException {

    // Register bean definition under primary name.
    // 获取Bean定义的名称
    String beanName = definitionHolder.getBeanName();
    // 使用Bean名称和BeanDefinition向IOC容器注册
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

    // Register aliases for bean name, if any.
    // 如果BeanDefinition有别名,那么向ioc容器注册别名
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}

15. DefaultListableBeanFactory类之registerBeanDefinition真正注册BeanDefinition

DefaultListableBeanFactory的UML图.png
// 使用Bean名称和BeanDefinition向IOC容器注册
@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");
    
    // 校验BeanDefinition;校验方法的注解、方法名称等
    if (beanDefinition instanceof AbstractBeanDefinition) {
        try {
            ((AbstractBeanDefinition) beanDefinition).validate();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                    "Validation of bean definition failed", ex);
        }
    }

    BeanDefinition oldBeanDefinition;
    // 通过beanName获取对应的旧的BeanDefinition
    oldBeanDefinition = this.beanDefinitionMap.get(beanName);
    // 检查是否有同名的BeanDefinition已经在IoC容器中注册
    if (oldBeanDefinition != null) {
        // 如果不允许BeanDefinition重写,那么抛出BeanDefinition存储异常
        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)) {
        // 如果新的需要注册的BeanDefinition不等于之前已经注册的BeanDefinition
            if (this.logger.isInfoEnabled()) {
                this.logger.info("Overriding bean definition for bean '" + beanName +
                        "' with a different definition: replacing [" + oldBeanDefinition +
                        "] with [" + beanDefinition + "]");
            }
        }
        else {
        // 进行新的需要注册的BeanDefinition覆盖之前已经注册的BeanDefinition
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Overriding bean definition for bean '" + beanName +
                        "' with an equivalent definition: replacing [" + oldBeanDefinition +
                        "] with [" + beanDefinition + "]");
            }
        }
        // 设置新的需要注册的BeanDefinition
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }
    else { // 之前没有注册过BeanDefinition
        if (hasBeanCreationStarted()) {// 如果已经创建BeanDefinition不为空
            // Cannot modify startup-time collection elements anymore (for stable iteration)
            synchronized (this.beanDefinitionMap) {
                // 设置当前需要注册BeanDefinition
                this.beanDefinitionMap.put(beanName, beanDefinition);
                // 创建存储更新BeanDefinition的名称的集合
                List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
                // 将之前的BeanDefinition的名称插入到集合中
                updatedDefinitions.addAll(this.beanDefinitionNames);
                // 将当前的BeanDefinition的名称插入到集合中
                updatedDefinitions.add(beanName);
                // 设置最新的BeanDefinition的名称集合
                this.beanDefinitionNames = updatedDefinitions;
                if (this.manualSingletonNames.contains(beanName)) {
                    Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
                    updatedSingletons.remove(beanName);
                    this.manualSingletonNames = updatedSingletons;
                }
            }
        }
        else {// 如果已经创建BeanDefinition为空
            // 设置beanName对应的beanDefinition
            this.beanDefinitionMap.put(beanName, beanDefinition);
            // 将beanName添加到名称集合中
            this.beanDefinitionNames.add(beanName);
            this.manualSingletonNames.remove(beanName);
        }
        this.frozenBeanDefinitionNames = null;
    }

    // 重置所有已经注册过的BeanDefinition的缓存 
    if (oldBeanDefinition != null || containsSingleton(beanName)) 
        resetBeanDefinition(beanName);
    }
}

spring初始化核心流程

1. AbstractApplicationContext类的refresh方法刷新spring上下文,完成spring上下文的加载。
2. AbstractXmlApplicationContext类的loadBeanDefinitions方法开始读取Bean定义的资源。
3. loadBeanDefinitions方法的流程:
4. 使用ResourceLoader通过给定的类路径加载资源,spring将资源文件封装成了Resource类,这样就拿到了Resource。
5. 使用XmlBeanDefinitionReader来解析XML资源Resource文件;譬如解决资源编码等问题。
6. 使用DocumentLoader将资源Resource转换为Document文档对象,这样就拿到了Document。
7. 表面上使用XmlBeanDefinitionReader解析Document对象;实际上是委派给BeanDefinitionParserDelegate类完成解析Document对象。
8. 使用DefaultBeanDefinitionDocumentReader类解析Document对象中的<import>,<alias>,<bean>,<beans>元素Element。
9. 将<bean>元素Element通过BeanDefinitionParserDelegate解析为BeanDefinitionHolder;而BeanDefinitionHolder本身是一个BeanDefinition的封装。
10. 如果需要<property>元素,那么需要BeanDefinitionParserDelegate类来解析,解析为BeanDefinition。
11. 最后在DefaultListableBeanFactory类实现了BeanDefinitionRegistry接口,完成BeanDefinition注册。
12. 注册的过程就是实现了一个公共的ConcurrentHashMap类型的beanDefinitionMap来保存刷新spring上下文的BeanDefinition。


到此只是粗略的完成了ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");中spring IOC容器的初始化。
实际上上面的过程还有很多地方可以深究,标签<list>解析,<property>子标签解析,qualifier属性解析等。spring ioc初始化复杂的地方在于它不停的委派给其他类来实现。至于getBean方法完成依赖注入下篇博客分析。


相关文章

网友评论

      本文标题:Spring4 IOC容器初始化源码

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