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初解析

【Spring 源码】Spring 加载资源并装配对象的过程(XmlBeanDefinitionReader)的更多相关文章

  1. Spring 源码学习——加载 Bean

    继上次注册 bean 之后好久没更新,这两天有空查了查资料也自己看了看 spring BeanFactory 的 getBean(beanName); 这个方法.因时间有限不能像之前那样复制代码并一行 ...

  2. Spring源码之DefaultListableBeanFactory及资源载入

    1.XmlBeanFactory 的使用,参考MyEclipse Spring 学习总结一 Spring IOC容器 public static void main(String[] args) { ...

  3. Spring boot 国际化自动加载资源文件问题

    Spring boot 国际化自动加载资源文件问题 最近在做基于Spring boot配置的项目.中间遇到一个国际化资源加载的问题,正常来说只要在application.properties文件中定义 ...

  4. 深入理解 spring 容器,源码分析加载过程

    Spring框架提供了构建Web应用程序的全功能MVC模块,叫Spring MVC,通过Spring Core+Spring MVC即可搭建一套稳定的Java Web项目.本文通过Spring MVC ...

  5. 2.2 spring5源码 -- ioc加载的整体流程

    之前我们知道了spring ioc的加载过程, 具体如下图. 下面我们就来对照下图, 看看ioc加载的源代码. 下面在用装修类比, 看看个个组件都是怎么工作的. 接下来是源码分析的整体结构图. 对照上 ...

  6. jquery源码 DOM加载

    jQuery版本:2.0.3 DOM加载有关的扩展 isReady:DOM是否加载完(内部使用) readyWait:等待多少文件的计数器(内部使用) holdReady():推迟DOM触发 read ...

  7. Spring源码窥探之:单实例Bean的创建过程

    finishBeanFactoryInitialization(beanFactory);初始化剩下的所有的单实例(非懒加载)Bean(Instantiate all remaining (non-l ...

  8. spring源码学习之路---深度分析IOC容器初始化过程(四)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 最近由于工作和生活,学习耽搁 ...

  9. spring源码解读-ioc

    本系列博客结合我的理解,对spring的ioc进行简单分析,欢迎大家批评指正. beanfactory 我们从beanfactory开始,beanfactory是最根部的容器,描述了整个ioc的一些规 ...

随机推荐

  1. [人物存档]【AI少女】【捏脸数据】1223今日份的推荐

    点击下载(城通网盘):AISChaF_20191112214754919.png 点击下载(城通网盘):AISChaF_20191111205924765.png

  2. phpstorm快捷键和激活

    点击PHP中文网->PHPstorm激活, 按照步骤激活 今天遇到了不能激活的情况, your activation code could not be validated.这个解决方法是把上面 ...

  3. Vue3.0+TypeScript

    序言 资料 https://www.cnblogs.com/chanwahfung/p/11968205.html

  4. react-native-swiper的Github地址

    https://github.com/liyinglihuannan/react-native-swiper https://www.jianshu.com/p/4dba338ef37a(中文版

  5. HDU - 6183 暴力,线段树动态开点,cdq分治

    B - Color itHDU - 6183 题目大意:有三种操作,0是清空所有点,1是给点(x,y)涂上颜色c,2是查询满足1<=a<=x,y1<=b<=y2的(a,b)点一 ...

  6. Java当中的集合框架

    Java当中的集合框架 01 在我们班里有50位同学,就有50位对象. // 简书作者:达叔小生 Student[] stus = new Student[20]; 结果来了一位插班生,该同学因为觉得 ...

  7. 浅淡数据仓库(二)星型模式与OLAP多维数据库

    在关系数据库管理系统中实现的维度模型称为星型模型模式,因为其结构类似星型结构.在多为数据库环境中实现的维度模型通常称为联机分析处理(OLAP)多维数据库

  8. Android学习_Selector

    Selector 实现组件在不同状态下不同的文字颜色.背景颜色或图片的切换,使用十分方便. 1. 创建方法 第一种:在XML中直接创建selector的XML文件,容易掌握,简单但是不灵活,较为常用. ...

  9. 09.变态跳台阶 Java

    题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级.求该青蛙跳上一个n级的台阶总共有多少种跳法. 思路 0:0 1:(1) 2:(1,1)(2) 3:(1,1,1)(2,1)( ...

  10. 【python / mxnet / gluoncv / jupyter notebook】基于mxnet和gluoncv的图像分割

    程序环境为高性能集群: CPU:Intel Xeon Gold 6140 Processor * 2(共36核心)内存:512GB RAMGPU:Tesla P100-PCIE-16GB * 2 In ...