Spring技术内幕笔记(1)——IOC容器初始化过程

IOC容器的初始化是由refresh()方法来启动的,这个方法标志着IOC容器的正式启动。
IOC容器初始化的过程
Resource定位过程:把容器比做水桶,类似于容器查找数据,提着水桶寻找水源;
BeanDefinition载入:容器中的主要的数据结构,类似于水;
**向IOC容器中注册这些BeanDefinition:**把水倒入水桶中;

在这个注册的过程中,一般不包含Bean依赖注入的实现。在SpringIOC设计过程中,载入和依赖注入是两个过程。依赖注入发生在第一次获取bean的时候。

BeanDefinition的Resource定位

ClassPathResource res = new ClassPathResource(“beans.xml”);

org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory

protected final void refreshBeanFactory() throws BeansException {
		//在这里进行判断,如果已经有了beanFactory,则销毁并关闭
        if (this.hasBeanFactory()) {
            this.destroyBeans();
            this.closeBeanFactory();
        }

        try {
		//创建DefaultListableBeanFactory
            DefaultListableBeanFactory beanFactory = this.createBeanFactory();
            beanFactory.setSerializationId(this.getId());
            this.customizeBeanFactory(beanFactory);
			//调用loadBeanDefinitions再载入BeanDefinition信息
            this.loadBeanDefinitions(beanFactory);
            synchronized(this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        } catch (IOException var5) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
        }
    }

org.springframework.core.io.DefaultResourceLoader#getResource

   public Resource getResource(String location) {
        Assert.notNull(location, "Location must not be null");
		//这里处理classpath:开头的路径
        if (location.startsWith("classpath:")) {
            return new ClassPathResource(location.substring("classpath:".length()), this.getClassLoader());
        } else {
            try {
			//这里处理URL表示的Resource位置
                URL url = new URL(location);
                return new UrlResource(url);
            } catch (MalformedURLException var3) {
			//如果两个都不是,则通过下面的方法获取
                return this.getResourceByPath(location);
            }
        }
    }

org.springframework.context.support.FileSystemXmlApplicationContext#FileSystemXmlApplicationContext(java.lang.String[], boolean, org.springframework.context.ApplicationContext)

 public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
        super(parent);
        this.setConfigLocations(configLocations);
		//这里调用容器的refresh,是载入BeanDefinition的入口
        if (refresh) {
            this.refresh();
        }

    }

BeanDefinition的载入和解析

在这里插入图片描述

org.springframework.context.support.AbstractApplicationContext#refresh

public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
			//这里是在子类中启动refreshBeanFactory的地方
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
			
			//准备在这个上下文环境中使用的BeanFactory
            this.prepareBeanFactory(beanFactory);

            try {
			//设置BeanFactory的后置处理器
                this.postProcessBeanFactory(beanFactory);
				//调用BeanFactory的后置处理器,这些后处理器是在Bean定义中向容器注册的
                this.invokeBeanFactoryPostProcessors(beanFactory);
				//注册Bean的后处理器,在Bean创建过程中调用;
                this.registerBeanPostProcessors(beanFactory);
				//对上下文中的消息源进行初始化
                this.initMessageSource();
				//初始化上下文中的事件机制
                this.initApplicationEventMulticaster();
				//初始化其他特殊的Bean
                this.onRefresh();
				//检查监听Bean并且将这些Bean向容器注册
                this.registerListeners();
				//实例化所有的non-lazy-inti单件
                this.finishBeanFactoryInitialization(beanFactory);
				//发布容器事件,结束Refresh过程
                this.finishRefresh();
            } catch (BeansException var5) {
			//为防止Bean资源占用,在异常处理中,销毁已经生成的bean
                this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt", var5);
                this.destroyBeans();
				//重置active标志
                this.cancelRefresh(var5);
                throw var5;
            }

        }
    }

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.support.EncodedResource)

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
//创建beanDefinitionReader,并且通过回调设置到BeanFactory中
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    beanDefinitionReader.setEnvironment(this.getEnvironment());
	//beanDefinitionReader配置ResourceLoader,因为DefaultResourceLoader是父类,可以直接使用this
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
	//这里启动bean定义信息载入过程
    this.initBeanDefinitionReader(beanDefinitionReader);
    this.loadBeanDefinitions(beanDefinitionReader);
}

org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.xml.XmlBeanDefinitionReader)

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

}

org.springframework.beans.factory.support.AbstractBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.Resource…)
public int loadBeanDefinitions(Resource… resources) throws BeanDefinitionStoreException {

    Assert.notNull(resources, "Resource array must not be null");
    int counter = 0;
    Resource[] arr$ = resources;
    int len$ = resources.length;
	//遍历Resource中包含的BeanDefinition信息
    for(int i$ = 0; i$ < len$; ++i$) {
        Resource resource = arr$[i$];
        counter += this.loadBeanDefinitions((Resource)resource);
    }

    return counter;
}

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.support.EncodedResource)

