【原文】

Spring的两个核心概念:IoC和AOP的雏形,Spring的历史变迁和如今的生态帝国。

IoC和DI的基本概念

IoC(控制反转,英文含义:Inverse of Control)是Spring容器的内核,AOP、事务等功能都是建立在此基础上的。从字面意思上可以把IoC拆分为两层含义:控制和反转。控制可以理解为是接口实现类的选择权,反转可以理解为这个选择权交给第三方进行管理;总的来说就是某一接口具体实现类的选择控制权从调用类中移除,转交给第三方进行决定,即由Spring容器通过Bean配置来进行控制,这样的话应用程序本身就不用负责依赖对象的创建和维护,而由Spring容器进行管理。

尽管我们现在对IoC的基本概念都已经熟读与心了,但是在老一辈的时候,IoC的概念还不是很容易被人理解。在那个年代,业界的一位大佬,软件界泰斗级的人物Martin Fowler提出了DI(Dependency Injection,依赖注入)的概念,来代替IoC。

依赖注入的概念和控制反转的概念从本质上是一样的,只是从不同的侧面描述了这个功能。依赖注入的概念描述的是让调用类对某一接口实现类的依赖关系有第三方容器或其他东西注入,以此来移除对某一接口实现类的依赖。

时至今日,我们常说的IoC/DI的时候也是把依赖注入和控制反转作为同一个概念来进行阐述的!

三、从哪里入手IoC容器?

我曾尝试过很多次,想踏进Spring原理的大门,但是一次次都被毫无头绪的开端而打退!后来逐渐翻阅一些书籍逐渐形成了那么一点点思路,接下来主要按着我的思路探讨一下Ioc容器的基本原理。

正如我们学习骑自行车一样,开始的时候都是先看别人如何骑的,然后自己才能慢慢的学会(当然发明自行车的人是天才)。学习Spring原理也是一样,只有掌握了基本的Spring的使用,才有可能踏进Spring原理的大门。因此,这里我们从如何使用开始哪?

1、首先看一下项目结构

继承关系:

bean的配置:

Main代码如下:

2、相信每一个学习Spring的小伙伴都是从上述的方式学起的,上图中最显眼的两个类就是红色圈圈出的,也设置我们在最开始使用到的,使用UML工具显示最基本的类图关系:

庞大的一个继承和实现体系!看到这里大致上也就是我要说的第二条路线了(下文会详细介绍)!这条路线向我们展示了从Spring最接近用开发人员使用的ClassPathXmlApplicationContext、FileSystemXmlApplicationContext类到Spring的顶层接口之间层层的继承和实现关系。

看到这里我们似乎还是毫无头绪,这就需要我们借鉴前人的经验了,这个经验就是如何正确的理解BeanFactory和ApplicationContext之间的关系。

四、BeanFactory和ApplicationContext之间的关系

我们都知道Spring是通过配置文件、注解、Java类等方式描述Bean与Bean之间的依赖关系,利用Java的反射功能实例化Bean并建立Bean与Bean之间的依赖关系;

这些底层的工作正是由Spring IoC容器完成的,除此之外Spring IoC容器还提供了Bean实例缓存、生命周期管理、时间发布等高级服务。

而这里要说的BeanFactory和ApplicationContext都作为Spring IoC容器的形态存在,只不过有些许区别而已,简单的来说:(1)BeanFactory接口的实现类是一个简单容器系列,该系列的容器只实现了容器最基本的功能;(2)ApplicationContext接口的实现类是一个高级容器系列,该系列的容器在简单容器的基础上增加了很多面向框架的特性,对应用环境做了很多适配,同时添加了很多面向应用的功能,例如:国际化支持和框架事件体系结构等。

通常情况下,我们习惯称BeanFactory为Ioc容器,而称ApplicationContext为应用上下文,有时候我们还直接称ApplicationContext为Spring容器。

至此,我应该可以引出我要说的前两条路线:第一条路线是基于BeanFactory的简单容器系列;第二天路线是基于ApplicationContext的高级容器系列;

五、第一条路线:基于BeanFactory的简单容器系列

既然BeanFactory的实现类也是一个容器,那么我们就应该可以使用它来注入我们的Bean和获取我们的Bean,如何使用哪?请看代码:

(1)创建IoC配置文件的抽象资源,这个抽象资源包含了BeanDefinition的定义信息(也就是我们在bean.xml文件中配置的一个bean的数据结构);

