zoukankan      html  css  js  c++  java
  • [spring源码] 小白级别的源码解析ioc(二)

    之前一篇,整体描述了一下 Spring的整体概况和 jar包的介绍。 现在开始进入具体的源码解析,从本篇开始,先介绍spring的ioc容器。之前也看过一些介绍spring源码的, 有的是只讲整体的接口,缺少和源码的结合,有的是一直源码跟进的讲解,由于类的调用太深, 导致看着看着就晕了。 所以自己决定动手写一遍,结合两者的优点。

    1,spring ioc容器的整体设计

        该图摘自spring技术内幕。

        图中的两条线路是主要的两条接口设计线路图。

        整体接口系统都是以beanfactory和applicationContext为核心。

        beanfactory是ioc容器最基本的接口。

        applicationContext 是在继承了 beanfactory的基础上,新增了一些高级的ioc特性。

    2,spring ioc容器设计详解

         这里采用相对原始的方式使用spring,方便深入了解springioc容器的初始化。其他的各种不同的实现,针对不懂得资源加载方式,扩展了一些功能,整体思路是相同的。

         

     ClassPathResource resource = new ClassPathResource("beans.xml");
     DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
     XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
     reader.loadBeanDefinitions(resource)

         主要分为了三个过程。 

         1.resource定位

         2.beanDefinition的载入。

         3.向ioc容器注册beanDefinition的过程。这个过程通过调用BeanDefinitionRegistry接口的实现来完成。

         在这里DefaultListableBeanFactory是一个纯粹的ioc容器,需要给他配置特定的读取器才能完成功能。而我们常用的application已经提供了一系列不同的resource,不需要手动指定。例如:

          FileSystemXmlApplicationContext 从文件系统中载入,ClassPathXmlApplicationContext 从class path载入,XmlWebApplicationContext 可以在web容器中载入。

        下面以FileSystemXmlApplicationContext为例详细的介绍。

         先给出整体的uml图。

          

       整个加载的入口不再过多的描述。

     public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
                throws BeansException { 
            super(parent);
            setConfigLocations(configLocations);
           if (refresh) {
               refresh();
            }
    }

    直接找到FileSystemXmlApplicationContext的构造函数即可。refresh()方法就是这个ioc容器加载的入口,该方法的具体实现在AbstractApplicationContext。

       下面我不去按照源码一步步的跟进。而是去按照ioc容器的整体的一个加载流程,做介绍。有一个整体思路,大家在一步步的去跟进代码,也比较清晰。

       

    public void refresh() throws BeansException, IllegalStateException {
            synchronized (this.startupShutdownMonitor) {
                // 刷新上下文
                prepareRefresh();
                //这里是在子类中启动refreshBeanFactort()的地方
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
                // Prepare the bean factory for use in this context.
                prepareBeanFactory(beanFactory);
                try {
                    // 设置beanFactory的后置处理
                    postProcessBeanFactory(beanFactory);
                    //调用beanFactory的后处理器,这些后处理器是在bean定义中向容器注册的
                    invokeBeanFactoryPostProcessors(beanFactory);
                    //注册bean的后处理器,在bean创建过程中调用
                    registerBeanPostProcessors(beanFactory);
                    //对上下文中的消息源进行初始化
                    initMessageSource();
                    //初始化上下文中的事件机制
                    initApplicationEventMulticaster();
                    //初始化其他的特殊bean
                    onRefresh();
                    //检查监听bean并且将这些bean向容器注册
                    registerListeners();
                    //实例化所有的(non-lazy-init)单利
                    finishBeanFactoryInitialization(beanFactory);
                    //发布容器事件,结束refresh过程
                    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();
                }
            }
        }

       Resource定位

         整体的调用链

         

    protected final void refreshBeanFactory() throws BeansException {
    //这里判断是否已经建立了beanFactory,如果存在就销毁并关闭
    if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try {
           //这里就是在上下文中创建defaultListableBeanFactory的地方。 DefaultListableBeanFactory beanFactory
    = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
    public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
    //这里取得resourceLoader,采用的是DefaultResourceLoader 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的地方 Resource[] resources
    = ((ResourcePatternResolver) resourceLoader).getResources(location); 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; } }
    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 {
                    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();
                }
            }
        }

       BeanDefinition的载入和解析

        从abstractRefreshableApplicationContext的refreshBeanFactory方法开始入手,了解整个bean定义信息的载入过程。

        

    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
            // 创建 XmlBeanDefinitionReader 
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
            beanDefinitionReader.setEnvironment(this.getEnvironment());
         //为xmlbeanDefinitionReader 设置resourceloader beanDefinitionReader.setResourceLoader(
    this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); //启动bean定义信息载入过程 initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); }

        下面是loadBeanDefinitions调用的地方,首先得到beanDefinition信息的resource定位,然后调用xmlBeanDefinitionReader来读取.

       

    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
            //以resource的方式获取配置文件的资源位置
            Resource[] configResources = getConfigResources();
            if (configResources != null) {
                reader.loadBeanDefinitions(configResources);
            }
            //以String的形式获取
            String[] configLocations = getConfigLocations();
            if (configLocations != null) {
                reader.loadBeanDefinitions(configLocations);
            }
        }

       

    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 {
                    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();
                }
            }
        }

     具体的读取过程在doLoadBeanDefinitions。

    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
                throws BeanDefinitionStoreException {
            try {
         //完成具体的文档读取 Document doc
    = doLoadDocument(inputSource, resource);
         //按照spring的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); } }

         beanDefinition 的载入分为两部分。首先调用xml的解析器得到document对象。然后documentReader中按照spring的bean的规则进行解析。

        BeanDefinition的注册

        在DefaultListableBeanFactory中,通过一个map来持有载入的beanDefinition的。

    /** Map of bean definition objects, keyed by bean name */
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);

    再DefaultListableBeanFactory中实现了beanDefinitionRegistry的接口,这个接口完成了beanDefinition向容器的注册。就是将解析得到的beandefinition设置到hashmap中。

    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 ex) {
                    throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                            "Validation of bean definition failed", ex);
                }
            }
    
            BeanDefinition oldBeanDefinition;
    
            oldBeanDefinition = this.beanDefinitionMap.get(beanName);
            if (oldBeanDefinition != null) {
                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)) {
                    if (this.logger.isInfoEnabled()) {
                        this.logger.info("Overriding bean definition for bean '" + beanName +
                                "' with a different definition: replacing [" + oldBeanDefinition +
                                "] with [" + beanDefinition + "]");
                    }
                }
                else {
                    if (this.logger.isDebugEnabled()) {
                        this.logger.debug("Overriding bean definition for bean '" + beanName +
                                "' with an equivalent definition: replacing [" + oldBeanDefinition +
                                "] with [" + beanDefinition + "]");
                    }
                }
                this.beanDefinitionMap.put(beanName, beanDefinition);
            }
            else {
                if (hasBeanCreationStarted()) {
                    // Cannot modify startup-time collection elements anymore (for stable iteration)
                    synchronized (this.beanDefinitionMap) {
                        this.beanDefinitionMap.put(beanName, beanDefinition);
                        List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
                        updatedDefinitions.addAll(this.beanDefinitionNames);
                        updatedDefinitions.add(beanName);
                        this.beanDefinitionNames = updatedDefinitions;
                        if (this.manualSingletonNames.contains(beanName)) {
                            Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
                            updatedSingletons.remove(beanName);
                            this.manualSingletonNames = updatedSingletons;
                        }
                    }
                }
                else {
                    // Still in startup registration phase
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    this.beanDefinitionNames.add(beanName);
                    this.manualSingletonNames.remove(beanName);
                }
                this.frozenBeanDefinitionNames = null;
            }
    
            if (oldBeanDefinition != null || containsSingleton(beanName)) {
                resetBeanDefinition(beanName);
            }
        }


  • 相关阅读:
    第8章 字符串
    第7章 方法
    第6章 类和对象
    第5章 数组
    第4章 循环结构、break与continue
    第3章 选择结构
    第2章 变量、数据类型和运算符
    Codeforces Round #426 (Div. 2)
    CCNA学前基础一
    Tinkoff Challenge
  • 原文地址:https://www.cnblogs.com/qunan/p/6868179.html
Copyright © 2011-2022 走看看