Spring系列(二)Spring IOC容器初始化

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容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。

Spring系列(二)Spring IOC容器初始化_第1张图片

 

最终的默认实现类是DefaultListableBeanFactory,他实现了所有的接口;

 

BeanFactory提供了管理bean的核心方法

Spring系列(二)Spring IOC容器初始化_第2张图片

 

2. BeanDefinition

SpringIOC 容器管理了我们定义的各种 Bean 对象及其相互的关系,Bean 对象在 Spring 实现中是以 BeanDefinition 来描述的。

BeanDefinition定义了Bean的数据结构,用来存储Bean。

Spring系列(二)Spring IOC容器初始化_第3张图片

 

Bean 的解析过程非常复杂,功能被分的很细,因为这里需要被扩展的地方很多,必须保证有足够的灵活性,以应对可能的变化。Bean 的解析主要就是对 Spring 配置文件的解析。这个解析过程主要通过下图中的类完成:

 Spring系列(二)Spring IOC容器初始化_第4张图片

 

3.ApplicationContext
      ApplicationContext实现了最顶层的BeanFactory接口,也是一个IOC容器,ApplicationContext作为Spring的启动入口,也是IOC容器初始化的入口

                                                          ApplicationContext体系


Spring系列(二)Spring IOC容器初始化_第5张图片

3.IOC容器初始化

IOC 容器的初始化包括BeanDefinition 的 Resource 定位、载入和注册这三个基本的过程

 Spring系列(二)Spring IOC容器初始化_第6张图片

 

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工厂初始化         newDefaultListableBeanFactory(getInternalParentBeanFactory())表示所有Bean都是由DefaultBeanFactory()创建.

                        DefaultBeanFactory的类结构图

6.loadBeanDefinitions(beanFactory)  调用载入Bean定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器

        6.1.newXmlBeanDefinitionReader(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 valueBeanDefinition

23.registry.registerBeanDefinition()  向IOC容器注册BeanDefinition
存贮到ConcurrentHashMap中
private final  Map  beanDefinitionMap  new  ConcurrentHashMap<>( 256 );
 

总体流成:首先把需要加载的Bean.xml路径存放到数组中,在创建一个DefaultListableBeanFactory()容器,获取路径把路径下的XML文件转化成java文件,把java文件解析成BeanDefinition,在把BeanDefinition存储到ConcurrentHashMap中。

 


你可能感兴趣的:(Spring)