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

原创 2018年01月05日 00:00:00

前几篇:

Spring核心技术原理-(1)-为什么要有Spring?

Spring核心技术原理-(2)-为什么要有Spring AOP?

Spring核心技术原理-(3)-Spring历史版本变迁和如今的生态帝国

一、前言

前三篇已经从历史的角度和大家一起探讨了为什么会有Spring,Spring的两个核心概念:IoC和AOP的雏形,Spring的历史变迁和如今的生态帝国。本节的主要目的就是通过一个切入点带大家一起学习一下Spring IoC的核心原理,正如从历史的角度出发讲述为什么会有Spring一样,希望通过这个切入点能让你轻松的掌握住Spring IoC的核心原理。

本篇文章假设你已经可以熟练的使用Spring了,因此对于某一个细节如何实现的不会在进行详细的阐述!

二、IoC和DI的基本概念

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

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

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

UtWdDgynLdbfVTGJUvbhrolqeJZnlrJ6GjicDIurt7nAfp3dIN2wLyVSB2Lyknv5pupT0MdibSiaI89UpEps8KmoA

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

三、从哪里入手IoC容器?

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

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

1、首先看一下项目结构

UtWdDgynLdbfVTGJUvbhrolqeJZnlrJ6SozdrpIS8vX5lInZzlIaLf3W33KeKWRY0XVQXicIB72bFRKErA9E9nQ

继承关系:

UtWdDgynLdbfVTGJUvbhrolqeJZnlrJ6vhGmAuNqFmOzWCROODKnaIKpEQzmklRX3eCVpaWYAbHImzfPIXckfg

bean的配置:

UtWdDgynLdbfVTGJUvbhrolqeJZnlrJ6gMtxkr21ulDSYu37B4EPLfJEDlgTez122YdXHo205uUnbFOjDa5lzg

Main代码如下:

UtWdDgynLdbfVTGJUvbhrolqeJZnlrJ6IGnBjwoGVgS2gKB3akCh4F5YzIOUDjAkziaskzEiaAF0htyEMpzLVs8A

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

UtWdDgynLdbfVTGJUvbhrolqeJZnlrJ6owx1G7AMibS62B4qquaREc2LZ0h4C3xwAnsicwaGp3WR1sIcQvajsW1A

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

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

四、BeanFactory和ApplicationContext之间的关系

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

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

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

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

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

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

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

UtWdDgynLdbfVTGJUvbhrolqeJZnlrJ6Wwza6q25WRjCYHO16nf9Nk6MtQJ3puSSPiaN2bYX029HV6GIbotq6xQ

(1)创建IoC配置文件的抽象资源,这个抽象资源包含了BeanDefinition的定义信息(也就是我们在bean.xml文件中配置的一个bean的数据结构); (2)创建一个BeanFactory,这里使用的是DefaultListableBeanFactory; (3)创建一个载入BeanDefinition的读取器,这里使用的是XmlBeanDefinitionReader来载入XML形式的BeanDefinition,通过一个回调配置给BeanFactory; (4)从定义好的资源位置读入配置信息,具体的解析过程由XmlBeanDefinitionReader来完成。

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

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

UtWdDgynLdbfVTGJUvbhrolqeJZnlrJ6vGnKJlNYbpMYeAd0orDCxEsnp4J2zZKDYWT3avxFRseLm5ZsXIrd8w

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

UtWdDgynLdbfVTGJUvbhrolqeJZnlrJ6iazFI7fbUfia56ocpkMVZhVSVYsuCNtB4YQZUgzk5YM30IOY9OXE40MQ

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

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

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

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

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

UtWdDgynLdbfVTGJUvbhrolqeJZnlrJ68a1vRw6ccGGoDgBVjESCtVqU9ne2K3ympHjc5icfUiagFDKk06UDnibJg

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

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

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

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

UtWdDgynLdbfVTGJUvbhrolqeJZnlrJ60ItZt6DZ8AuLZiaPN3VZCxr2pic0icIVENK9TPd5O93bsibYOUWMZzQQ9Q

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

UtWdDgynLdbfVTGJUvbhrolqeJZnlrJ68KicPv2UJd9KmWdb4VFBricIlVAQ0HMfLxML0ibOUqfjzEiaOBgenbjIxw

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

八、总结

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

纸上得来终觉浅,绝知此事要躬行!

对于Spring IoC容器的核心原理远不止这些,但是基本都是在这三条主线上进行穿插,其他没有提到的如:容器初始化,配置文件解析过程、Bean的解析和注册等,希望大家在在进行学习的时候注意到!

