• 【Spring 源码】Spring 加载资源并装配对象的过程(XmlBeanDefinitionReader)


    Spring 加载资源并装配对象过程

    在Spring中对XML配置文件的解析从3.1版本开始不再推荐使用XmlBeanFactory而是使用XmlBeanDefinitionReader。

    ClassPathResource resource = new ClassPathResource("bean.xml");
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
    reader.loadBeanDefinitions(resource);
    // 上面步骤只是将spring bean的配置文件解析并注册到spring容器中,并未实例化
    // 经过下面的步骤,才会执行实例化
    Person person = (Person) factory.getBean("person");
    person.say();
    

    解析XML主要流程:
    1、定义好Spring 的配置文件
    2、通过Resource对象将Spring配置文件进行抽象,抽象成一个Resource对象
    3、定义好Bean工厂(各种BeanFactory)
    4、定义好XmlBeanDefinitionReader对象,并将工厂作为参数传递进去供后续回调使用
    5、通过XmlBeanDefinitionReader对象读取之前抽象出的Resource对象(包含了XML文件的解析过程)
    6、本质上,XML文件的解析是由XmlBeanDefinitionReader对象交由BeanDefinitionParserDelegate委托来完成的,实质上这里使用了委托设计模式。--注册bean定义到容器
    7、IoC容器创建完闭,用户可以通过容器获取所需对象信息。--实例化

    重要:在DefaultBeanDefinitionDocumentReader类中的doRegisterBeanDefinitions方法使用了经典的模板方法设计模式,子类可以重写preProcessXml与poseProcessXml方法,实现对XML配置文件的自定义扩展。

    singleton bean的实例化过程:(org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String))
    1、Spring 的bean实际上是缓存在 ConcurrentHashMap(singletonObjects)中(org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean))
    2、在创建bean之前,首先需要将该bean的创建标识设定好,表示该bean已经或即将被创建,为的是增强缓存效率(org.springframework.beans.factory.support.AbstractBeanFactory#markBeanAsCreated)
    3、根据bean的scope属性确定是singleton还是prototype等范围,然后创建相应的bean对象。
    4、通过Java反射来创建bean实例,在创建之前首先检查访问修饰符,如果不是public的,则调用setAccessible(true)来突破Java的语法限制,使得可以通过如私有构造方法来创建对象实例。(org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean)
    5、接下来,寻找bean的属性值,完成属性注入(org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean)
    6、将所有创建出的singleton实例添加到缓存当中,供下次使用调用(org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingleton)


    涉及的源代码UML

    ClassPathResource

    DefaultListableBeanFactory

    XmlBeanDefinitionReader

    验证代码

    代码结构

    pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>spring</groupId>
      <artifactId>zqq</artifactId>
      <version>1.0-SNAPSHOT</version>
    
      <name>zqq</name>
      <!-- FIXME change it to the project's website -->
      <url>http://www.example.com</url>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
      </properties>
    
      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.12</version>
        </dependency>
        <!--1)Spring核心依赖-->
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
          <version>4.3.4.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
          <version>4.3.4.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>4.3.4.RELEASE</version>
        </dependency>
        <!--Spring DAO层依赖-->
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>4.3.4.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-tx</artifactId>
          <version>4.3.4.RELEASE</version>
        </dependency>
        <!--3)Spring Web相关依赖-->
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-web</artifactId>
          <version>4.3.4.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>4.3.4.RELEASE</version>
        </dependency>
        <!--4)Spring test相关依赖-->
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-test</artifactId>
          <version>4.3.4.RELEASE</version>
        </dependency>
      </dependencies>
    
      <build>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
          <plugins>
            <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
            <plugin>
              <artifactId>maven-clean-plugin</artifactId>
              <version>3.1.0</version>
            </plugin>
            <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
            <plugin>
              <artifactId>maven-resources-plugin</artifactId>
              <version>3.0.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>3.8.0</version>
            </plugin>
            <plugin>
              <artifactId>maven-surefire-plugin</artifactId>
              <version>2.22.1</version>
            </plugin>
            <plugin>
              <artifactId>maven-jar-plugin</artifactId>
              <version>3.0.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-install-plugin</artifactId>
              <version>2.5.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-deploy-plugin</artifactId>
              <version>2.8.2</version>
            </plugin>
            <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
            <plugin>
              <artifactId>maven-site-plugin</artifactId>
              <version>3.7.1</version>
            </plugin>
            <plugin>
              <artifactId>maven-project-info-reports-plugin</artifactId>
              <version>3.0.0</version>
            </plugin>
          </plugins>
        </pluginManagement>
      </build>
    </project>
    
    

    App.java

    package spring;
    
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
    import org.springframework.core.io.ClassPathResource;
    
    public class App 
    {
        public static void main( String[] args )
        {
            ClassPathResource resource = new ClassPathResource("beans.xml");
            DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
            XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
            reader.loadBeanDefinitions(resource);
            Person person = (Person) factory.getBean("person");
            person.say();
        }
    }
    
    

    Person.java

    package spring;
    
    public interface Person {
        void say();
    
    }
    
    

    PersonImpl.java

    package spring;
    
    public class PersonImpl implements Person {
        String name="";
    
        @Override
        public void say() {
            System.out.println(name);
        }
    
        public void setName(String name) {
            this.name=name;
        }
    }
    
    

    注意:由于开始创建的是quickstart工程,没有resources目录,而beans.xml需要放到该目录下才会被找到,需要在project structure的modules管理中新建资源文件夹。

    参考资料:
    Spring如何解析XML文件——Spring源码之XML初解析

  • 相关阅读:
    喜欢的诗
    诗集与集诗
    oracle 12c 中asm元数据是否有所变化
    hdu2066一个人的旅行(dijkstra)
    单链表
    ExtJS4.2学习(7)——基础知识之Reader&Writer篇
    hdu3790最短路径问题 (用优先队列实现的)
    poj 1220 NUMBER BASE CONVERSION(短除法进制转换)
    POJ 4003 Bob’s Race && HDU4123 Bob’s Race (dfs+rmq)
    全排列
  • 原文地址:https://www.cnblogs.com/z00377750/p/11752385.html
Copyright © 2020-2023  润新知