目录
一、初识Spring
为什么要使用Spring
可以看官网的这段话:
Spring官网链接
什么是Spring
Spring 是一个轻量级Java开发框架,最根本的使命是解决企业级应用开发的复杂性,即简化Java开发,目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题。 它是一个分层的 JavaSE/JavaEE full-stack(一站式)轻量级开源框架,为开发Java应用程序提供全面的基础架构支持。Spring 负责基础架构,因此 Java 开发者可以专注于应用程序的开发。
Spring可以做很多事情,它为企业级开发提供给了丰富的功能,但是这些功能的底层都依赖于它的两个核心特性,也就是依赖注入(dependency injection,DI)和面向切面编程(aspect-oriented programming,AOP)。
Spring框架的核心
IoC容器
和AOP模块
。通过IoC容器管理POJO对象以及他们之间的耦合关系;通过AOP以动态非侵入的方式增强服务。IoC让相互协作的组件保持松散的耦合,而AOP编程允许你把遍布于应用各层的功能分离出来形成可重用的功能组件。
由哪些模块组成
Spring Framework 属于其中最基础,最核心的部分,Spring下的其他大部分框架都依赖 Spring
Framework 。 其中大约有 20 个模块, 由 1300 多个不同的文件构成。 而这些组件被分别整合在核心容器(Core Container)
、 AOP(Aspect Oriented Programming)和设备支持(Instrmentation)
、数据访问与集成(Data Access/Integeration)
、 Web
、 消息(Messaging)
、 Test
等 6 个模块中。 以下是 Spring 5.x 版本的模块结构图:
spring core
:提供了框架的基本组成部分,包括控制反转(Inversion of Control,IOC)和依赖注入(Dependency Injection,DI)功能。spring beans
:提供了BeanFactory,是工厂模式的一个经典实现,Spring将管理对象称为Bean。spring context
:构建于 core 封装包基础上的 context 封装包,提供了一种框架式的对象访问方法。spring jdbc
:提供了一个JDBC的抽象层,消除了烦琐的JDBC编码和数据库厂商特有的错误代码解析, 用于简化JDBC。spring aop
:提供了面向切面的编程实现,让你可以自定义拦截器、切点等。spring Web
:提供了针对 Web 开发的集成特性,例如文件上传,利用 servlet listeners 进行 ioc 容器初始化和针对 Web 的 ApplicationContext。spring test
:主要为测试提供支持的,支持使用JUnit或TestNG对Spring组件进行单元测试和集成测试。
官网对于各模块的详细介绍资料链接
二、Core Container(核心容器)
本模块由spring-core
,spring-beans
,spring-context
,spring-context-support
,and spring-expression (Spring Expression Language)
4 个模块组成。
spring-core
和spring-beans
模块,这两个模块提供了整个 Spring 框架最基础的设施:IoC (Inversion of Control,控制反转) 和 DI (Dependency Injection,依赖注入)。 这部分功能相当于所有 Spring 框架运行的基础,以前我们操作对象都需要手动的 new 对象,由对象的作用域决定对象的生命周期。使用 Spring 后,由框架提供了统一的容器来实例化、管理这些对象,并自动组织对象与对象间的关系。这种容器称为 IoC 容器,有些地方也叫 Spring Bean 容器、Spring 容器。对象之间的复杂关系(体现在代码中就是对象中成员变量,引用了另一个对象),也交给了容器来进行设置。
IoC(控制反转)
什么是 IoC
控制反转即 IoC (Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。
Spring IoC 负责创建对象,管理对象(通过依赖注入(DI),装配对象,配置对象,并且管理这些对象的整个生命周期。
IoC 的作用
- 管理对象的创建和依赖关系的维护。对象的创建并不是一件简单的事,在对象关系比较复杂时,如果依赖关系需要程序猿来维护的话,那是相当头疼的。
- 解耦,由容器去维护具体的对象。
- 托管了类的产生过程,比如我们需要在类的产生过程中做一些处理,最直接的例子就是代理,如果有容器程序可以把这部分处理交给容器,应用程序则无需去关心类是如何完成代理的。
IoC 的优点
- IoC 或 依赖注入把应用的代码量降到最低。
- 它使应用容易测试,单元测试不再需要单例和 JNDI 查找机制。
- 最小的代价和最小的侵入性使松散耦合得以实现。
- IoC 容器支持加载服务时的饿汉式初始化和懒加载。
IoC 的缺点
- 软件系统引入第三方IoC 容器,使得生成对象变得复杂,本来是两者之间的事情,凭空又增加了一条手续。在一定程度上,引入一个新的框架,增加了团队成员学习和认知的培训成本。
- IoC 容器在生成对象上是通过反射的方式,在运行效率上一定的损耗。
- 具体到IoC 框架项目来说,需要进行大量的配置,比较繁琐,对于小的项目来说,一定程度上加大了工作成本。
- 需要关注于IoC 框架的成熟度,如果引入了一个不成熟的IoC 框架,对项目整体来说也会产生一定的隐患。
DI(依赖注入)
什么是DI
相对于IoC而言,依赖注入更加准确地描述了IoC的设计理念。所谓依赖注入(Dependency Injection)就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中,即组件之间的依赖关系由容器在应用系统运行期来决定,也就是由容器动态地将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。
依赖注入的基本原则
应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由IoC容器负责,“查找资源”的逻辑应该从应用组件的代码中抽取出来,交给IoC容器负责。容器全权负责组件的装配,它会把符合依赖关系的对象通过属性(JavaBean中的setter)或者是构造器传递给需要的对象。
依赖注入的优势
依赖注入之所以更流行是因为它是一种更可取的方式:让容器全权负责依赖查询,受管组件只需要暴露JavaBean的setter方法或者带参数的构造器或者接口,使容器可以在初始化时组装对象的依赖关系。其与依赖查找方式相比,主要优势为:
- 查找定位操作与应用代码完全无关。
- 不依赖于容器的API,可以很容易地在任何容器以外使用应用对象。
- 不需要特殊的接口,绝大多数对象可以做到完全不必依赖容器。
不同类型的依赖注入实现方式
依赖注入是时下最流行的IoC实现方式,依赖注入分为接口注入(Interface Injection),Setter方法注入(Setter Injection)和构造器注入(Constructor Injection)三种方式。其中接口注入由于在灵活性和易用性比较差,从Spring4开始已被废弃。
构造器依赖注入:构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖。
Setter方法注入:Setter方法注入是容器通过调用无参构造器或无参static工厂 方法实例化bean之后,调用该bean的setter方法,即实现了基于setter的依赖注入。
构造器依赖注入和 Setter方法注入的区别
构造函数注入 | setter 注入 |
---|---|
没有部分注入 | 有部分注入 |
不会覆盖 setter 属性 | 会覆盖 setter 属性 |
任意修改都会创建一个新实例 | 任意修改不会创建一个新实例 |
适用于设置很多属性 | 适用于设置少量属性 |
两种依赖方式都可以使用,构造器注入和Setter方法注入。最好的解决方案是用构造器参数实现强制依赖,setter方法实现可选依赖。