如果想进一步学习Spring原理的,这里推荐两本书籍《Spring技术内幕-深入解析Spring架构与设计原理》和《精通Spring 4.x 企业应用开发实战》,前者可能有点久,版本不是最新的,但是书中Spring IoC容器和AOP的讲解还是很有参考价值的,后者应该算是市面上一本讲解还算透彻的书籍,值得阅读!


最近热文阅读:

1、为什么要有Spring?

2、为什么要有Spring AOP?

3、2017年IT人期末考试卷,能考60分就是自己人!

4、Spring历史版本变迁和如今的生态帝国

5、大型网站应用之海量数据和高并发解决方案总结一二

6、Java大型互联网公司经典面试题,论JDK源码的重要性的无限思考

7、使用Jenkins配置SpringBoot的自动化构建

更多精彩,从关注《Java后端技术》公众号开始!

?

版权声明:本文为博主原创文章,未经博主允许不得转载。

Spring源码剖析——核心IOC容器原理

IOC介绍  相信大多数人在学习Spring时 IOC 和 Bean 算得上是最常听到的两个名词,IOC在学习Spring当中出现频率如此之高必然有其原因。如果我们做一个比喻的话,把Bean说成Spr...
  • lisongjia123
  • lisongjia123
  • 2016年08月05日 15:06
  • 4389

深入理解Spring的两大特征(IOC和AOP)

众所周知,Spring的核心特性就是IOC和AOP,IOC(Inversion of Control),即“控制反转”;AOP(Aspect-OrientedProgramming),即“面向切面编程...
  • gloomy_114
  • gloomy_114
  • 2017年04月05日 11:46
  • 10172

谈谈对Spring IOC的理解

学习过Spring框架的人一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC 、DI这两个概念是模糊不清的,是很难理解的,今天和大家...
  • qq_22654611
  • qq_22654611
  • 2016年09月21日 13:42
  • 45428

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

原创 2018-01-05 徐刘根 Java后端技术一、前言前三篇已经从历史的角度和大家一起探讨了为什么会有Spring,Spring的两个核心概念:IoC和AOP的雏形,Spring的历史变迁和如今...
  • GoGleTech
  • GoGleTech
  • 2018年01月05日 09:25
  • 59

Spring应用、原理以及粗读源码系列(一)--框架总述、以Bean为核心的机制(IoC容器初始化以及依赖注入)

总述:spring框架是如今J2EE开发最重要框架之一,为企业级应用提供一系列轻量级解决方案,比如:基于依赖注入的核心机制、基于AOP的声明式事务管理、与多种持久层技术整合、整合后端各种组件等等。贯穿...
  • Jack__Frost
  • Jack__Frost
  • 2017年06月05日 15:08
  • 1565

Spring 核心知识点 IOC容器入门与了解

知识体系:一: Spring框架的简介  1.什么是Spring? 2.Spring 的主要功能有哪些?   二:  容器和Bean管理   1.Spring容器的简介 2.Spring 容器的实例化...
  • qq_26563167
  • qq_26563167
  • 2017年11月17日 14:55
  • 132

Spring框架核心技术--IOC容器

Spring框架核心技术–IOC容器Spring框架核心技术IOC容器 概述 Spring框架 专业术语详解 Spring框架六大模块功能 Spring开发步骤 bean对象创建的细节 SpringI...
  • jpzhu16
  • jpzhu16
  • 2016年10月03日 09:49
  • 1013

Spring核心概念理解-IoC容器、DI、AOP

每个java程序员对spring的基础概念都倒背入流,AOP(面向切面编程)、IOC(控制反转)、DI(依赖注入)。今天就这几个概念做一个简单深入的原理分析。AOP\IOC主要是思想和原则性的东西。D...
  • c123728529
  • c123728529
  • 2016年03月15日 23:58
  • 589

Spring框架参考文档-核心技术-IoC容器

基本概念: @Bean 和 @Configuration 在Spring新的Java配置支持中,其核心构件是@Configuration注解类和@Bean注解方法. @Bean 注解用来表...
  • u012560902
  • u012560902
  • 2016年08月09日 14:37
  • 313

Spring技术内幕2Spring Framework的核心:IoC容器的实现

1SpringIoC容器概述 IoC容器和依赖反转模式: 早在2004年,Martin Fowler就提出了“哪些方面的控制被反转了?”这个问题。他总结出是依赖对象的获得被反转了。基于这个结论...
  • partner4java
  • partner4java
  • 2012年03月19日 22:30
  • 3919
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:三条路线告诉你如何掌握Spring IoC容器的核心原理
举报原因:
原因补充:

(最多只允许输入30个字)