1. 什么是 IoC/DI
IoC(Inversionof Control) 控制反转: 所谓控制反转, 就是把原先我们代码里面需要实现的对象创建, 依赖的代码, 反转给容器来帮忙实现. 那么必然的我们需要创建一个容器, 同时需要一种描述来让容器知道需要创建的对象与对象的关系. 这个描述最具体表现就是我们可配置的文件.
DI(Dependency Injection) 依赖注入: 就是指对象是被动接受依赖类而不是自己主动去找, 换句话说 就是指对象不是从容器中查找它依赖的类, 而是在容器实例化对象的时候主动将它依赖的类注入给它.
谁控制谁, 控制什么: 传统 Java SE 程序设计, 我们直接在对象内部通过 new 进行创建对象, 是程序主动去创建依赖对象; 而 IoC 是有专门一个容器来创建这些对象, 即由 IoC 容器来控制对 象的创建; 谁控制谁? 当然是 IoC 容器控制了对象; 控制什么? 那就是主要控制了外部资
源获取 (不只是对象包括比如文件等).
为何是反转, 哪些方面反转了: 有反转就有正转, 传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象, 也就是正转; 而反转则是由容器来帮忙创建及注入依赖对象; 为何是反转? 因为由容器帮我们查找及注入依赖对象, 对象只是被动的接受依赖对象, 所以是
反转; 哪些方面反转了? 依赖对象的获取被反转了.
综上: IoC 分为两个部分.
第一部分 初始化一个 IoC 容器, 获取外部资源文件 (管理类 Bean 定义的相关数据)
第二部分 IoC 容器对所管理的 Bean 进行依赖注入
2.Spring 中核心的概念
1. BeanFactory(IoC 容器管理 Bean)
BeanFactory, 以 Factory 结尾, 表示它是一个工厂类 (接口), 用于管理 Bean 的一个工厂. 在 Spring 中, BeanFactory 是 IoC 容器的核心接口, 它的职责包括: 实例化, 定位, 配置应用程序中的对象及建立这些对象间的依赖.
最终的默认实现类是 DefaultListableBeanFactory, 他实现了所有的接口; BeanFactory 提供了管理 bean 的核心方法
2. BeanDefinition
SpringIOC 容器管理了我们定义的各种 Bean 对象及其相互的关系, Bean 对象在 Spring 实现中是以 BeanDefinition 来描述的.
BeanDefinition 定义了 Bean 的数据结构, 用来存储 Bean.
Bean 的解析过程非常复杂, 功能被分的很细, 因为这里需要被扩展的地方很多, 必须保证有足够的灵活性, 以应对可能的变化. Bean 的解析主要就是对 Spring 配置文件的解析. 这个解析过程主要通过下图中的类完成:
3.ApplicationContext
ApplicationContext 实现了最顶层的 BeanFactory 接口, 也是一个 IoC 容器, ApplicationContext 作为 Spring 的启动入口, 也是 IoC 容器初始化的入口
ApplicationContext 体系
3.IoC 容器初始化
IoC 容器的初始化包括 BeanDefinition 的 Resource 定位, 载入和注册这三个基本的过程
1.super(parent) 方法 设置 Spring 的资源加载器
private final ResourceLoader resourceLoader;
2.setConfigLocations() 把配置文件路径存放到数组中 (可传入多个参数路径)
private String[] configLocations;
3.refresh() 把所有的 Bean 重新构造一遍
4.obtainFreshBeanFactory() Bean 定义资源文件的载入 (从这个方法开始)
5.refreshBeanFactory() 使用了委派设计模式, 父类定义了抽象的 refreshBeanFactory() 方法, 具体实现调用子类容器 refreshBeanFactory() 方法, 子类 refreshBeanFactory()
判断 BeanFactory 是否存在, 如果存在则先销毁 beans 并关闭 beanFactory, 接着创建 DefaultListableBeanFactory, 并调用 loadBeanDefinitions(beanFactory) 装载 bean 定义.
5.1.createBeanFactory() 用 createBeanFactory 对 beanFactory 工厂初始化 new DefaultListableBeanFactory(getInternalParentBeanFactory()) 表示所有 Bean 都是由 DefaultBeanFactory() 创建.
DefaultBeanFactory 的类结构图
6.loadBeanDefinitions(beanFactory) 调用载入 Bean 定义的方法, 主要这里又使用了一个委派模式, 在当前类中只定义了抽象的 loadBeanDefinitions 方法, 具体的实现调用子类容器
6.1.new XmlBeanDefinitionReader(beanFactory) 创建 Bean 读取器, 并通过回调设置到容器中去, 容器使用该读取器读取 Bean 定义资源
7.loadBeanDefinitions(beanDefinitionReader) 传入新建的读取器 Bean 读取器真正实现加载的方法
7.1.getConfigResources(); 获取 Bean 定义资源的定位 即 2 中保存的参数 String[] configLocations;
8.reader.loadBeanDefinitions(configLocations); XmlBean 读取器调用其父类 AbstractBeanDefinitionReader 读取定位的 Bean 定义资源
9.loadBeanDefinitions(location) 是一个重载方法
10.loadBeanDefinitions(location, null)(重载方法) 获取在 IoC 容器初始化过程中设置的资源加载器 一 1 中设置的 resourceLoader; 判读是否为 NULL, 并且如果 resourceLoader instanceof ResourcePatternResolver
11.loadBeanDefinitions(resources) 委派设计模式委派给 XmlBeanDefinitionReader 实现
12.doLoadBeanDefinitions()(重载方法) 将读入的 xml 资源进行特殊编码处理 载入 xml 形式 Bean 定义资源文件方法, 首先 / 将资源文件转为 InputStream 的 IO 流 在从 InputStream 中得到 xml 的解析源
13.doLoadBeanDefinitions()(重载方法) 从特定 xml 文件中实际载入 Bean 定义资源的方法
14.doLoadDocument() 将 xml 文件转换为 DOM 对象, 解析过程由 documentLoader 实现
15.registerBeanDefinitions() 这里是启动对 Bean 定义解析的详细过程, 该解析过程会用到 Spring 的 Bean 配置规则 按照 Spring 的 Bean 语义要求将 Bean 定义资源解析并转换为容器内部数据结构
16.documentReader.registerBeanDefinitions 解析过程入口, 这里使用了委派模式, BeanDefinitionDocumentReader 只是个接口, 具体的解析实现过程有实现类 DefaultBeanDefinitionDocumentReader 完成
17.doRegisterBeanDefinitions(root) do 开头的都是干活的方法, 开始解析 Bean
18.preProcessXml(root) 在解析 Bean 定义之前, 进行自定义的解析, 增强解析过程的可扩展性
19.parseBeanDefinitions() 进入了加载过程 解析过程解析 Bean.xml 中的标签 , 把 xml 中的内容变成 BeanDefinition 运用 delegate 委派模式
20.parseDefaultElement(ele, delegate) 使用 Spring 的 Bean 规则解析元素节点
21.processBeanDefinition(ele, delegate) 进入注册环节
22.BeanDefinitionReaderUtils.registerBeanDefinition() 向 Spring IoC 容器注册解析得到的 Bean 定义, 这是 Bean 定义向 IoC 容器注册的入口 进入注册环节 Key 就是 Bean id value 为 BeanDefinition
23.registry.registerBeanDefinition() 向 IoC 容器注册 BeanDefinition 存贮到 ConcurrentHashMap 中
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
总体流成: 首先把需要加载的 Bean.xml 路径存放到数组中, 在创建一个 DefaultListableBeanFactory() 容器, 获取路径把路径下的 xml 文件转化成 java 文件, 把 java 文件解析成 BeanDefinition, 在把 BeanDefinition 存储到 ConcurrentHashMap 中.
来源: http://www.bubuko.com/infodetail-3484113.html