总述:spring框架是如今J2EE开发最重要框架之一,为企业级应用提供一系列轻量级解决方案,比如:基于依赖注入的核心机制、基于AOP的声明式事务管理、与多种持久层技术整合、整合后端各种组件等等。贯穿了表现层、业务层、持久层,实现无缝整合。
文章结构:(1) 框架总述;(2)以Bean为核心的IOC/DI机制;
一、框架总述:
图选自疯狂Java讲义。文字参考:此博主此文章。本博主在此摘抄并补充下
(1)Core Container(核心容器):
包含有Core,Beans,Context,Expression Language模块。是框架的基础部分,提供IOC(控制反转)和依赖注入特性。这里的基础概念 是BeanFactory,它提供Factory模式的经典实现来消除对程序单例模式的需要,并真正地允许你从程序逻辑中分离出依赖关系和配置。
- Core模块主要包含Spring框架基本的核心工具类,Spring的其他组件都要使用到这个包里的类,Core模块是其他组件的基本核心。当然你也可以在自己的应用系统中使用这些工具类。
- Beans模块是所有应用都要用到的,它包含访问配置文件,创建和管理bean以及进行Inversion of Control/Dependency Injection(依赖注入)操作相关的所有类。
- Context模块构建于Core和Beans模块基础之上,提供了一种类似于JNDI注册器的框架式的对象访问方法。Context模块集成了Beans的特性,为Spring核心提供了大量的扩展,添加了对国际化(例如资源绑定),事件传播,资源加载和对Context的透明创建的支持。Context模块同时也支持J2EE的一些特性,例如EJB(java企业Bean),JMX(Java Management Extensions,即Java管理扩展是一个为应用程序、设备、系统等植入管理功能的框架)和基础的远程处理。ApplicationContext接口是Context模块的关键。
- Expression Language 模块提供了一个强大的表达式语言用于在运行时查询和操纵对象。它是JSP2.1规范中定义的unifed expression language的一个扩展。该语言支持设置/获取属性的值,属性的分配,方法的调用,访问数组上下文(accession the context of arrays),容器和索引器,逻辑和算数运算符,命名变量以及从Spring的IOC容器中根据名称检索对象。它也支持list投影,选择和一般的list聚合。
(2)WEB层:
Web上下文模块建立在应用程序上下文模块之上,为基于Web的应用程序提供了上下文。所以Spring框架支持与Jakarta Struts的集成。Web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。Web层包含了Web,Web-Servlet,Web-Struts和Web-Porlet模块,具体说明如下。
- Web-Servlet模块web.servlet.jar:该模块包含Spring的model-view-controller(MVC)的实现。Spring的MVC框架使得模型范围内的代码和web forms之间能够清楚地分离开来,并与Spring框架的其他特性集成在一起。
- Web模块:提供了基础的面向Web的集成特性。例如,多文件上传,使用servlet listeners初始化IOC容器以及一个面向Web的应用上下文。它还包含Spring远程支持中Web的相关部分。
- Web-Porlet模块:提供了用于Portlet环境和Web-Servlet模块的MVC的实现。
- spring4.0以后加入了对websocket技术的支持.目的是浏览器与服务端建立全双工的通信方式,解决http请求-响应带来过多的资源消耗,同时对特殊场景应用提供了全新的实现方式,比如聊天、股票交易、游戏等对对实时性要求较高的行业领域。
(3)Data Access/Integration.持久层:
Data Access/Integration层包含有JDBC,ORM,OXM,JMS和Transaction模块,其中:
- JDBC模块提供了一个JDBC抽象层,它可以消除冗长的JDBC编码和解析数据库厂商特有的错误代码。这个模块包含了Spring对JDBC数据访问进行封装的所有类。
- ORM(Object Relational Mapping对象关系映射)模块为流行的对象-关系映射API,如JPA,JDO,Hibernate,iBatis等,提供了一个交互层。利用ORM封装包,可以混合使用所有Spring提供的特性进行O/R映射。如前边提到的简单声明性事务管理。
Spring框架插入了若干个ORM框架,从而提供了ORM的对象关系工具,其中包括JDO,hibernate和MyBatis。所有这些都遵从Spring的通用事务和DAO异常层次结构。
- OXM模块提供了一个对Object/XML映射实现的抽象层,Object/XML映射实现包括JAXB(JAXB能够使用Jackson对JAXB注解的支持实现(jackson-module-jaxb-annotations),既方便生成XML,也方便生成JSON,这样一来可以更好的标志可以转换为JSON对象的JAVA类。
- JMS(Java Messaging Service)模块主要包含了一些制造和消费消息的特性。
- Transaction模块支持编程和声明性的事务管理,这些事务类必须实现特定的接口,并且对所有的POJO(实际就是普通JavaBeans)都适用。
(4)切面层:
1. AOP模块提供了一个符合AOP联盟标准的面向切面编程的实现,它让你可以定义例如方法拦截器和切点。从而将逻辑代码分开,降低它们之间的耦合性。利用source-level的元数据功能,还可以将各种行为信息合并到你的代码中,这有点像.Net技术中的attribute概念。
通过配置管理特性,SpringAOP模块直接将面向切面的编程功能集成到了Spring框架中,所以可以很容易地使Spring框架管理的任何对象支持AOP。Spring AOP模块为基于Spring的应用程序中的对象提供了事务管理服务。通过使用Spring AOP,不用依赖EJB组件,就可以将声明性事务管理集成到应用程序中。
2. Aspects模块提供了对AspectJ(一个面向切面的框架,它扩展了Java语言)的集成支持。
3.Instrumentation模块提供了class instrumentation 支持和classloader实现,使得可以在特定的应用服务器上使用。
(5)Test层:
此层支持使用JUnit和TestNG对Spring组件进行测试。
@RunWith(SpringJUnit4ClassRunner.class) // 使用Springtest测试框架
@ContextConfiguration("/spring/spring-*.xml") // 加载配置
二、以Bean为核心的IOC/DI机制:
总述理论核心:在spring中,所有的对象都会被spring核心容器管理。一切对象统称为Bean。
Spring容器可通过XML配置文件或者注解去管理这堆Bean。
(1)定义以及原理:
依赖注入(IOC/DI):spring容器负责将被依赖对象赋值给调用者的成员变量--相当于为调用者注入它依赖的实例。
依赖关系:A对象需要调用B对象方法的情况--A依赖B。
原理:
1. 原始做法:调用者主动创建被依赖对象,然后再调用被依赖对象的方法。
调用者需要通过像“new 对象”的操作去创建对象。
缺点:必然导致调用者与被依赖对象实现类的硬编码耦合。(因为我不想知道你的创建过程、也不想主动去创建你)
2. 简单工厂模式:调用者先找到被依赖对象的工厂,然后主动通过工厂去获取被依赖对象,最后再调用被依赖对象的方法。
调用者面向被依赖对象的接口编程;将被依赖对象的创建交给工厂;调用者通过工厂来获得被依赖组件。
缺点:调用组件需要主动通过工厂去获取被依赖对象,必然带来调用组件与被依赖对象工厂的耦合。(同样,我也不想知道你这个工厂存在,我只想要个依赖对象)
3.Spring框架下的依赖注入:框架为调用者注入它依赖的实例。
优点:程序无须例会被依赖对象的实现,也无须主动定位工厂。只需被动等待IOC容器分配依赖对象。
(2)应用:
依赖注入分为两种:[一]设值注入;[二]构造注入;
1. 设值注入:指IOC容器通过成员遍历的setter方法来注入被依赖对象。
使用方法:可见我们没有硬编码上去创建依赖对象
<?xml version="1.0" encoding="GBK"?>
<!-- Spring配置文件的根元素,使用spring-beans-4.0.xsd语义约束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<!-- 配置chinese实例,其实现类是Chinese类 -->
<bean id="chinese" class="com.fuzhu.Chinese">
<!-- 驱动调用chinese的setAxe()方法,将容器中stoneAxe作为传入参数 -->
<property name="axe" ref="stoneAxe"/>
</bean>
<!-- 配置Axe实例 -->
<bean id="axe" class="com.fuzhu.Axe"/>
</beans>
public class Chinese
{
private Axe axe;//定义个斧头引用
// 设值注入所需的setter方法
public void setAxe(Axe axe)
{
this.axe = axe;
}
// 实现依赖对象的方法useAxe方法
public void useAxe()
{
// 调用axe的chop()方法,
// 表明Chinese 对象依赖于axe对象
System.out.println(axe.chop());
}
}
//斧头类
public class Axe
{
public String chop()
{
return "石斧砍柴好慢";
}
}
写个test类
public class BeanTest
{
public static void main(String[] args)throws Exception
{
// 创建Spring容器
ApplicationContext ctx = new
ClassPathXmlApplicationContext("beans.xml");
// 获取chinese 实例
Chinese p = ctx.getBean("chinese" , Chinese.class);
// 调用useAxe()方法
p.useAxe();
}
}
2. 构造注入:IOC容器使用构造器来注入被依赖对象。
在构造实例时,已经为其完成了依赖关系的初始化。本质就是当执行带参数的构造器时,就可利用构造器参数对成员变量执行初始化。《contructopr-arg... /》
使用方法:
<?xml version="1.0" encoding="GBK"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<!-- 配置chinese实例,其实现类是Chinese -->
<bean id="chinese" class="com.fuzhu.Chinese">
<!-- 下面只有一个constructor-arg子元素,
驱动Spring调用Chinese带一个参数的构造器来创建对象 -->
<constructor-arg ref="axe" type="com.fuzhu.Axe"/>
</bean>
<!-- 配置Axe实例-->
<bean id="axe" class="com.fuzhu.StoneAxe"/>
</beans>
public class Chinese
{
private Axe axe;
// 构造注入所需的带参数的构造器
public Chinese(Axe axe)
{
this.axe = axe;
}
// 实现依赖对象的方法useAxe()方法
public void useAxe()
{
// 调用axe的chop()方法
// 表明Chinese 对象依赖于axe对象
System.out.println(axe.chop());
}
}
public class Axe
{
public String chop()
{
return "石斧砍柴好慢";
}
}
3. 注解注入装配: 以后再讲,其实是基于前两种注解方式实现的。
(3)IOC/DI依赖注入源码理解:(基于spring4.1.7)
重点理解两个过程:IoC容器初始化过程以及IoC容器依赖注入过程。
其实就是:资源定位、资源装载、资源解析、Bean生成,Bean注册、Bean依赖注入这几个过程(前五属于初始化过程)。方法:eclipse断点ClassPathXmlApplicationContext调用,不断跳进去,就看到spring执行栈了。
1. IoC容器初始化过程:
以上图思路进行详细讲述
初始化总过程:资源定位(确定工厂创建和bean的配置文件)--->资源装载(在文件系统路径上对IOC配置文件、bean配置进行加载)--->资源解析(解析bean配置,解析xml元素)--->生成bean(根据DOM资源解析成bean)--->在IoC容器中注册(交给IoC容器管理,还有依赖注入的权限)
整体过程大致如上图(从下往上看的栈,):保存配置,并刷新工厂-->创建载入BeanFactory-->创建XmlBeanDefinitionReader-->创建处理每一个Resource-->转换成Document对象-->处理XML每个元素-->解析注册bean
[一]资源定位:
追踪:我们可在此句获取工厂前设断点然后debug追踪进去,查看IoC的资源定位
ApplicationContext ctx = new ClassPathXmlApplicationContext("/spring/spring-*.xml");
然后一路跳进去:
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[]{configLocation}, true, (ApplicationContext)null);
}
/*
此处为资源定位核心调用层
*/
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
super(parent);//有前面类图 可 以知道,最终 父类 为AbstractApplicationContext
this.setConfigLocations(configLocations);//调用资源定位设置方法,然后我们跳进去寻找此方法位置,如下面代码
if(refresh) {//接着执行容器刷新方法
this.refresh();
}
}
//这个是追踪上去的ClassPathXmlApplicationContext父类
public AbstractXmlApplicationContext(ApplicationContext parent) {
super(parent);
}
//再追踪AbstractXmlApplicationContext的父类AbstractRefreshableConfigApplicationContext。然后它拥有了以下方法,从而
public void setConfigLocation(String location) {
this.setConfigLocations(StringUtils.tokenizeToStringArray(location, ",; \t\n"));
}
/*
资源定位方法
*/
public void setConfigLocations(String... locations) {
if(locations != null) {
Assert.noNullElements(locations, "Config locations must not be null");
this.configLocations = new String[locations.length];
// 该方法调用 SystemPropertyUtils.resolvePlaceholders(path) ;对 path 中的占位 符进行替换, eg : path 路径中含有 ${user.dir} ,则将替换为: System.getProperty(user.dir);
for(int i = 0; i < locations.length; ++i) {
this.configLocations[i] = this.resolvePath(locations[i]).trim();
}
} else {
this.configLocations = null;
}
}
根据资源定位核心调用层,我们可以看到他必执行AbstractApplicationContext中的refresh方法,执行容器刷新。部分叙述参考此博主此文章
public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
//加锁同步了
synchronized(this.startupShutdownMonitor) {
//调用容器准备刷新的方法,获取 容器的当时时间,同时给容器设置同步标识
this.prepareRefresh();
//告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从子类的refreshBeanFactory()方法启动
//并获取beanFactory
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
//为BeanFactory配置容器特性,例如类加载器、事件处理器等
this.prepareBeanFactory(beanFactory);
try {
//为容器的某些子类指定特殊的BeanPost事件处理器
this.postProcessBeanFactory(beanFactory);
//调用所有注册的BeanFactoryPostProcessor的Bean
this.invokeBeanFactoryPostProcessors(beanFactory);
//为BeanFactory注册BeanPost事件处理器.
//BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件
this.registerBeanPostProcessors(beanFactory);
//初始化信息源,和国际化相关.
this.initMessageSource();
//初始化容器事件传播器.
this.initApplicationEventMulticaster();
//调用子类的某些特殊Bean初始化方法
this.onRefresh();
//为事件传播器注册事件监听器.
this.registerListeners();
//初始化所有剩余的单态Bean.
this.finishBeanFactoryInitialization(beanFactory);
//初始化容器的生命周期事件处理器,并发布容器的生命周期事件
this.finishRefresh();
} catch (BeansException var5) {
//打印警告
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt", var5);
//销毁以创建的单态Bean
this.destroyBeans();
//取消refresh操作,重置容器的同步标识.
this.cancelRefresh(var5);
throw var5;
}
}
}
//获取工厂,让子类刷新内部 bean 工厂。
/*
关闭前面所有 bean 工厂,为新的上下文环境初始化一个新的 bean 工厂。这里需要子类来 协助完成资源位置定义 ,bean 载入和向 IOC 容器注册的过程
容器真正调用的是其子类AbstractRefreshableApplicationContext实现的 refreshBeanFactory()方法
见下方
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
this.refreshBeanFactory();//子类实现,调用子类的实现
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
if(this.logger.isDebugEnabled()) {
this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
AbstractRefreshableApplicationContext实现的refreshBeanFactory
/*
在这个方法中,先判断BeanFactory是否存在,如果存在则先销毁beans并关闭beanFactory,接着创建DefaultListableBeanFactory,并调用loadBeanDefinitions(beanFactory)装载bean
*/
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {//如果已经有容器,销 毁 容器中的bean,关闭容器
destroyBeans();
closeBeanFactory();
}
try {
//创建IoC容器
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
//对IoC容器进行定制化,如设置启动参数,开启注解的自动装配等
customizeBeanFactory(beanFactory);
//调用载入Bean定义的方法,主要这里使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
//为刷新准备上下文环境
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.active.set(true);
if(this.logger.isInfoEnabled()) {
this.logger.info("Refreshing " + this);
}
this.initPropertySources();
this.getEnvironment().validateRequiredProperties();
}
总的来说:资源定位做的就是:确定工厂位置,执行工厂初始化并刷新,建立好bean资源加载路径。等待bean资源装载。
[二]资源装载
设置工厂配置,刷新容器后,还要把我们的bean配置给资源加载器。
目标:拿到资源加载器,可以classpath:那样直接拿到资源装载。
在这之前,很有必要大家一起区分:不同类中的loadBeanDefinitions解析职责。
在AbstractXmlApplicationContext类中,职责为:对applicationContext.xml的解析操作,就是解析工厂的那个xml
在AbstractBeanDefinitionReader类中,职责为:从指定的资源加载bean定义,真正实现在其子类,这里是做了些兼容性错误处理。
在XmlBeanDefinitionReader类中,是AbstractBeanDefinitionReader的子类,而且是一个真正的实现类 ,是实现BeanDefinitionReader接口的loadBeanDefinitions(Resource var1) 等方法的关键解析类。职责为:读取并真正解析 xml 文件。
AbstractRefreshableApplicationContext中只定义了抽象的loadBeanDefinitions方法,容器真正调用的是其子类AbstractXmlApplicationContext对该方法的实现。(全局搜索SHIFT)
/*
!!!!资源装载以此为主线!!!这个是哪里的呢??AbstractXmlApplicationContext实现的
*/
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
//从beanfactory拿到reader
// 这里使用XMLBeanDefinitionReader来载入bean定义信息的XML文件
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//这里配置reader的环境,其中ResourceLoader是我们用来定位bean定义信息资源位置的
///因为上下文本身实现了ResourceLoader接口,所以可以直接把上下文作为ResourceLoader传递给XmlBeanDefinitionReader。容器本身也是一个资源加载器
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
//当Bean读取器读取Bean定义的Xml资源文件时,启用Xml的校验机制
this.initBeanDefinitionReader(beanDefinitionReader);
//这里转到定义好的XmlBeanDefinitionReader中对载入bean信息进行处理
this.loadBeanDefinitions(beanDefinitionReader);
}
由上面代码得知进入AbstractXmlApplicationContext的loadBeanDefinitions(XmlBeanDefinitionReader参数)
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
//获取Bean定义资源的定位
Resource[] configResources = this.getConfigResources();
//调用XmlBeanDefinitionReader来载入bean定义信息。 也就是AbstractBeanDefinitionReader类的loadBeanDefinitions去读取Bean资源
if(configResources != null) {
reader.loadBeanDefinitions(configResources);
}
//例子中使用了的是ClassPathXmlApplicationContext,所以跑下面的bean装载方法
String[] configLocations = this.getConfigLocations();
if(configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
接着根据上面继续追踪,到了AbstractBeanDefinitionReader类的loadBeanDefinitions方法
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
//这里得到当前定义的ResourceLoader,默认的 我 们 使用DefaultResourceLoader
ResourceLoader resourceLoader = this.getResourceLoader();
//如果没有找到我们需要的ResourceLoader,直接抛出异常
if(resourceLoader == null) {
throw new BeanDefinitionStoreException("Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
} else {
int loadCount;
if(!(resourceLoader instanceof ResourcePatternResolver)) {
// 这里处理我们在定义位置时使用的各种pattern,需要ResourcePatternResolver来完成
Resource resource = resourceLoader.getResource(location);
loadCount = this.loadBeanDefinitions((Resource)resource);
if(actualResources != null) {
actualResources.add(resource);
}
return loadCount;
} else {
try {
// 这里通过ResourceLoader来完成位置定位
Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);
// 这里已经把一个位置定义转化为Resource接口,可以供XmlBeanDefinitionReader来使用了
loadCount = this.loadBeanDefinitions(resources);
if(actualResources != null) {
Resource[] var6 = resources;
int var7 = resources.length;
for(int var8 = 0; var8 < var7; ++var8) {
Resource resource = var6[var8];
actualResources.add(resource);
}
}
if(this.logger.isDebugEnabled()) {
this.logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
} catch (IOException var10) {
throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", var10);
}
}
}
}
所以,AbstractBeanDefinitionReader的loadBeanDefinitions方法源码分析可以看出该方法做了以下两件事:
(1)首先,调用资源加载器的获取资源方法resourceLoader.getResource(location),获取到要加载的资源。
(2)其次,真正执行加载功能是其子类XmlBeanDefinitionReader实现的loadBeanDefinitions方法。
另外,此时调用的是DefaultResourceLoader中的getSource()方法定位Resource。
然后我们再仔细看下各个类想拿到资源加载器就是通过getResourceLoader,拿到AbstractBeanDefinitionReader类定义的resourceLoader。这样的话,我们可通过此方式在工程spring下的任何地方拿到资源加载器,“随处加载”了。
public interface ResourceLoader {
String CLASSPATH_URL_PREFIX = "classpath:";
Resource getResource(String var1);//拿到资源
ClassLoader getClassLoader();//拿到类加载器
}
总的来说,资源装载就是:根据之前确定好的bean资源配置路径,拿到资源、拿到加载器,并把bean配置丢进XmlBeanDefinitionReader。等待Bean资源解析。
[三]Bean资源解析:其实就是刚我们遇到的XmlBeanDefinitionReader类啦。真正去解析xml。解析的关注重心请注意到doLoadBeanDefinitions方法,从这里进行分发。从而到下一部生成bean对象。
目标:将XML文件转为DOM对象。进而交DocumentLoader和DocumentBuilderFactory处理dom对象给doLoadBeanDefinitions方法,从而为bean生成作铺垫
//这里是载入XML形式Bean定义资源文件方法
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());
}
//获取当前的线程变量,它是用于保存处理的resource的
Set<EncodedResource> currentResources = (Set)this.resourcesCurrentlyBeingLoaded.get();
if(currentResources == null) {
currentResources = new HashSet(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);//保存当前的resource
}
if(!((Set)currentResources).add(encodedResource)) {
throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");
} else {
int var5;
try {
//将资源文件转为InputStream的IO流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
//从InputStream中得到XML的解析源
InputSource inputSource = new InputSource(inputStream);
if(encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
//这里是具体的读取过程
var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
} finally {
//关闭从Resource中得到的IO流
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;
}
}
//从特定XML文件中实际载入Bean定义资源的方法 ,就是转成dom对象后交给这里去进一步处理从而转换出bean
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
try {
//将XML文件转换为DOM对象,解析过程由documentLoader实现
Document doc = this.doLoadDocument(inputSource, resource);
//这里是启动对Bean定义解析的详细过程,该解析过程会用到Spring的Bean配置规则
return this.registerBeanDefinitions(doc, resource);
} catch (BeanDefinitionStoreException var4) {
throw var4;
} catch (SAXParseException var5) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + var5.getLineNumber() + " in XML document from " + resource + " is invalid", var5);
} catch (SAXException var6) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", var6);
} catch (ParserConfigurationException var7) {
throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, var7);
} catch (IOException var8) {
throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, var8);
} catch (Throwable var9) {
throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, var9);
}
}
然后沿着doLoadDocument继续追踪,追踪到一个接口DocumentLoader和一个实现类DefaultDocumentLoader。以下是DefaultDocumentLoader这个实现类的部分代码
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver, ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
//创建文件解析器工厂
DocumentBuilderFactory factory = this.createDocumentBuilderFactory(validationMode, namespaceAware);
if(logger.isDebugEnabled()) {
logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
}
//创建文档解析器
DocumentBuilder builder = this.createDocumentBuilder(factory, entityResolver, errorHandler);
//解析Spring的Bean定义资源
return builder.parse(inputSource);
}
//再根据上面方法追踪到它也执行了本类的一个方法:
//调用了Javaee的JAXP标准,根据定位的Bean定义资源文件,加载读入并转换成为Document对象过程完成
protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory, EntityResolver entityResolver, ErrorHandler errorHandler) throws ParserConfigurationException {
DocumentBuilder docBuilder = factory.newDocumentBuilder();
if(entityResolver != null) {
docBuilder.setEntityResolver(entityResolver);
}
if(errorHandler != null) {
docBuilder.setErrorHandler(errorHandler);
}
return docBuilder;
}
总的来说:Bean资源解析就是,先通过 XML解析器讲Bean定义资源文件转换得到Document对象,但是这堆Document对象没有按照spring的Bean规则的,所以不可直接转换成bean对象。然后完成XML解析变成Document对象后,就调用spring的解析方法按照Spring的Bean规则去对Document进行解析,生成Bean对象。
[四]生成Bean:还是关注XmlBeanDefinitionReader类的doLoadBeanDefinitions方法,他进行了一个调用:registerBeanDefinitions。
//按照Spring的Bean语义要求 将Bean 定 义 资源解析并转换为容器内部数据结构
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//得到BeanDefinitionDocumentReader来对xml格式的BeanDefinition解析
BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();
//读取环境的配置设置
documentReader.setEnvironment(this.getEnvironment());
//获得容器中注册的Bean数量
int countBefore = this.getRegistry().getBeanDefinitionCount();
//解析过程入口,这里使用了委派模式,BeanDefinitionDocumentReader只是个接口,//具体的解析实现过程有实现类DefaultBeanDefinitionDocumentReader完成
documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
//统计解析的Bean数量
return this.getRegistry().getBeanDefinitionCount() - countBefore;
}
//在此方法真正去转化document对象成为bean
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
return (BeanDefinitionDocumentReader)BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
}
接下来就是document元素的一个个解析,然后转化成bean对象了。我们根据上面的解析入口可以追踪到 BeanDefinitionDocumentReader接口的实现类DefaultBeanDefinitionDocumentReader。在这个类进行详细的document元素解析成我们平常工程用的bean。但本博主不打算继续看了,因为对我们掌握spring的IOC原理并不影响。
[五]在IoC容器注册解析生成的Bean:
目标:到IoC容器注册
我们能猜到他在类DefaultBeanDefinitionDocumentReader生成bean后必然会丢给IoC容器去注册,交给它管理。但是我们怎么找到呢??根据上面生成bean中的解析入口,我们CTRL+F查registerBeanDefinitions。
再进一步追踪到parseDefaultElement方法,可以看到这里就是识别主标签,从而进行解析生成bean。
/*
根据标签去选择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);
} else if(delegate.nodeNameEquals(ele, "beans")) {
this.doRegisterBeanDefinitions(ele);
}
}
//进入解析和注册分发啦
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if(bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
//注册分发: 继续追踪
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));
}
}
//终于找到你了,注册!!
//BeanDefinitionReaderUtils类的
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
//得到需要 注册 的 bean名字
String beanName = definitionHolder.getBeanName();
//开始注册。锁定registerBeanDefinition方法
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 别名也是可以 通过IOC容器和bean联系起来的进行注册
String[] aliases = definitionHolder.getAliases();
if(aliases != null) {
String[] var4 = aliases;
int var5 = aliases.length;
for(int var6 = 0; var6 < var5; ++var6) {
String alias = var4[var6];
registry.registerAlias(beanName, alias);
}
}
}
//锁定registerBeanDefinition方法后,然而我们发现的是一个接口BeanDefinitionRegistry,因此我们必须找到他的实现类,但是我们却只是发现很多他的抽象类AbstractAutowireCapableBeanFactory、AbstractBeanFactory、FactoryBeanRegistrySupport、DefaultSingletonBeanRegistry等等(感慨编写spring大佬的心累(我找得更累!!))
终于找到非抽象实现类啦:DefaultListableBeanFactory(其实我当时查的快疯,是查他的继承树才查到这个的。)
使用一个HashMap的集合对象存放IoC容器中注册解析的BeanDefinition
//~~~!!!实现了BeanDefinitionRegistry接口
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
//一堆验证beanDefinition的正确性
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 var4) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var4);
}
}
//先看看在容器里是不是已经有了同名的bean,如果有抛出异常。
BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
if(oldBeanDefinition != null) {
if(!this.isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound.");
}
if(oldBeanDefinition.getRole() < beanDefinition.getRole()) {
if(this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-define d bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else if(this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName + "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else {
//没重复就把bean的名字加到IOC容器中去
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
this.frozenBeanDefinitionNames = null;
}
//这里把bean的名字和Bean定义联系起来放到一个HashMap中去,IOC容器通过这个Map来维护容器里的Bean定义信息。
this.beanDefinitionMap.put(beanName, beanDefinition);
if(oldBeanDefinition != null || this.containsSingleton(beanName)) {
this.resetBeanDefinition(beanName);
}
}
总的来说就是:把beandefinition丢给工厂用hashmap存好。
IOC容器初始化总结:
(1)通过setConfigLocations载入spring配置文件;
(2)初始化容器入口通过refresh方法,进入AbstractApplicationContext实现的refresh方法。
(3)然后通过obtainFreshBeanFactory方法进入子类AbstractRefreshableApplicationContext实现的refreshBeanFactory刷新一个容器工厂
(4)在此创建了DefaultListableBeanFactory类,并调用loadBeanDefinitions(beanFactory)装载bean定义
(5)接着以AbstractRefreshableApplicationContext为中心回到此类,进入其子类AbstractXmlApplicationContext实现的loadBeanDefinitions方法。对applicationContext.xml的解析操作,就是解析工厂的那个xml。
(6)再接着通过AbstractXmlApplicationContext的loadBeanDefinitions进入到AbstractBeanDefinitionReader类的loadBeanDefinitions。通过获取资源方法resourceLoader.getResource(location),获取到要加载的资源。再真正执行加载功能是其子类XmlBeanDefinitionReader实现的loadBeanDefinitions方法。
(6)接着进入XmlBeanDefinitionReader中的loadBeanDefinitions。(XmlBeanDefinitionReader通过调用其父类中调用的DefaultResourceLoader的getResource方法获取要加载的资源)DocumentLoader将Bean定义资源转换成Document对象。
(7)doLoadBeanDefinitions中进入DefaultBeanDefinitionDocumentReader类的registerBeanDefinitions 解 析 D ocument对象
(8)解析完后,调用DefaultListableBeanFactory类中使用一个HashMap的集合对象存放IoC容器中注册解析的BeanDefinition
2.IoC容器依赖注入过程:
[ 一 ]先来读懂beanfactory的继承逻辑树
类图。我们根据DefaultListableBeanFactory继续追踪上去。一会详讲此逻辑线。参考此博主此文章,非常感谢他,写得太棒了。让我学到很多。
先来读懂它beanfactory的继承树逻辑线。图取自此文章
解析上图:
BeanFactory是Spring的最根的接口,类的工厂接口。HierarchicalBeanFactory接口是在继承BeanFactory的基础上,实现BeanFactory的父子关系。Hierarchical表示的是这些 Bean 是有继承关系的,也就是每个 Bean 有可能有父 Bean。
AutowireCapableBeanFactory接口是在继承BeanFactory的基础上,实现Bean的自动装配功能。定义 Bean 的自动装配规则。
ListableBeanFactory接口是在继承BeanFactory的基础上,实现Bean的list集合操作功能。表示这些 Bean 是可列表的。
ConfigurableBeanFactory接口是在继承HierarchicalBeanFactory的基础上,实现BeanFactory的全部配置管理功能, SingletonBeanRegistry是单例bean的注册接口
ConfigurableListableBeanFactory接口是继承AutowireCapableBeanFactory,ListableBeanFactory,ConfigurableBeanFactory三个接口的一个综合接口。
AliasRegistry接口是别名注册接口,SimpleAliasRegistry类是简单的实现别名注册接口的类。
DefaultSingletonBeanRegistry是默认的实现SingletonBeanRegistry接口的类,同时,继承类SimpleAliasRegistry 。
FactoryBeanRegistrySupport是实现FactoryBean注册的功能实现。继承类DefaultSingletonBeanRegistry 。负责FactoryBean相关的操作,并缓存FactoryBean的getObject实例化的bean. 判断factory是单例,同时已经new好了单例时,先尝试去缓存找;如果找不到或者不是单例,委托doGetObjectFromFactoryBean实例化一个。
AbstractBeanFactory是部分实现接口ConfigurableBeanFactory,并继承类FactoryBeanRegistrySupport 。这个是最顶层的抽象IOC容器空构造器,主要用来具体实现了BeanFactory接口。
AbstractAutowireCapableBeanFactory是实现接口AutowireCapableBeanFactory,并继承类 AbstractBeanFactory 。主要的功能就是实现了默认的bean创建方法createBean().而在这个创建过程中,提供了诸如bean的属性注入,初始化方法的调用,自动装配的实现,bean处理器的调用。
DefaultListableBeanFactory实现接口 ConfigurableListableBeanFactory、BeanDefinitionRegistry(bean定义的注册接口), 并继承AbstractAutowireCapableBeanFactory,实现全部类管理的功能。
可以看出DefaultListableBeanFactory就是springIoC机制的入口。
[二]IoC容器依赖注入源码详讲:上面可知我们从实现BeanFactory的AbstractBeanFactory入手
1.我们从DefaultListableBeanFactory开始不断追踪父类,直到找到了AbstractBeanFactory。
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
//真正实现向IoC容器获取Bean的功能,也是触发依赖注入功能的地方
protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
//根据指定的名称获取被管理Bean的名称,剥离指定名称中对容器的相关依赖
//如果指定的是别名,将别名转换为规范的Bean名称
final String beanName = this.transformedBeanName(name);
Object sharedInstance = this.getSingleton(beanName);
Object bean;
//IoC容器创建单态模式Bean实例对象
if(sharedInstance != null && args == null) {
if(this.logger.isDebugEnabled()) {
//如果指定名称的Bean在容器中已有单态模式的Bean被创建,直接返回
//已经有创建的Bean
if(this.isSingletonCurrentlyInCreation(beanName)) {
this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//获取给定Bean的实例对象,主要是完成FactoryBean的相关处理
//注意:BeanFactory是管理容器中Bean的工厂,而FactoryBean是
//创建创建对象的工厂Bean,两者之间有区别
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
//缓存没有正在创建的单态模式Bean
//缓存中已经有已经创建的原型模式Bean,但是由于循环引用的问题导致实
//例化对象失败
if(this.isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//对IoC容器中是否存在指定名称的BeanDefinition进行检查,首先检查是否
//能在当前的BeanFactory中获取的所需要的Bean,如果不能则委托当前容器
//的父级容器去查找,如果还是找不到则沿着容器的继承体系向父级容器查找
BeanFactory parentBeanFactory = this.getParentBeanFactory();
//当前容器的父级容器存在,且当前容器中不存在指定名称的Bean
if(parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
//解析指定Bean名称的原始名称
String nameToLookup = this.originalBeanName(name);
if(args != null) {
//委派父级容器根据指定名称和显式的参数查找
return parentBeanFactory.getBean(nameToLookup, args);
}
//委派父级容器根据指定名称和类型查找
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
//创建的Bean是否需要进行类型验证,一般不需要
if(!typeCheckOnly) {
//向容器标记指定的Bean已经被创建
this.markBeanAsCreated(beanName);
}
try {
//根据指定Bean名称获取其父级的Bean定义,主要解决Bean继承时子类
//合并父类公共属性问题
final RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
this.checkMergedBeanDefinition(mbd, beanName, args);
//获取当前Bean所有依赖Bean的名称
String[] dependsOn = mbd.getDependsOn();
String[] var11;//用来暂存dependsOn ,用var11来循环
//如果当前Bean有依赖Bean
if(dependsOn != null) {
var11 = dependsOn;
int var12 = dependsOn.length;
for(int var13 = 0; var13 < var12; ++var13) {
//递归调用getBean方法,获取当前Bean的依赖Bean
String dependsOnBean = var11[var13];
if(this.isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
}
//把被依赖Bean注册给当前依赖的Bean
this.registerDependentBean(dependsOnBean, beanName);
this.getBean(dependsOnBean);
}
}
//创建单态模式Bean的实例对象
if(mbd.isSingleton()) {
//这里使用了一个匿名内部类,创建Bean实例对象,并且注册给所依赖的对象
sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
//创建一个指定Bean实例对象,如果有父级继承,则合并子类和父类的定义!!!!!就是在此再次分发到创建bean的实现方法
return AbstractBeanFactory.this.createBean(beanName, mbd, args);
} catch (BeansException var2) {
//显式地从容器单态模式Bean缓存中清除实例对象
AbstractBeanFactory.this.destroySingleton(beanName);
throw var2;
}
}
});
//获取给定Bean的实例对象
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if(mbd.isPrototype()) { //IoC容器创建原型模式Bean实例对象
var11 = null;
Object prototypeInstance;//原型模式(Prototype)是每次都会创建一个新的对象
try {
//回调beforePrototypeCreation方法,默认的功能是注册当前创//建的原型对象
this.beforePrototypeCreation(beanName);
//创建指定Bean对象实例
prototypeInstance = this.createBean(beanName, mbd, args);
} finally {
//回调afterPrototypeCreation方法,默认的功能告诉IoC容器指//定Bean的原型对象不再创建了
this.afterPrototypeCreation(beanName);
}
//获取给定Bean的实例对象
bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
//要创建的Bean既不是单态模式,也不是原型模式,则根据Bean定义资源中
//配置的生命周期范围,选择实例化Bean的合适方法,这种在Web应用程序中
//比较常用,如:request、session、application等生命周期
String scopeName = mbd.getScope();
Scope scope = (Scope)this.scopes.get(scopeName);
//Bean定义资源中没有配置生命周期范围,则Bean定义不合法
if(scope == null) {
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}
try {
//这里又使用了一个匿名内部类,获取一个指定生命周期范围的实例
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
AbstractBeanFactory.this.beforePrototypeCreation(beanName);
Object var1;
try {
var1 = AbstractBeanFactory.this.createBean(beanName, mbd, args);
} finally {
AbstractBeanFactory.this.afterPrototypeCreation(beanName);
}
return var1;
}
});
//获取给定Bean的实例对象
bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException var21) {
throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; " + "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", var21);
}
}
} catch (BeansException var23) {
this.cleanupAfterBeanCreationFailure(beanName);
throw var23;
}
}
//对创建的Bean实例对象进行类型检查
if(requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return this.getTypeConverter().convertIfNecessary(bean, requiredType);
} catch (TypeMismatchException var22) {
if(this.logger.isDebugEnabled()) {
this.logger.debug("Failed to convert bean '" + name + "' to required type [" + ClassUtils.getQualifiedName(requiredType) + "]", var22);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
} else {
return bean;
}
}
}
我们可以很清晰看到,创建bean的时候所做的判断:
(1)如果Bean定义的单态模式(Singleton),则容器在创建之前先从缓存中查找,以确保整个容器中只存在一个实例对象
(2) 如果Bean定义的是原型模式(Prototype),则容器每次都会创建一个新的实例对象。
(3)两者都不是,则根据Bean定义资源中配置的生命周期范围,选择实例化Bean的合适方法,这种在Web应用程序中 比较常用,如:request、session、application等生命周期。
上面的源码只是定义了根据Bean定义的模式,采取的不同创建Bean实例对象的策略,具体的Bean实例对象的创建过程由实现了ObejctFactory接口的匿名内部类的createBean方法完成,ObejctFactory使用委派模式,具体的Bean实例创建过程交由其实现类AbstractAutowireCapableBeanFactory完成,我们继续分析AbstractAutowireCapableBeanFactory的createBean方法的源码,理解其创建Bean实例的具体实现过程
2.因此我们根据上面所述继续追踪,现追踪AbstractBeanFactory的一个匿名内部类的createBean方法,实际上这方法的实现就是在我们从DefaultListableBeanFactory追踪父类过来的途中遇到的AbstractAutowireCapableBeanFactory类,是AbstractBeanFactory子类。
//创建Bean实 例对象
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if(this.logger.isDebugEnabled()) {
this.logger.debug("Creating instance of bean '" + beanName + "'");
}
//判断需要创建的Bean是否可以实例化,即是否可以通过当前的类加载器加载
this.resolveBeanClass(mbd, beanName, new Class[0]);
//校验和准备Bean中的方法覆盖
try {
mbd.prepareMethodOverrides();
} catch (BeanDefinitionValidationException var5) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "Validation of method overrides failed", var5);
}
Object beanInstance;
try {
//如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建
//Bean的代理对象
beanInstance = this.resolveBeforeInstantiation(beanName, mbd);
if(beanInstance != null) {
return beanInstance;
}
} catch (Throwable var6) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var6);
}
//真正创建Bean的入口
beanInstance = this.doCreateBean(beanName, mbd, args);
if(this.logger.isDebugEnabled()) {
this.logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
//真正创建bean的方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) {
//封装被创建的Bean对象
BeanWrapper instanceWrapper = null;
if(mbd.isSingleton()) {//单态模式的Bean,先从容器中缓存中获取同名Bean
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
//容器没有的话
if(instanceWrapper == null) {
//创建实例对象
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper != null?instanceWrapper.getWrappedInstance():null;
//获取实例化对象的类型
Class<?> beanType = instanceWrapper != null?instanceWrapper.getWrappedClass():null;
Object var7 = mbd.postProcessingLock;
//调用PostProcessor后置处理器
synchronized(mbd.postProcessingLock) {
if(!mbd.postProcessed) {
this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed = true;
}
}
//向容器中缓存单态模式的Bean对象,以防循环引用
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if(earlySingletonExposure) {
if(this.logger.isDebugEnabled()) {
this.logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
}
//这里是一个匿名内部类,为了防止循环引用,尽早持有对象的引用
this.addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return AbstractAutowireCapableBeanFactory.this.getEarlyBeanReference(beanName, mbd, bean);
}
});
}
//Bean对象的初始化,依赖注入在此触发
//这个exposedObject在初始化完成之后返回作为依赖注入完成后的Bean
Object exposedObject = bean;
try {
//将Bean实例对象封装,并且Bean定义中配置的属性值赋值给实例对象
this.populateBean(beanName, mbd, instanceWrapper);
if(exposedObject != null) {
//初始化Bean对象
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
}
} catch (Throwable var17) {
if(var17 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var17).getBeanName())) {
throw (BeanCreationException)var17;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var17);
}
if(earlySingletonExposure) {
//获取指定名称的已注册的单态模式Bean对象
Object earlySingletonReference = this.getSingleton(beanName, false);
if(earlySingletonReference != null) {
//根据名称获取的以注册的Bean和正在实例化的Bean是同一个
if(exposedObject == bean) {
//当前实例化的Bean初始化完成
exposedObject = earlySingletonReference;
} else if(!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {//当前Bean依赖其他Bean,并且当发生循环引用时不允许新创建实例对象
String[] dependentBeans = this.getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
String[] var12 = dependentBeans;//用来暂存当前bean
int var13 = dependentBeans.length;
//获取当前Bean所依赖的其他Bean
for(int var14 = 0; var14 < var13; ++var14) {
String dependentBean = var12[var14];
//对依赖Bean进行类型检查
if(!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if(!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
//注册完成依赖注入的Bean
try {
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
} catch (BeanDefinitionValidationException var16) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
}
}
上面还是一堆校验以及状态判断。
其中真正实现是分发到:
createBeanInstance:生成Bean所包含的Java对象实例。
populateBean :对Bean属性的依赖注入进行处理。
3.那么我们来看下createBeanInstance方法的代码,还是在AbstractAutowireCapableBeanFactory类中。
在此方法中,根据指定的初始化策略,使用静态工厂、工厂方法或者容器的自动装配特性生成java实例对象。
//创建Bean的实例对象
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
//检查确认Bean是可实例化的
Class<?> beanClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
//使用工厂方法对Bean进行实例化
if(beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
} else if(mbd.getFactoryMethodName() != null) {
//调用工厂方法实例化
return this.instantiateUsingFactoryMethod(beanName, mbd, args);
} else { //使用容器的自动装配方法进行实例化
boolean resolved = false;
boolean autowireNecessary = false;
if(args == null) {
Object var7 = mbd.constructorArgumentLock;
synchronized(mbd.constructorArgumentLock) {
if(mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
//决定是否使用自动装配的构造器
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
//autowireConstructor构造器方法配置了自动装配属性,使用容器的自动装配实例化,容器的自动装配是根据参数类型匹配Bean的构造方法
if(resolved) {
//根据标记位autowireNecessary而决定采用无参构造器还是自动装配构造器
return autowireNecessary?this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null):this.instantiateBean(beanName, mbd);
} else {
//使用Bean的构造方法进行实例化
Constructor<?>[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
//根据是否有参数还是已经配置了自动装配模式,去选择构造器,无参构造器还是自动装配构造器。
return ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args)?this.instantiateBean(beanName, mbd):this.autowireConstructor(beanName, mbd, ctors, args);
}
}
}
上面看到一个无参构造器:instantiateBean
//使用默认的无参构造方法实例化Bean对象
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
//获取系统的安全管理接口,JDK标准的安全管理API
if(System.getSecurityManager() != null) {
//这里是一个匿名内置类,根据实例化策略创建实例对象
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
return AbstractAutowireCapableBeanFactory.this.getInstantiationStrategy().instantiate(mbd, beanName, AbstractAutowireCapableBeanFactory.this);
}
}, this.getAccessControlContext());
} else {
//将实例化的对象封装起来
beanInstance = this.getInstantiationStrategy().instantiate(mbd, beanName, this);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
this.initBeanWrapper(bw);
return bw;
} catch (Throwable var6) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", var6);
}
}
4.我们都看到了,无论什么调用什么构造器,返回的都是统一的BeanWrapper
BeanWrapper是什么贵?org.springframework.beans.BeanWrapper是Spring框架中重要的组件类。BeanWrapper相当于一个代理器,Spring通过BeanWrapper完成Bean属性的填充工作。在Bean实例被InstantiationStrategy创建出来之后,容器主控程序将Bean实例通过BeanWrapper包装起来。
由于它是接口,必然有个实现类,实现依赖注入的具体实现。那就是BeanWrapperImpl,它的作用是:(1)Bean包裹器;(2)属性访问器;(3)属性编辑器注册表。
5.我们接着回到createBean,它还有个实现分发populateBean 方法:对Bean属性的依赖注入进行处理
过程是两部分:属性值解析和注入
//将Bean属性设置到生成的实例对象上
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
//获取容器在解析Bean定义资源时为BeanDefiniton中设置的属性值
PropertyValues pvs = mbd.getPropertyValues();
//实例对象为null
if(bw == null) {
//属性值不为空
if(!((PropertyValues)pvs).isEmpty()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
} else {
//在设置属性之前调用Bean的PostProcessor后置处理器
boolean continueWithPropertyPopulation = true;
if(!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
Iterator var6 = this.getBeanPostProcessors().iterator();
while(var6.hasNext()) {
BeanPostProcessor bp = (BeanPostProcessor)var6.next();
if(bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
if(!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
//依赖注入开始,首先处理autowire自动装配的注入
if(continueWithPropertyPopulation) {
if(mbd.getResolvedAutowireMode() == 1 || mbd.getResolvedAutowireMode() == 2) {
MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
//对autowire自动装配的处理,根据Bean名称自动装配注入
if(mbd.getResolvedAutowireMode() == 1) {
this.autowireByName(beanName, mbd, bw, newPvs);
}
//根据Bean类型自动装配注入
if(mbd.getResolvedAutowireMode() == 2) {
this.autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
//检查容器是否持有用于处理单态模式Bean关闭时的后置处理器
boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
//Bean实例对象没有依赖,即没有继承基类
boolean needsDepCheck = mbd.getDependencyCheck() != 0;
if(hasInstAwareBpps || needsDepCheck) {
//从实例对象中提取属性描述符
PropertyDescriptor[] filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if(hasInstAwareBpps) {
Iterator var9 = this.getBeanPostProcessors().iterator();
while(var9.hasNext()) {
BeanPostProcessor bp = (BeanPostProcessor)var9.next();
if(bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
//使用BeanPostProcessor处理器处理属性值
pvs = ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
if(pvs == null) {
return;
}
}
}
}
if(needsDepCheck) {
//为要设置的属性进行依赖检查
this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);
}
}
//对属性进行注入 ,解析并注入依赖属性的过程 就在这个方法里面
/*
属性转换也有两情况:
1.属性值类型不需要转换时,不需要解析属性值,直接准备进行依赖注入。
2.属性值需要进行类型转换时,如对其他对象的引用等,首先需要解析属性值,然后对解析后的属性值进行依赖注入。
*/
this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
}
}
}
6.那么我们继续追踪applyPropertyValues方法
//解析并注入依赖属性的过程
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if(pvs != null && !pvs.isEmpty()) {
//封装属性值
MutablePropertyValues mpvs = null;
if(System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
//设置安全上下文,JDK安全机制
((BeanWrapperImpl)bw).setSecurityContext(this.getAccessControlContext());
}
List original;
if(pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues)pvs;
//属性值已经转换
if(mpvs.isConverted()) {
try {
//为实例化对象设置属性值 ,依赖注入真真正正地实现在此!!!!!
bw.setPropertyValues(mpvs);
return;
} catch (BeansException var18) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", var18);
}
}
//获取属性值对象的原始类型值
original = mpvs.getPropertyValueList();
} else {
original = Arrays.asList(pvs.getPropertyValues());
}
//获取用户自定义的类型转换
TypeConverter converter = this.getCustomTypeConverter();
if(converter == null) {
converter = bw;
}
//创建一个Bean定义属性值解析器,将Bean定义中的属性值解析为Bean实例对象
//的实际值
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, (TypeConverter)converter);
//为属性的解析值创建一个拷贝,将拷贝的数据注入到实例对象中
List<PropertyValue> deepCopy = new ArrayList(original.size());
boolean resolveNecessary = false;
Iterator var11 = original.iterator();//用迭代器去遍历
while(true) {
while(var11.hasNext()) {
PropertyValue pv = (PropertyValue)var11.next();
//属性值不需要转换
if(pv.isConverted()) {
deepCopy.add(pv);
} else {//属性值需要转换
String propertyName = pv.getName();
//原始的属性值,即转换之前的属性值
Object originalValue = pv.getValue();
//转换属性值,例如将引用转换为IoC容器中实例化对象引用 !!!!! 对属性值的解析!!
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
//转换之后的属性值
Object convertedValue = resolvedValue;
//属性值是否可以转换
boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if(convertible) {
//使用用户自定义的类型转换器转换属性值
convertedValue = this.convertForProperty(resolvedValue, propertyName, bw, (TypeConverter)converter);
}
//存储转换后的属性值,避免每次属性注入时的转换工作
if(resolvedValue == originalValue) {
if(convertible) {
//设置属性转换之后的值
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
//属性是可转换的,且属性原始值是字符串类型,且属性的原始类型值不是
//动态生成的字符串,且属性的原始值不是集合或者数组类型
else if(convertible && originalValue instanceof TypedStringValue && !((TypedStringValue)originalValue).isDynamic() && !(convertedValue instanceof Collection) && !ObjectUtils.isArray(convertedValue)) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
} else {
resolveNecessary = true;
//重新封装属性的值
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
if(mpvs != null && !resolveNecessary) {
//标记属性值已经转换过
mpvs.setConverted();
}
//进行属性依赖注入 ,依赖注入的真真正正实现依赖的注入方法在此!!!
try {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
return;
} catch (BeansException var19) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", var19);
}
}
}
}
总结applyPropertyValues方法(完成属性转换):
属性值类型不需要转换时,不需要解析属性值,直接准备进行依赖注入。
属性值需要进行类型转换时,如对其他对象的引用等,首先需要解析属性值,然后对解析后的属性值进行依赖注入。
而且我们看到调用了resolveValueIfNecessary方法对属性值的解析
7.追踪resolveValueIfNecessary,发现是在BeanDefinitionValueResolver类
当容器在对属性进行依赖注入时,如果发现属性值需要进行类型转换,如属性值是容器中另一个Bean实例对象的引用,则容器首先需要根据属性值解析出所引用的对象,然后才能将该引用对象注入到目标实例对象的属性上去,对属性进行解析的由resolveValueIfNecessary方法实现。
可知:创建与注入是个递归的过程
//解析属性值,对注入类型进行转换
public Object resolveValueIfNecessary(Object argName, Object value) {
//对引用类型的属性进行解析
if(value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference)value;
//调用引用类型属性的解析方法
return this.resolveReference(argName, ref);
} else if(value instanceof RuntimeBeanNameReference) { //对属性值是引用容器中另一个Bean名称的解析
String refName = ((RuntimeBeanNameReference)value).getBeanName();
refName = String.valueOf(this.doEvaluate(refName));
//从容器中获取指定名称的Bean
if(!this.beanFactory.containsBean(refName)) {
throw new BeanDefinitionStoreException("Invalid bean name '" + refName + "' in bean reference for " + argName);
} else {
return refName;
}
} else if(value instanceof BeanDefinitionHolder) { //对Bean类型属性的解析,主要是Bean中的内部类
BeanDefinitionHolder bdHolder = (BeanDefinitionHolder)value;
return this.resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
} else if(value instanceof BeanDefinition) {
BeanDefinition bd = (BeanDefinition)value;
String innerBeanName = "(inner bean)#" + ObjectUtils.getIdentityHexString(bd);
return this.resolveInnerBean(argName, innerBeanName, bd);
} else if(value instanceof ManagedArray) {//对集合数组类型的属性解析
ManagedArray array = (ManagedArray)value;
//获取数组的类型
Class<?> elementType = array.resolvedElementType;
if(elementType == null) {
//获取数组元素的类型
String elementTypeName = array.getElementTypeName();
if(StringUtils.hasText(elementTypeName)) {
try {
//使用反射机制创建指定类型的对象
elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
array.resolvedElementType = elementType;
} catch (Throwable var9) {
throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Error resolving array type for " + argName, var9);
}
} else {
//没有获取到数组的类型,也没有获取到数组元素的类型,则直接设置数
//组的类型为Object
elementType = Object.class;
}
}
//创建指定类型的数组
return this.resolveManagedArray(argName, (List)value, elementType);
} else if(value instanceof ManagedList) {//解析list类型的属性值
return this.resolveManagedList(argName, (List)value);
} else if(value instanceof ManagedSet) { //解析set类型的属性值
return this.resolveManagedSet(argName, (Set)value);
} else if(value instanceof ManagedMap) { //解析map类型的属性值
return this.resolveManagedMap(argName, (Map)value);
} else if(value instanceof ManagedProperties) { //解析props类型的属性值,props其实就是key和value均为字符串的map
Properties original = (Properties)value;
//创建一个拷贝,用于作为解析后的返回值
Properties copy = new Properties();
Object propKey;
Object propValue;
for(Iterator var19 = original.entrySet().iterator(); var19.hasNext(); copy.put(propKey, propValue)) {
Entry<Object, Object> propEntry = (Entry)var19.next();
propKey = propEntry.getKey();
propValue = propEntry.getValue();
if(propKey instanceof TypedStringValue) {
propKey = this.evaluate((TypedStringValue)propKey);
}
if(propValue instanceof TypedStringValue) {
propValue = this.evaluate((TypedStringValue)propValue);
}
}
return copy;
} else if(value instanceof TypedStringValue) {//解析字符串类型的属性值
TypedStringValue typedStringValue = (TypedStringValue)value;
Object valueObject = this.evaluate(typedStringValue);
try {
//获取属性的目标类型
Class<?> resolvedTargetType = this.resolveTargetType(typedStringValue);
//对目标类型的属性进行解析,递归调用 。没有获取到属性的目标对象,则按Object类型返回
return resolvedTargetType != null?this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType):valueObject;
} catch (Throwable var10) {
throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Error converting typed String value for " + argName, var10);
}
} else {
return this.evaluate(value);
}
}
刚也说了解析引用类型是特殊的:resolveReference方法
//解析引用类型的属性值
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
//获取引用的Bean名称
String refName = ref.getBeanName();
refName = String.valueOf(this.doEvaluate(refName));
//如果引用的对象在父类容器中,则从父类容器中获取指定的引用对象
if(ref.isToParent()) {
if(this.beanFactory.getParentBeanFactory() == null) {
throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Can't resolve reference to bean '" + refName + "' in parent factory: no parent factory available");
} else {
return this.beanFactory.getParentBeanFactory().getBean(refName);
}
} else {
//从当前的容器中获取指定的引用Bean对象,如果指定的Bean没有被实例化
//则会递归触发引用Bean的初始化和依赖注入
Object bean = this.beanFactory.getBean(refName);
//将当前实例化对象的依赖引用对象
this.beanFactory.registerDependentBean(refName, this.beanName);
return bean;
}
} catch (BeansException var5) {
throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, var5);
}
}
8.并且我们注意到applyPropertyValues方法(刚刚的AbstractAutowireCapableBeanFactory类)中,分发了一个方法实现对属性值的依赖注入setPropertyValues
前面也说到BeanWrapper接口的实现类就是BeanWrapperImpl。一系列的依赖注入都在这个里面,那么我们往上查找PropertyAccessor接口,并且发现路过的抽象类AbstractPropertyAccessor,终于找到了setPropertyValues方法的实现,有个模板模式,就是调用在AbstractPropertyAccessor中的抽象方法setPropertyValue(此方法在BeanWrapperImpl实现了!!)
//实现属性依赖注入功能
private void setPropertyValue(BeanWrapperImpl.PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
//PropertyTokenHolder主要保存属性的名称、路径,以及集合的size等信息
String propertyName = tokens.canonicalName;
String actualName = tokens.actualName;
Object propValue;
//keys是用来保存集合类型属性的size
if(tokens.keys != null) {
//将属性信息拷贝
BeanWrapperImpl.PropertyTokenHolder getterTokens = new BeanWrapperImpl.PropertyTokenHolder(null);
getterTokens.canonicalName = tokens.canonicalName;
getterTokens.actualName = tokens.actualName;
getterTokens.keys = new String[tokens.keys.length - 1];
System.arraycopy(tokens.keys, 0, getterTokens.keys, 0, tokens.keys.length - 1);
try {
//获取属性值,该方法内部使用JDK的内省( Introspector)机制,调用属性//的getter(readerMethod)方法,获取属性的值
propValue = this.getPropertyValue(getterTokens);
} catch (NotReadablePropertyException var21) {
throw new NotWritablePropertyException(this.getRootClass(), this.nestedPath + propertyName, "Cannot access indexed value in property referenced in indexed property path '" + propertyName + "'", var21);
}
//获取集合类型属性的长度
String key = tokens.keys[tokens.keys.length - 1];
if(propValue == null) {
if(!this.isAutoGrowNestedPaths()) {
throw new NullValueInNestedPathException(this.getRootClass(), this.nestedPath + propertyName, "Cannot access indexed value in property referenced in indexed property path '" + propertyName + "': returned null");
}
int lastKeyIndex = tokens.canonicalName.lastIndexOf(91);
getterTokens.canonicalName = tokens.canonicalName.substring(0, lastKeyIndex);
propValue = this.setDefaultValue(getterTokens);
}
Object convertedValue;
Object newArray;
Class requiredType;
PropertyDescriptor pd;
//注入array类型的属性值
if(propValue.getClass().isArray()) {
//获取属性的描述符
pd = this.getCachedIntrospectionResults().getPropertyDescriptor(actualName);
//获取数组的类型
requiredType = propValue.getClass().getComponentType();
//获取数组的长度
int arrayIndex = Integer.parseInt(key);
Object oldValue = null;
try {
//获取数组以前初始化的值
if(this.isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
oldValue = Array.get(propValue, arrayIndex);
}
//将属性的值赋值给数组中的元素
convertedValue = this.convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType, TypeDescriptor.nested(this.property(pd), tokens.keys.length));
int length = Array.getLength(propValue);
if(arrayIndex >= length && arrayIndex < this.autoGrowCollectionLimit) {
Class<?> componentType = propValue.getClass().getComponentType();
newArray = Array.newInstance(componentType, arrayIndex + 1);
System.arraycopy(propValue, 0, newArray, 0, length);
this.setPropertyValue(actualName, newArray);
propValue = this.getPropertyValue(actualName);
}
Array.set(propValue, arrayIndex, convertedValue);
} catch (IndexOutOfBoundsException var20) {
throw new InvalidPropertyException(this.getRootClass(), this.nestedPath + propertyName, "Invalid array index in property path '" + propertyName + "'", var20);
}
} else {
Object convertedValue;
if(propValue instanceof List) {//注入list类型的属性值
pd = this.getCachedIntrospectionResults().getPropertyDescriptor(actualName);
//获取list集合的类型
requiredType = GenericCollectionTypeResolver.getCollectionReturnType(pd.getReadMethod(), tokens.keys.length);
List<Object> list = (List)propValue;
//获取list集合的size
int index = Integer.parseInt(key);
convertedValue = null;
if(this.isExtractOldValueForEditor() && index < list.size()) {
convertedValue = list.get(index);
}
//获取list解析后的属性值
convertedValue = this.convertIfNecessary(propertyName, convertedValue, pv.getValue(), requiredType, TypeDescriptor.nested(this.property(pd), tokens.keys.length));
int size = list.size();
//如果list的长度大于属性值的长度,则多余的元素赋值为null
if(index >= size && index < this.autoGrowCollectionLimit) {
for(int i = size; i < index; ++i) {
try {//如果list的长度大于属性值的长度,则多余的元素赋值为null
list.add((Object)null);
} catch (NullPointerException var19) {
throw new InvalidPropertyException(this.getRootClass(), this.nestedPath + propertyName, "Cannot set element with index " + index + " in List of size " + size + ", accessed using property path '" + propertyName + "': List does not support filling up gaps with null elements");
}
}
list.add(convertedValue);
} else { //如果list的长度小于属性值的长度,为list属性赋值
try {
list.set(index, convertedValue);
} catch (IndexOutOfBoundsException var18) {
throw new InvalidPropertyException(this.getRootClass(), this.nestedPath + propertyName, "Invalid list index in property path '" + propertyName + "'", var18);
}
}
} else { //注入map类型的属性值
if(!(propValue instanceof Map)) {
throw new InvalidPropertyException(this.getRootClass(), this.nestedPath + propertyName, "Property referenced in indexed property path '" + propertyName + "' is neither an array nor a List nor a Map; returned value was [" + propValue + "]");
}
pd = this.getCachedIntrospectionResults().getPropertyDescriptor(actualName);
//获取map集合key的类型
requiredType = GenericCollectionTypeResolver.getMapKeyReturnType(pd.getReadMethod(), tokens.keys.length);
//获取map集合value的类型
Class<?> mapValueType = GenericCollectionTypeResolver.getMapValueReturnType(pd.getReadMethod(), tokens.keys.length);
Map<Object, Object> map = (Map)propValue;//强转
//解析map类型属性key值
TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(requiredType);
//解析map类型属性value值
convertedValue = this.convertIfNecessary((String)null, (Object)null, key, requiredType, typeDescriptor);
Object oldValue = null;
if(this.isExtractOldValueForEditor()) {
oldValue = map.get(convertedValue);
}
newArray = this.convertIfNecessary(propertyName, oldValue, pv.getValue(), mapValueType, TypeDescriptor.nested(this.property(pd), tokens.keys.length));
//将解析后的key和value值赋值给map集合属性
map.put(convertedValue, newArray);
}
}
} else { //对非集合类型的属性注入
PropertyDescriptor pd = pv.resolvedDescriptor;
if(pd == null || !pd.getWriteMethod().getDeclaringClass().isInstance(this.object)) {
pd = this.getCachedIntrospectionResults().getPropertyDescriptor(actualName);
//无法获取到属性名或者属性没有提供setter(写方法)方法
if(pd == null || pd.getWriteMethod() == null) {
//如果属性值是可选的,即不是必须的,则忽略该属性值
if(pv.isOptional()) {
logger.debug("Ignoring optional value for property '" + actualName + "' - property not found on bean class [" + this.getRootClass().getName() + "]");
return;
}
//如果属性值是必须的,则抛出无法给属性赋值,因为每天提供setter方法异常
PropertyMatches matches = PropertyMatches.forProperty(propertyName, this.getRootClass());
throw new NotWritablePropertyException(this.getRootClass(), this.nestedPath + propertyName, matches.buildErrorMessage(), matches.getPossibleMatches());
}
pv.getOriginalPropertyValue().resolvedDescriptor = pd;
}
propValue = null;
PropertyChangeEvent propertyChangeEvent;
try {
Object originalValue = pv.getValue();//拿到初始值
Object valueToApply = originalValue;
final Method readMethod;
if(!Boolean.FALSE.equals(pv.conversionNecessary)) {
if(pv.isConverted()) {
valueToApply = pv.getConvertedValue();
} else {
if(this.isExtractOldValueForEditor() && pd.getReadMethod() != null) {
//获取属性的getter方法(读方法),JDK内省机制
readMethod = pd.getReadMethod();
//如果属性的getter方法不是public访问控制权限的,即访问控制权限比较严格,
//则使用JDK的反射机制强行访问非public的方法(暴力读取属性值)
if(!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()) && !readMethod.isAccessible()) {
if(System.getSecurityManager() != null) {
//匿名内部类,根据权限修改属性的读取控制限制
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
readMethod.setAccessible(true);
return null;
}
});
} else {
readMethod.setAccessible(true);
}
}
try {
//属性没有提供getter方法时,调用潜在的读取属性值//的方法,获取属性值
if(System.getSecurityManager() != null) {
propValue = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
return readMethod.invoke(BeanWrapperImpl.this.object, new Object[0]);
}
}, this.acc);
} else {
propValue = readMethod.invoke(this.object, new Object[0]);
}
} catch (Exception var22) {
Exception ex = var22;
if(var22 instanceof PrivilegedActionException) {
ex = ((PrivilegedActionException)var22).getException();
}
if(logger.isDebugEnabled()) {
logger.debug("Could not read previous value of property '" + this.nestedPath + propertyName + "'", ex);
}
}
}
//设置属性的注入值
valueToApply = this.convertForProperty(propertyName, propValue, originalValue, new TypeDescriptor(this.property(pd)));
}
pv.getOriginalPropertyValue().conversionNecessary = Boolean.valueOf(valueToApply != originalValue);
}
//根据JDK的内省机制,获取属性的setter(写方法)方法
readMethod = pd instanceof GenericTypeAwarePropertyDescriptor?((GenericTypeAwarePropertyDescriptor)pd).getWriteMethodForActualAccess():pd.getWriteMethod();
//如果属性的setter方法是非public,即访问控制权限比较严格,则使用JDK的反射机制,
//强行设置setter方法可访问(暴力为属性赋值)
if(!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()) && !readMethod.isAccessible()) {
//如果使用了JDK的安全机制,则需要权限验证
if(System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
readMethod.setAccessible(true);
return null;
}
});
} else {
readMethod.setAccessible(true);
}
}
final Object value = valueToApply;
if(System.getSecurityManager() != null) {
try {
//将属性值设置到属性上去
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
readMethod.invoke(BeanWrapperImpl.this.object, new Object[]{value});
return null;
}
}, this.acc);
} catch (PrivilegedActionException var17) {
throw var17.getException();
}
} else {
readMethod.invoke(this.object, new Object[]{valueToApply});
}
} catch (TypeMismatchException var23) {
throw var23;
} catch (InvocationTargetException var24) {
propertyChangeEvent = new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, propValue, pv.getValue());
if(var24.getTargetException() instanceof ClassCastException) {
throw new TypeMismatchException(propertyChangeEvent, pd.getPropertyType(), var24.getTargetException());
}
throw new MethodInvocationException(propertyChangeEvent, var24.getTargetException());
} catch (Exception var25) {
propertyChangeEvent = new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, propValue, pv.getValue());
throw new MethodInvocationException(propertyChangeEvent, var25);
}
}
}
很复杂的一个解析方法:将属性的值注入到Bean实例对象中情况如下:
1. 对于集合类型的属性,将其属性值解析为目标类型的集合后直接赋值给属性
2. 对于非集合类型的属性,大量使用了JDK的反射和内省机制,通过属性的getter方法(reader method)获取指定属性注入以前的值,同时调用属性的setter方法(writer method)为属性设置注入后的值。
依赖注入总结:
(一)DefaultListableBeanFactory父类AbstractBeanFactory根据Bean的状态定义(单例、存在、原型)进行构造方法分发。分发到AbstractAutowireCapableBeanFactory类的createBean方法
(二)createBean方法负责Bean实例要求状态判断以及再度分发到doCreateBean实现创建实例(再次配置判断)。并在doCreateBean再度分发去createBeanInstance去Bean所包含的Java对象实例以及去populateBean 方法对Bean属性的依赖注入进行处理(以此为责任分发中心)。
(三)在createBeanInstance方法中真正地根据之前的配置判断设置选择真正合适的构造器(自动装配、无参构造器);
(四)在populateBean 方法中真正地将Bean属性设置到生成的实例对象上 ,但在过程中注入依赖属性的是在applyPropertyValues方法(完成属性转换),调用BeanDefinitionValueResolver类调用resolveValueIfNecessary方法对属性值的解析,属性的真正注入实现在BeanWrapperImpl类。
好了,Spring应用、原理以及粗读源码系列(一)--框架总述、以Bean为核心的机制(IoC容器初始化以及依赖注入)讲完了,这个系列以应用为基本点,结合源码讲解那堆应用的机制原理,我会加快脚步学习,分享经验给大家,希望大家喜欢。欢迎在下面指出错误,共同学习!!你的点赞是对我最好的支持!!