Spring 是 Java EE 编程领域的一个轻量级开源框架,同时也是针对 Bean 的生命周期进行管理的轻量级容器(lightweight container)框架。在整个框架中,各类型的功能被抽象成一个个的 Bean 并通过 Bean Factory 实现了对 Bean 生命周期的管理。
Spring 框架 是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在 核心容器 之上,核心容器定义了创建、配置 和 管理 Bean 的方式。组成 Spring 框架 的每个 模块(或组件)都可以单独存在,或者与其它一个(或多个)模块 联合实现。

补充:
Spring 的七大组成:
Spring Core(核心模块)
提供 Spring 框架的基本功能,主要组件是 BeanFactory(工厂模式的实现),BeanFactory 使用 控制反转(IOC)模式 将应用程序的 配置和依赖性规范 与实际的应用程序代码分开。
Spring AOP(Spring Aspect Oriented Programing)
通过配置管理特性,将 面向切面(AOP)的编程功能 直接集成到 Spring 中,并为 Bean 提供了事务管理服务。
Spring ORM(Object Relational Mapping)
负责框架中的 对象关系映射,提供相关 ORM 接入框架 的关系对象管理工具(JDO、Hibernate、iBatis)。
Spring DAO(Data Access Objects)
提供 管理 异常处理 和 不同数据库供应商抛出的错误消息 的异常层次结构,简化了错误处理,降低了异常代码量(如:打开和关闭连接)。
Spring Context
Spring Context 是一个 配置文件,向 Spring 框架 提供上下文信息。Spring Context 还包括 企业服务,如:JNDI、EJB、电子邮件、国际化、校验和调度功能。
Spring Web
为基于 Web 的应用程序提供 上下文,简化了 处理多部分请求 和 将请求参数绑定到 域对象 的工作。
Spring Web MVC(Spring Web Model View Controller)
Spring Web MVC 是一个 全功能的构建 Web 应用程序的 MVC 实现,Model 由 JavaBean 构成,存放于 Map;View 是一个接口,负责显示 Model;Controller 负责对 Model 和 View 的逻辑处理。
轻量
完整的 Spring 可以在一个 大小 只有 1MB 多的 JAR 文件里发布,并且 Spring 所需的处理开销也是微不足道的。
非入侵式
Spring 应用中的 对象不依赖于 Spring 的特定类。
控制反转(IOC,Inversion of Control)
控制反转 是一种 面向对象 编程的设计思想,主要内容是:设计的类 将交由 容器 去控制,而不是在 类的内部 去控制,类与类之间的关系 将交由 容器 处理,一个类 在需要调用 另一个类 时,只要调用 另一个类 在容器中注册的名字 就可以得到这个类的实例。
Spring 的 IOC 底层设计模式 采用了 工厂模式,所有的 Bean 都需要注册到 Bean 工厂中,将其初始化 和 生命周期的监控 交由 工厂实现管理;程序员 只需要按照规定的格式进行 Bean 开发,然后利用 XML 文件(SpringBoot 可通过注解) 进行 Bean 的 定义和参数配置,其它的动态生成和监控 就不需要调用者完成,而是统一交给了 平台 进行管理。
补充:
控制反转的实现方式:
依赖注入(DI,Dependency Injection)
一个 对象 依赖的其它对象 会通过被动的方式 传递进来,而不是这个 对象 自己创建或者查找 依赖对象。
实现依赖注入的关键是 IoC 容器,它的本质就是一个工厂。
依赖注入的三种实现方式:
构造方法注入
被注入对象 可以在 它的构造方法 中声明 依赖对象 的参数列表,让外部知道它需要哪些 依赖对象。然后,IoC Service Provider 会检查 被注入对象的构造方法,取得它所需要的 依赖对象列表,进而为其注入相应的对象。
构造方法注入 比较直观,对象被构造完成后,即进入 就绪状态(可以立即使用)。
setter 方法注入
被注入对象 可以为其 依赖对象所对应的属性 添加 setter 方法(setter 方法 可以更改相应的对象属性),IoC Service Provider 即可通过 setter 方法,将 相应的依赖对象 设置到被注入对象中。
setter 方法注入 相较于 构造方法注入 条件更宽松些,可以在对象构造完成之后再注入。
接口注入(不推荐)
被注入对象 如果想要 IoC Service Provider 为其注入依赖对象,就必须 实现某个接口,该接口将提供一个方法,用来为其注入依赖对象。
接口注入 相较于 前两种 依赖注入方式 步骤更为死板和繁琐。
面向切面编程(AOP,Aspect Oriented Programing)
面向切面编程 既是 一种编程思想,是对 面对对象编程(OOP)思想的补充,在 OOP 的基础进一步提高编程效率,也是 一种通过 预编译方式 和 运行期间动态代理 实现程序功能 统一维护 的技术。
AOP 是 函数式编程 的一种衍生类型,通过 AOP,可以对 业务逻辑 的各个部分进行隔离,从而使得业务逻辑各部分之间的 耦合度 降低,在提高 程序可重用性 的同时 提高了 开发效率。
例如:将 日志记录、性能统计、安全控制、事务处理、异常处理等代码 从业务逻辑代码中 独立出来,使得 在改动这些功能的代码时 不会对 业务逻辑代码 产生任何影响。
补充:AOP 术语
容器
Spring 包含并管理 应用对象的配置和生命周期,在这个意义上它是一种容器。
框架
Spring 可以将 简单的组件 配置、组成成为复杂的应用。
MVC
客户端的请求,经由 Model(模型)、View(视图)、控制器(Controller)分层处理并给予相应的反馈。
Bean 的生命周期 包括:实例化 --> 初始化 --> 调用 --> 销毁 。