(2)创建一个BeanFactory,这里使用的是DefaultListableBeanFactory;

(3)创建一个载入BeanDefinition的读取器,这里使用的是XmlBeanDefinitionReader来载入XML形式的BeanDefinition,通过一个回调配置给BeanFactory;

(4)从定义好的资源位置读入配置信息,具体的解析过程由XmlBeanDefinitionReader来完成。

上述的过程,完成了整个载入和注册Bean的定义之后,我们所需要的IoC容器就建立起来了,这个时候我们就可以直接使用IoC容器了。

上述代码中使用了DefaultListableBeanFactory 这个BeanFactory默认实现的容器完成了Bean的注入和获取操作,查看其继承和实现关系如下:

BeanFactory位于接口类结构的顶端,它主要定义了IoC容器中应该具有的基本特性,主要接口定义如下,根据名称就可以看出是什么作用,这里不再一一解释:

面对如此多的接口或类,我们应该如何理解哪?举个栗子,就像一辆汽车一样,BeanFactory中定义了这辆汽车应该具有的基本功能,通过层层的接口继承和实现为这个基本的汽车架构定制了很多特性,比如:可以座几个人,是否可以倒车等,一直到最后才形成了一辆基本可以正常使用的汽车,但到这一步还是一个比较粗糙的产品或者半成品。(可以使用,但对于普通用户不会直接使用)

而关于这些接口或类的介绍,由于篇幅有限,这里不再一一介绍,主要给大家提供一种思路,如何顺藤摸瓜,掌握第一条理解Spring IoC容器的路线。

总的来说,BeanFactory是Spring框架的基础设置,面向的是Spring本身,下文中讲述的第二条路线其中也是使用到了上述代码中的过程,我们在实际的开发中很少会直接使用基于BeanFactory的简单容器系列。

六、第二条路线:基于ApplicationContext的高级容器系列

相对于第一条路线中的汽车半成品来说,第二个路线下的产品才真正算是一辆可以开的出去的汽车,在基于ApplicationContext的高级容器系列下为汽车新增了很多特性,比如:加了电子档位、加了倒车雷达、全景天窗、全液晶显示器什么的,一直到最后才形成了一辆可以使用的汽车(可以使用,普通用户也可以直接使用)。

从上图中可以看出来,相对于BeanFactory来说ApplicationContext增加了很多新特性,例如MessageSource接口、ApplicationEventPublisher接口等,所以说ApplicationContext是一个高级形态意义上的IoC容器。

ApplicationContext的主要实现类是ClassPathXmlApplicationContext、FileSystemXmlApplicationContext,前者是通过从类路径加载配置文件,后者模式从文件系统中装载配置。

七、第三条路线:基于WebApplicationContext的Web容器系列

从上边的介绍我们应该已经看出来了,不管是第一条路线还是第二条路线都是基于Java应用的,而我们使用最多的是JavaWeb应用,这也是接下来要说的第三条路线:基于WebApplicationContext的Web容器系列。

WebApplicationContext是专门为Web应用准备的,由于Web应用比一般的Java应用拥有更多的特性,因此WebApplicationContext扩展了ApplicationContext。

我们在配置Spring集成Spring MVC的时候基本都会使用上述的方式配置Spring容器,ContextLoaderListener通过Web容器上下文参数contextConfigLocation获取Spring配置文件的位置。如果只是使用Xml配置的Bean的话,会使用WebApplicationContext的实现类XmlWebApplicationContext。

八、总结

本文的目的并不是详细的阐述Spring IoC容器的核心原理,这是因为市面上已经有很多书讲述Spring IoC容器的核心原理的,并且简单的一篇文章很难说清楚这么多的内容,这里主要是是希望通过将Spring IoC容器的核心原理内容进行划分,整理为3条基本路线,这样的话逐步击破,才能使自己不会被庞大的代码结构体系所吓到!

