【转】Spring学习---Spring IoC容器的核心原理
【原文】
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容器的核心原理的更多相关文章
- 三条路线告诉你如何掌握Spring IoC容器的核心原理
原文链接:https://blog.csdn.net/bntx2jsqfehy7/article/details/78977178
- Spring源码学习之IOC容器实现原理(一)-DefaultListableBeanFactory
从这个继承体系结构图来看,我们可以发现DefaultListableBeanFactory是第一个非抽象类,非接口类.实际IOC容器.所以这篇博客以DefaultListableBeanFactory ...
- Spring学习之Ioc控制反转(1)
开始之前: 1. 本博文为原创,转载请注明出处 2. 作者非计算机科班出身,如有错误,请多指正 ---------------------------------------------------- ...
- Spring学习之Ioc控制反转(2)
开始之前: 1. 本博文为原创,转载请注明出处 2. 作者非计算机科班出身,如有错误,请多指正 ---------------------------------------------------- ...
- Spring学习笔记IOC与AOP实例
Spring框架核心由两部分组成: 第一部分是反向控制(IOC),也叫依赖注入(DI); 控制反转(依赖注入)的主要内容是指:只描述程序中对象的被创建方式但不显示的创建对象.在以XML语言描述的配置文 ...
- Spring之一:IoC容器体系结构
温故而知心. Spring IoC概述 常说spring的控制反转(依赖反转),看看维基百科的解释: 如果合作对象的引用或依赖关系的管理要由具体对象来完成,会导致代码的高度耦合和可测试性降低,这对复杂 ...
- 比Spring简单的IoC容器
比Spring简单的IoC容器 Spring 虽然比起EJB轻量了许多,但是因为它需要兼容许多不同的类库,导致现在Spring还是相当的庞大的,动不动就上40MB的jar包, 而且想要理解Spring ...
- 使用Spring.NET的IoC容器
使用Spring.NET的IoC容器 0. 辅助类库 using System; using System.Collections.Generic; using System.Linq; using ...
- Spring.NET的IoC容器(The IoC container)——简介(Introduction)
简介 这个章节介绍了Spring Framework的控制反转(Inversion of Control ,IoC)的实现原理. Spring.Core 程序集是Spring.NET的 IoC 容器实 ...
随机推荐
- Ceph 块设备 - 块设备快速入门
目录 一.准备工作 二.安装 Ceph 三.使用块存储 一.准备工作 本文描述如何安装 ceph 客户端,使用 Ceph 块设备 创建文件系统并挂载使用. 必须先完成 ceph 存储集群的搭建,并 ...
- Async异步编程入门示例
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- Servlet 监听器Listener详解
转自:http://blog.csdn.net/u012228718/article/details/41730799 一.简介 (一)概述 1.Listener 用于监听 Javaweb程序中的事件 ...
- BFS算法(——模板习题与总结)
首先需要说明的是BFS算法(广度优先算法)本质上也是枚举思想的一种体现,本身效率不是很高,当数据规模很小的时候还是可以一试的.其次很多人可能有这样的疑问,使用搜索算法的时候,到底选用DFS还是BFS, ...
- C指针与内存
C指针与内存 指针是C / C++ 中重要的构造类型,指针赋予了C / C++程序直接访问和修改内存的能力.C / C++的许多重要应用,如编译.OS.嵌入式开发都依赖于这种能力. 冯诺依曼体系的计算 ...
- $.each()和$(selector).each()
转载:http://www.jb51.net/article/65215.htm $.each()与$(selector).each()不同, 后者专用于jquery对象的遍历, 前者可用于遍历任何的 ...
- A simple Gaussian elimination problem.(hdu4975)网络流+最大流
A simple Gaussian elimination problem. Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65 ...
- SpringMVC+Spring+MyBatis 整合与图片上传简单示例
一.思路: (一) Dao层: 1. SqlMapConfig.xml,空文件即可.需要文件头.2. applicationContext_dao.xml. a) 数据库连接池b) SqlSessio ...
- Java 与C++区别:复写(override)
C++中子类复写父类virtual方法要做到函数参数和返回值类型都一致,而Java中返回值类型可以不同,即子类复写的方法返回值类型可以使父类方法返回值类型的一个子类型.比如 返回类型兼容情况 Java ...
- Sql Server分页储存过程
--分页储存过程if exists (select * from sys.procedures where name='Page')drop proc Pagegocreate proc Page@P ...