Spring 技术内幕
依赖反转
依赖对象的获得被反转了。控制反转也叫依赖注入。
许多应用都是由两个或多个类通过彼此的合作来实现业务逻辑的。这使得每个对象都需要与其合作的对象(也就是它所依赖的对象)的引用。
Ioc 容器
对象之间的互相依赖关系由Ioc来进行管理,并由Ioc容器完成对象的注入
- Ioc 应用场景
在Spring中,Spring Ioc 提供了一个基本的Javabean容器,通过IOC模式管理依赖关系,并通过依赖注入和AOP切面增强了为Javabean这样的POJO对象赋予事务管理,生命周期管理等基本功能。
-
Spring依赖注入的三种方式
- 接口注入
- setter注入
- 构造器注入
-
设计实现
-
BeanFactory (作为一个最基本的接口类出现在Spring 的Ioc容器体系中)
这系列容器只实现了容器的最基本功能。
-
ApplicationContext
它作为容器的高级形态而存在。
-
-
Spring BeanDefinition
Spring通过定义Spring BeanDefinition来管理基于Spring的应用中的各种对象以及它们之间的互相依赖关系。Spring BeanDefinition抽象了我们对Bean的定义,是让容器起作用的主要数据类型。
对Ioc容器来说BeanDefinition就是对依赖反转模式中管理的对象依赖关系的数据抽象,也是实现依赖反转功能的核心数据结构,依赖反转功能都是围绕对这个BeanDefinition的处理来完成的。
-
Ioc 容器的设计
- WebApplicationContext Spring Ioc 5.x版本
- 通过XmlBeanFactory( 继承关系) 理解 BeanFactory
-
使用IOC容器
- 创建IOC配置文件的抽象资源,这个抽象资源包含了BeanDefinition的定义信息
- 创建一个BeanFactory,这里使用DefaultListtableBeanFactory
- 创建一个载入BeanDefinition的读取器,这里使用XmlBeanDefinitionReader来载入XML文件形式的BeanDefinition,通过一个回调器配置给BeanFactory
- 从定义好的资源位置读入配置信息,具体的解析过程由XmlBeanDefinitionReader来完成。完成整个载入和注册Bean定义后,需要的IOC容器就建立起来了,这个时候就可以直接使用IOC容器了。
-
通过FileSystemXmlApplicationContext( 继承关系) 理解 ApplicationContext
-
功能一:实例化应用上下文的支持,同时启动IoC容器的refresh()过程
refresh() 过程会牵涉Ioc容器启动的一系列复杂操作
public FileSystemXmlApplicationContext( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { super(parent); setConfigLocations(configLocations); if (refresh) { refresh(); } }
-
功能二:从文件系统中加载XML的Bean定义资源有关,可以为在文件系统中读取以XML形式存在的BeanDefinition作准备
// 获取FileSystemResource资源定位 protected Resource getResourceByPath(String path) { if (path.startsWith("/")) { path = path.substring(1); } return new FileSystemResource(path); }
-
IoC容器初始化过程,refresh()操作进行启动
-
Resource定位过程
指BeanDefinition的资源定位,由ResourceLoader通过统一的Resource接口来完成,这个Resource对各种形势的BeanDefinition的使用都提供了统一接口。 这个定位过程类似于寻找数据的过程,像水桶装水要先把水找到一样。
-
BeanDefinition的载入
把用户定义好的Bean表示成IoC容器内部的数据结构,而这个结构内部的数据结构就是BeanDefinition. BeanDefinition实际上就是POJO对象在IoC容器中的抽象,通过这个BeanDefinition定义的数据结构,使IoC容器能够方便地对POJO对象进行管理。
-
向IoC容器注册这些BeanDefinition的过程
通过调用BeanDefinitionRegistry接口完成。把载入解析到的BeanDefinition向IoC容器进行注册。 Ioc容器内部将BeanDefinition注入到一个HashMap中去,Ioc容器就是通过这个HashMap来持有这些BeanDefinition数据。
IOC容器初始化过程中一般不包含Bean依赖注入的实现。
-
-
依赖注入一般发生在应用第一次通过getBean向容器索取Bean的时候
Ioc预实例化配置,lazyinit属性,配置后可将Bean的依赖注入在Ioc容器初始化时就预先完成。