【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 源码】Spring 加载资源并装配对象的过程(XmlBeanDefinitionReader)的更多相关文章
- Spring 源码学习——加载 Bean
继上次注册 bean 之后好久没更新,这两天有空查了查资料也自己看了看 spring BeanFactory 的 getBean(beanName); 这个方法.因时间有限不能像之前那样复制代码并一行 ...
- Spring源码之DefaultListableBeanFactory及资源载入
1.XmlBeanFactory 的使用,参考MyEclipse Spring 学习总结一 Spring IOC容器 public static void main(String[] args) { ...
- Spring boot 国际化自动加载资源文件问题
Spring boot 国际化自动加载资源文件问题 最近在做基于Spring boot配置的项目.中间遇到一个国际化资源加载的问题,正常来说只要在application.properties文件中定义 ...
- 深入理解 spring 容器,源码分析加载过程
Spring框架提供了构建Web应用程序的全功能MVC模块,叫Spring MVC,通过Spring Core+Spring MVC即可搭建一套稳定的Java Web项目.本文通过Spring MVC ...
- 2.2 spring5源码 -- ioc加载的整体流程
之前我们知道了spring ioc的加载过程, 具体如下图. 下面我们就来对照下图, 看看ioc加载的源代码. 下面在用装修类比, 看看个个组件都是怎么工作的. 接下来是源码分析的整体结构图. 对照上 ...
- jquery源码 DOM加载
jQuery版本:2.0.3 DOM加载有关的扩展 isReady:DOM是否加载完(内部使用) readyWait:等待多少文件的计数器(内部使用) holdReady():推迟DOM触发 read ...
- Spring源码窥探之:单实例Bean的创建过程
finishBeanFactoryInitialization(beanFactory);初始化剩下的所有的单实例(非懒加载)Bean(Instantiate all remaining (non-l ...
- spring源码学习之路---深度分析IOC容器初始化过程(四)
作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 最近由于工作和生活,学习耽搁 ...
- spring源码解读-ioc
本系列博客结合我的理解,对spring的ioc进行简单分析,欢迎大家批评指正. beanfactory 我们从beanfactory开始,beanfactory是最根部的容器,描述了整个ioc的一些规 ...
随机推荐
- 配置https证书
官网: https://certbot.eff.org/lets-encrypt/ubuntubionic-nginx ssl安装检测工具: https://www.myssl.cn/tools/ch ...
- ga
https://developers.google.com/analytics/devguides/collection/gtagjs/events ga 添加事件示例: 在代码中指定您自己的值,就可 ...
- audio 预加载
http://www.w3school.com.cn/tags/av_event_loadeddata.asp var audio = document.createElement("aud ...
- javascript类型判断最佳实践
javascript有8种数据类型 值类型 Number Null Undefined String Symbol Boolean BigInt 引用类型 Object Array Function ...
- Codevs 1851 越狱 2008年湖南省队选拔赛
1851 越狱 2008年湖南省队选拔赛 时间限制: 10 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 监狱有连续编号为1-N的N个房间,每 ...
- Codeforces 1214 F G H 补题记录
翻开以前打的 #583,水平不够场上只过了五题.最近来补一下题,来记录我sb的调试过程. 估计我这个水平现场也过不了,因为前面的题已经zz调了好久-- F:就是给你环上一些点,两两配对求距离最小值. ...
- 2019 7.6 T2 虫洞
虫洞(conch) [题目描述] HZY 现在在数轴原点处,她想跑到 2000001 这个点上.听说各路 神犇暑假里都在健♂身,所有 HZY 也想不要只是简单地跑步,于是她 决定在这条数轴上造虫洞,具 ...
- Zabbix 4.0.2试用(七):在Linux主机中安装zabbix agent并添加该主机(yum源安装)
Zabbix 4.0.2试用(七):在Linux主机中安装zabbix agent并添加主机(yum源安装) 2018年12月20日, 上午6:42 之前介绍的是下载源安装包,编译安装的方式来安装ag ...
- 6 Java Shell排序
希尔排序是先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序. 1.基本思想 将待排序数组按照步长gap进行分组,然后将 ...
- Mybatis不使用Spring框架(Druid)
1.Mysql database CREATE TABLE mockrecord (id INT(10) unsigned PRIMARY KEY NOT NULL COMMENT 'mock记录编号 ...