Bean 的整个生命周期都是 Spring 容器自动管理的,其中只有两个环节我们可以进行干预:
补充:Bean 的作用域
默认情况下,Bean 在 Spring 容器中是单例的,我们可以通过 @Scope 修改 Bean 的作用域。
@Scope 的取值及含义:
| 取值 | 含义 |
|---|---|
| singleton(单例) | 在 Spring 容器中仅存在一个实例 |
| prototype(原型) | 每次调用 getBean() 时,都会返回一个新的实例 |
| request | 每次 HTTP 请求都会创建一个新的实例 |
| session | 同个 HTTP Session 共享一个实例 |
| globalSession | 同个全局 Session 共享一个实例 |
Spring 通过 IoC 容器来对 Bean 进行管理,我们可以通过 XML 配置 或者 注解配置,来指导 IoC 容器对 Bean 的管理。因为 注解配置 相较于 XML 配置 更为便捷,因而我们大多数时候都是通过 注解 进行配置。
管理 Bean 的相关注解:
| 注解 | 说明 |
|---|---|
| @ComponentScan | 扫描 xx包中 Bean,也可以排除指定的 Bean |
| @Component、@Repository、@Service、@Controller | 声明该类是一个 Bean |
| @Autowired、@Qualifier | 向 IoC 容器中注入 Bean |
| @Scope | 声明 Bean 的作用域 |
| @PostConstruct、@PreDestroy | 声明 Bean 生命周期中的自定义方法 |
补充:BeanFactory
BeanFactory 是 类的通用工厂,它可以 创建并管理 各种类的对象,这些对象 Spring 称之为 Bean。
BeanFactory 是 Spring 容器的顶层接口,Spring 为其提供了多种实现,最常用的是 XMLBeanDefinitionReader、DefaultListableBeanFactory。
BeanFactory 最主要的方法是 getBean(String beanName):从容器中返回特定名称的 Bean。
扩展:@Autowired 和 @Resource 的区别
@Autowired 是 Spring 提供的注解;@Resource 是 JDK 提供的注解
@Autowired 只能按类型注入;@Resource 默认名称注入,同时也支持按类型注入
@Autowired 默认情况下 要求依赖对象必须存在(如果允许为 null 值,可以设置 required 属性为 false),如果想 使用名称进行注入 则需要配合 @Qualifier 一起使用;
@Resource 的 name 属性指定 Bean 的名称,如果没有指定 name,当 注解 标注在字段上,则默认取字段的名称作为 Bean 名称寻找依赖对象;当 注解 标注在属性的 setter 方法上,则默认取属性名作为 Bean 名称寻找依赖对象;当 按照 默认名称 找不到依赖对象时,则 按类型(type 属性)进行注入。
Spring 三种循环依赖:
这三种循环依赖 只有第二种 Spring 可以通过 “三级缓存” 进行处理,其它两种 Spring 都无法处理,第一种 Spring 会直接抛出 BeanCurrentlyInCreationException 异常。
补充:
“三级缓存” 处理:
Spring 对事务进行了更高层次的抽象,为事务管理提供了一致的编程模版,使得 用户无论是选择 Hibernate、MyBatis、或是 Spring JDBC,都可以使用统一的编程模型进行事务管理。
Spring 支持的两种事务编程模型:
编程式事务
Spring 提供了 Transaction Template 模版,利用该模版我们可以通过编程的方式实现事务管理,而无需关注 资源获取、复用、释放、事务同步及异常处理等操作。
private static TransactionTemplate transactionTemplate;
声明式事务
Spring 允许我们通过声明(添加 @Transactional 注解)的方式,在 IoC 配置中指定 事务的边界和事务属性,Spring 会自动在指定的事务边界上应用事务属性。
@Transactional
public String service() {
...
}
补充:
1、@Transactional 可以标注在 类 或 方法上
2、@Transactional 的常用属性
当我们调用一个业务方法时,它的内部可能会调用其它的业务方法,以完成一个完整的业务操作。这种业务方法嵌套调用时,如果这两个方法都是要保证事务的,那么就要通过 Spring 的事务传播机制 控制 当前事务 如何传播到 被嵌套调用的业务方法中。
Spring 的 7 种事务传播方式:
| 事务传播方式 | 说明 |
|---|---|
| PROPAGATION_REQUIRED(默认传播方式) | 如果当前不存在事务,则创建一个新事务;如果当前存在事务,则加入该事务 |
| PROPAGATION_REQUIRES_NEW | 新建事务,如果当前存在事务,则将当前事务挂起 |
| PROPAGATION_SUPPORTS | 如果当前不存在事务,则以非事务执行;如果当前存在事务,则加入该事务 |
| PROPAGATION_NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,则将当前事务挂起 |
| PROPAGATION_MANDATORY | 如果当前不存在事务,则抛出异常;如果当前存在事务,则加入该事务 |
| PROPAGATION_NEVER | 以非事务方式执行操作,如果当前存在事务,则抛出异常 |
| PROPAGATION_NESTED | 如果当前不存在事务,则创建一个新事务;如果当前存在事务,则在嵌套事务内执行 |