//这里载入XML形式的BeanDefinition的地方
    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
        Assert.notNull(encodedResource, "EncodedResource must not be null");
        if (this.logger.isInfoEnabled()) {
            this.logger.info("Loading XML bean definitions from " + encodedResource.getResource());
        }

        Set<EncodedResource> currentResources = (Set)this.resourcesCurrentlyBeingLoaded.get();
        if (currentResources == null) {
            currentResources = new HashSet(4);
            this.resourcesCurrentlyBeingLoaded.set(currentResources);
        }

        if (!((Set)currentResources).add(encodedResource)) {
            throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");
        } else {
            int var5;
			//这里得到XML文件,并得到IO的INPUTSOURCE准备进行读取
            try {
                InputStream inputStream = encodedResource.getResource().getInputStream();

                try {
                    InputSource inputSource = new InputSource(inputStream);
                    if (encodedResource.getEncoding() != null) {
                        inputSource.setEncoding(encodedResource.getEncoding());
                    }

                    var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
                } finally {
                    inputStream.close();
                }
            } catch (IOException var15) {
                throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), var15);
            } finally {
                ((Set)currentResources).remove(encodedResource);
                if (((Set)currentResources).isEmpty()) {
                    this.resourcesCurrentlyBeingLoaded.remove();
                }

            }

            return var5;
        }
    }

BeanDefinition在IOC容器中的注册

在这里插入图片描述

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadBeanDefinitions

 protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
        try {
            int validationMode = this.getValidationModeForResource(resource);
			//这里取得XML文件的DOC对象,这个解析过程是由Document完成的。
            Document doc = this.documentLoader.loadDocument(inputSource, this.getEntityResolver(), this.errorHandler, validationMode, this.isNamespaceAware());
			//这里启动的是对BeanDefinition解析的详细过程,这个解析会使用到spring的Bean配置规则
            return this.registerBeanDefinitions(doc, resource);
        } catch (BeanDefinitionStoreException var5) {
            throw var5;
        } catch (SAXParseException var6) {
            throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + var6.getLineNumber() + " in XML document from " + resource + " is invalid", var6);
        } catch (SAXException var7) {
            throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", var7);
        } catch (ParserConfigurationException var8) {
            throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, var8);
        } catch (IOException var9) {
            throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, var9);
        } catch (Throwable var10) {
            throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, var10);
        }
    }

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#processBeanDefinition

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
	//BeanDefinitionHolder是BeanDefinition的封装类,封装了BeanDefinition、Bean的名字和别名,用它来向IOC容器注册;
	//得到BeanDefinitionHolder表明通过了sping规则解析得到的
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);

            try {
			//这里是向IOC容器注册解析得到的BeanDefinition的地方
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
            } catch (BeanDefinitionStoreException var5) {
                this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
            }

			//在BeanDefinition向ICO容器注册后,发送消息
            this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }

    }

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)

 public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
	//这里获取<bean>元素定义的id、name和aliase属性的值
        String id = ele.getAttribute("id");
        String nameAttr = ele.getAttribute("name");
        List<String> aliases = new ArrayList();
        if (StringUtils.hasLength(nameAttr)) {
            String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
            aliases.addAll(Arrays.asList(nameArr));
        }

        String beanName = id;
        if (!StringUtils.hasText(id) && !aliases.isEmpty()) {
            beanName = (String)aliases.remove(0);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases");
            }
        }

        if (containingBean == null) {
            this.checkNameUniqueness(beanName, aliases, ele);
        }

		//这个方法是对Bean的详细解析
        AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);
        if (beanDefinition != null) {
            if (!StringUtils.hasText(beanName)) {
                try {
                    if (containingBean != null) {
                        beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
                    } else {
                        beanName = this.readerContext.generateBeanName(beanDefinition);
                        String beanClassName = beanDefinition.getBeanClassName();
                        if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                            aliases.add(beanClassName);
                        }
                    }

                    if (this.logger.isDebugEnabled()) {
                        this.logger.debug("Neither XML 'id' nor 'name' specified - using generated bean name [" + beanName + "]");
                    }
                } catch (Exception var9) {
                    this.error(var9.getMessage(), ele);
                    return null;
                }
            }

            String[] aliasesArray = StringUtils.toStringArray(aliases);
            return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
        } else {
            return null;
        }
    }

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element, java.lang.String, org.springframework.beans.factory.config.BeanDefinition)

public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
        this.parseState.push(new BeanEntry(beanName));
		//这是只是获取bean定义中的class名字,然后载入在BeanDefinition中,只是记录,不涉及实例化过程,实例化是依赖注入时进行的
        String className = null;
        if (ele.hasAttribute("class")) {
            className = ele.getAttribute("class").trim();
        }

        try {
            String parent = null;
            if (ele.hasAttribute("parent")) {
                parent = ele.getAttribute("parent");
            }
			//这里生成需要的BeanDefinition对象,为Bean定义信息的载入做准备
            AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);
			//这里对当前的bean元素进行属性解析,并设置describe信息
            this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);		
            bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
			//这里是对bean元素的信息进行解析的地方
            this.parseMetaElements(ele, bd);
            this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
            this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
			//解析bean的构造函数设置
            this.parseConstructorArgElements(ele, bd);
			//解析bean的property设置
            this.parsePropertyElements(ele, bd);
            this.parseQualifierElements(ele, bd);
            bd.setResource(this.readerContext.getResource());
            bd.setSource(this.extractSource(ele));
            AbstractBeanDefinition var7 = bd;
            return var7;
			//经常看到的异常信息
        } catch (ClassNotFoundException var13) {
            this.error("Bean class [" + className + "] not found", ele, var13);
        } catch (NoClassDefFoundError var14) {
            this.error("Class that bean class [" + className + "] depends on not found", ele, var14);
        } catch (Throwable var15) {
            this.error("Unexpected failure during bean definition parsing", ele, var15);
        } finally {
            this.parseState.pop();
        }

        return null;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章