【转】Spring学习---Spring IoC容器的核心原理的更多相关文章

  1. 三条路线告诉你如何掌握Spring IoC容器的核心原理

    原文链接:https://blog.csdn.net/bntx2jsqfehy7/article/details/78977178

  2. Spring源码学习之IOC容器实现原理(一)-DefaultListableBeanFactory

    从这个继承体系结构图来看,我们可以发现DefaultListableBeanFactory是第一个非抽象类,非接口类.实际IOC容器.所以这篇博客以DefaultListableBeanFactory ...

  3. Spring学习之Ioc控制反转(1)

    开始之前: 1. 本博文为原创,转载请注明出处 2. 作者非计算机科班出身,如有错误,请多指正 ---------------------------------------------------- ...

  4. Spring学习之Ioc控制反转(2)

    开始之前: 1. 本博文为原创,转载请注明出处 2. 作者非计算机科班出身,如有错误,请多指正 ---------------------------------------------------- ...

  5. Spring学习笔记IOC与AOP实例

    Spring框架核心由两部分组成: 第一部分是反向控制(IOC),也叫依赖注入(DI); 控制反转(依赖注入)的主要内容是指:只描述程序中对象的被创建方式但不显示的创建对象.在以XML语言描述的配置文 ...

  6. Spring之一:IoC容器体系结构

    温故而知心. Spring IoC概述 常说spring的控制反转(依赖反转),看看维基百科的解释: 如果合作对象的引用或依赖关系的管理要由具体对象来完成,会导致代码的高度耦合和可测试性降低,这对复杂 ...

  7. 比Spring简单的IoC容器

    比Spring简单的IoC容器 Spring 虽然比起EJB轻量了许多,但是因为它需要兼容许多不同的类库,导致现在Spring还是相当的庞大的,动不动就上40MB的jar包, 而且想要理解Spring ...

  8. 使用Spring.NET的IoC容器

    使用Spring.NET的IoC容器 0. 辅助类库 using System; using System.Collections.Generic; using System.Linq; using ...

  9. Spring.NET的IoC容器(The IoC container)——简介(Introduction)

    简介 这个章节介绍了Spring Framework的控制反转(Inversion of Control ,IoC)的实现原理. Spring.Core 程序集是Spring.NET的 IoC 容器实 ...

随机推荐

  1. SpringMVC之表单校验

    SpringMVC已经实现了对Java校验API(JSR-303)的支持,通过使用该API可以实现对数据的校验.要使用SpringMVC的Java校验API并不需要任何配置,只要引入其实现即可.本文使 ...

  2. quartz ? * 区别

    官方文档上提到问号时是这样说的: The '?' character is allowed for the day-of-month and day-of-week fields. It is use ...

  3. Linux QT 连接 Sqlite数据库

    #include <QApplication> #include <QDebug> #include <QSqlQuery> #include <QSqlDa ...

  4. Go的基本类型与变量

    基本类型 布尔型:bool 长度:1字节 取值范围:true,false 注意:不可以用数字代表true或false 整型:int/uint 根据运行平台可能为32或64位 8位整型:int8/uin ...

  5. Spring AOP切面变成——创建增强类

    说明 Spring使用增强类定义横向逻辑,同时Spring只支持方法连接点,增量类还包含在方法的哪一点添加横切代码的方位信息.所以增强既包含横向逻辑,又包含部分连接点的信息. 类型 按着增强在目标类方 ...

  6. Spring 通过Java代码装配bean

    1. 背景 书接上文Spring自动化装配bean 尽管在很多场景下通过组件扫描和自动装配实现Spring的自动化扫描配置是更为推荐的方式,但在有些情况下自动化扫描的方案行不通,如想要将第三方库中的组 ...

  7. 第一次项目上Linux服务器(五:CentOS7下Mysql数据库的安装与配置(转))

    好像在CentOS 7系统中,默认安装的mysql是它的分支mariadb.所以不能像CentOS-6.3那样安装,如下: [root@izwz ~]# yum -y install mysql my ...

  8. SpringMVC之使用 @RequestMapping 映射请求

    @RequestMapping注解 SpringMVC使用该注解让控制器知道可以处理哪些请求路径的,除了可以修饰方法,还可以修饰在类上. – 类定义处:提供初步的请求映射信息.相对于 WEB 应用的根 ...

  9. Java中异常发生时代码执行流程

    异常与错误: 异常: 在Java中程序的错误主要是语法错误和语义错误,一个程序在编译和运行时出现的错误我们统一称之为异常,它是VM(虚拟机)通知你的一种方式,通过这种方式,VM让你知道,你(开发人员) ...

  10. AngularJS学习笔记(五)自定义指令(1)

    先来说说自定义指令 ng通过内置指令的方式实现了对html的增强,同时也赋予了我们自定义指令的功能,让我们根据实际需求进行指令的定制.自定义指令涉及到模板(template).作用域(scope).数 ...