• spring源码-bean之初始化-1


      一、spring的IOC控制反转:控制反转——Spring通过一种称作控制反转(IOC)的技术促进了松耦合。当应用了IOC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。说白了就是原本需要手动去创建和管理的对象,现在交给容器了。在容器的基础上,实现对象的控制。这个方式也很好的减少了开发者在框架上面的时间,更多关注点在业务逻辑上面。

      二、这表博客的主要目的是研究,bean容器的初始化,会在最基本的bean初始化作源码的解析和分析。如何存在不妥当的地方,还请指出!

      三、BeanFactory是spring的核心,通过工厂的模式来创建和使用bean。

      四、我们都知道spring的bean初始化,依赖xml文件来实现的,所以这里重点讲解XmlBeanFactory的初始化过程。可能有人会问为什么不是ApplicationContext,相对于ApplicationContext,XmlBeanFactory是基础的bean初始化过程,后续我会单独将ApplicationContext又做了哪些动作。

      五、源码解读

      1)创建xml配置文件spring-bean.xml(这里省略User,,重点不在这里)

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="user" class="com.pinnet.customLabel.User"/>
    </beans>

      2)开始创建对象

    package com.pinnet.bean;
    
    import org.springframework.beans.factory.xml.XmlBeanFactory;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.core.io.Resource;
    
    public class Test {
    
        public static void main(String[] args) {
            //读取资源
            Resource resource = new ClassPathResource("spring-bean.xml");
            //初始化容器
            new XmlBeanFactory(resource);
        }
    }

      3)初始化XmlBeanFactory

    private final XmlBeanDefinitionReader reader;
    
        public XmlBeanFactory(Resource resource) throws BeansException {
            this(resource, (BeanFactory)null);
        }
    
        public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
            super(parentBeanFactory);
            //用XmlBeanDefinitionReader,来进行加载
            this.reader = new XmlBeanDefinitionReader(this);
            //解析资源
            this.reader.loadBeanDefinitions(resource);
        }

      4)loadBeanDefinitions

    public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    //包装成EncodedResource
    return this.loadBeanDefinitions(new EncodedResource(resource)); } 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 var6; try {
    //转换成InputStream流 InputStream inputStream
    = encodedResource.getResource().getInputStream(); try { InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } //进一步解析 var6 = 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 var6; } }

      5)doLoadBeanDefinitions

    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
            try {
                int validationMode = this.getValidationModeForResource(resource);
    //读取xml为doc Document doc
    = this.documentLoader.loadDocument(inputSource, this.getEntityResolver(), this.errorHandler, validationMode, this.isNamespaceAware());
    //注册BeanDefinition
    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); } }

      6)registerBeanDefinitions

    public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
            this.readerContext = readerContext;
            this.logger.debug("Loading bean definitions");
            Element root = doc.getDocumentElement();
            BeanDefinitionParserDelegate delegate = this.createHelper(readerContext, root);
         //此方法用于提供子类处理之用
    this.preProcessXml(root); this.parseBeanDefinitions(root, delegate);
         //此方法用于提供子类处理之用
    this.postProcessXml(root); }

      7)parseBeanDefinitions(这一部分就是解析过程了)

    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
            if (delegate.isDefaultNamespace(root)) {
                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)) {
                  //默认标签解析
    this.parseDefaultElement(ele, delegate); } else {
                  //自定义标签解析(这里后面讲,这个也是非常重要的拓展功能)         delegate.parseCustomElement(ele); } } } }
    else { delegate.parseCustomElement(root); } }

      8)parseDefaultElement(默认标签解析,这里关注bean)

    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
            if (delegate.nodeNameEquals(ele, "import")) {
                this.importBeanDefinitionResource(ele);
            } else if (delegate.nodeNameEquals(ele, "alias")) {
                this.processAliasRegistration(ele);
            } else if (delegate.nodeNameEquals(ele, "bean")) {
                this.processBeanDefinition(ele, delegate);
            }
        }

      9)processBeanDefinition

     protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
            //这里主要是解析过程
            BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
            if (bdHolder != null) {
                bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
                try {
                    //这里注册bean到beanDefinitionMap,后面会看到
                    BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
                } catch (BeanDefinitionStoreException var5) {
                    this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
                }
                this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
            }
        }

      a、parseBeanDefinitionElement

      public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
            return this.parseBeanDefinitionElement(ele, (BeanDefinition)null);
        }
    
        public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
            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((Collection)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) {
                //检查id和别名是否重复
                this.checkNameUniqueness(beanName, aliases, ele);
            }
    
            //解析过程
            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
                            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); //将别名和beanName放入BeanDefinitionHolder return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } else { return null; } }

      parseBeanDefinitionElement(进一步解析过程,可以自己查看源码,这里不讲解)

    public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
            this.parseState.push(new BeanEntry(beanName));
            String className = null;
            if (ele.hasAttribute("class")) {
                className = ele.getAttribute("class").trim();
            }
            try {
                String parent = null;
                if (ele.hasAttribute("parent")) {
                    parent = ele.getAttribute("parent");
                }
                //创建GenericBeanDefinition
                AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);
                //解析bean上面的默认元素
                this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
                bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
                //meta
                this.parseMetaElements(ele, bd);
                //lookup-method
                this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
                //replaced-method
                this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
                //constructor-arg
                this.parseConstructorArgElements(ele, bd);
                //property
                this.parsePropertyElements(ele, bd);
                //qualifier
                this.parseQualifierElements(ele, bd);
                bd.setResource(this.readerContext.getResource());
                bd.setSource(this.extractSource(ele));
                //所有解析过后的元素全部放在AbstractBeanDefinition里面
                AbstractBeanDefinition var8 = bd;
                return var8;
            } 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;
        }

      b、registerBeanDefinition(将AbstractBeanDefinition的相关数据放入beanDefinitionMap)

    public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
            String beanName = definitionHolder.getBeanName();
            registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
            String[] aliases = definitionHolder.getAliases();
            if (aliases != null) {
                String[] var7 = aliases;
                int var6 = aliases.length;
    
                for(int var5 = 0; var5 < var6; ++var5) {
                    String aliase = var7[var5];
                    registry.registerAlias(beanName, aliase);
                }
            }
    
        }
    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 var6) {
                    throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var6);
                }
            }
    
            Map var3 = this.beanDefinitionMap;
            synchronized(this.beanDefinitionMap) {
                Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
                if (oldBeanDefinition != null) {
                    if (!this.allowBeanDefinitionOverriding) {
                        throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound.");
                    }
    
                    if (this.logger.isInfoEnabled()) {
                        this.logger.info("Overriding bean definition for bean '" + beanName + "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
                    }
                } else {
                    this.beanDefinitionNames.add(beanName);
                    this.frozenBeanDefinitionNames = null;
                }
                //将beanName和beanDefinition形成键值对的形式,保存在Map中
                this.beanDefinitionMap.put(beanName, beanDefinition);
                this.resetBeanDefinition(beanName);
            }
        }

      六、好了,这就是源码的实现过程,中间省略了很多的判定和实现过程。主要的流程,基本上就是这样。这里重点注意几个点,也是对流程的梳理

      1)初始化XmlBeanFactory,需要注意XmlBeanDefinitionReader:这是整个解读过程的关键

      2)然后就是字符集包装,然后形成流EncodedResource、inputSource

      3)解析xml,基本上是通过spring的DefaultDocumentLoader实现的,通过对Document文档的解析来实现标签和元素的解析

      4)判断是否是默认标签是通过xml的Namespace来实现的,默认Namespace的读取目录是通过DefaultNamespaceHandlerResolver来实现的,也就是读取spring.handlers和spring.schemas,后续会讲到这两个文件的作用

      public boolean isDefaultNamespace(String namespaceUri) {
            return !StringUtils.hasLength(namespaceUri) || "http://www.springframework.org/schema/beans".equals(namespaceUri);
        }
      protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
            return new DefaultNamespaceHandlerResolver(this.getResourceLoader().getClassLoader());
        }

      spring.handlers

    http://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler
    http://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler

      spring.schemas

    http://www.springframework.org/schema/beans/spring-beans-2.0.xsd=org/springframework/beans/factory/xml/spring-beans-2.0.xsd
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd=org/springframework/beans/factory/xml/spring-beans-2.5.xsd
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd
    http://www.springframework.org/schema/beans/spring-beans.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd
    http://www.springframework.org/schema/tool/spring-tool-2.0.xsd=org/springframework/beans/factory/xml/spring-tool-2.0.xsd
    http://www.springframework.org/schema/tool/spring-tool-2.5.xsd=org/springframework/beans/factory/xml/spring-tool-2.5.xsd
    http://www.springframework.org/schema/tool/spring-tool-3.0.xsd=org/springframework/beans/factory/xml/spring-tool-3.0.xsd
    http://www.springframework.org/schema/tool/spring-tool.xsd=org/springframework/beans/factory/xml/spring-tool-3.0.xsd
    http://www.springframework.org/schema/util/spring-util-2.0.xsd=org/springframework/beans/factory/xml/spring-util-2.0.xsd
    http://www.springframework.org/schema/util/spring-util-2.5.xsd=org/springframework/beans/factory/xml/spring-util-2.5.xsd
    http://www.springframework.org/schema/util/spring-util-3.0.xsd=org/springframework/beans/factory/xml/spring-util-3.0.xsd
    http://www.springframework.org/schema/util/spring-util.xsd=org/springframework/beans/factory/xml/spring-util-3.0.xsd

      5)解析bean标签,是生产一个GenericBeanDefinition这个类是继承AbstractBeanDefinition生产BeanDefinition的过程其实就是讲标签里面的元素进行解析放入的过程

      6)注册的过程是放在DefaultListableBeanFactory里面的beanDefinitionMap,是不是有点奇怪过程并没有DefaultListableBeanFactory。在源码的9)中使用了BeanDefinitionRegistry ,而这个BeanDefinitionRegistry 也是我们最开始使用的XmlBeanFactory,但是XmlBeanFactory,并没有太多的实现。看来一个结构:

      其实最开始调用XmlBeanFactory的时候就已经使用了DefaultListableBeanFactory,值不够是继承关系而已。所以这里基本上所有的数据都在DefaultListableBeanFactory里面了

      7)最后解析过程就到这里,主要数据全部在DefaultListableBeanFactorybeanDefinitionMap里面。

      8)注意一点,别名的加载过程也很重要,这里不多介绍,多想法自己查看源码

      七、容器的初始化基本上就是这样了,主要是梳理流程和spring在IOC的控制中做了什么。

  • 相关阅读:
    v4l2程序实例
    uboot的readme导读
    基于Linux的v4l2视频架构驱动编写
    V4L2
    Uboot优美代码赏析1:目录结构和malkefile分析
    查找 mysql 配置文件 my.cnf
    thinkphp中array_diff运行无效 Invalid opcode 153/1/8
    thinkphp后端开发ajax接口开发测试
    Thinkphp getLastSql函数用法
    web日志分析的重要性
  • 原文地址:https://www.cnblogs.com/ll409546297/p/9451784.html
Copyright © 2020-2023  润新知