概述
Spring 是一个企业级 J2EE 应用开发一站式解决方案,其提供的功能贯穿了项目开发的表现层、业务层和持久化层,同时,Spring 可以和其他应用框架无缝整合
Spring 的特性包括以下几个方面:
- 轻量:Spring 是一个轻量级的框架,其核心 JAR 包的大小均为 1MB 左右。从系统的资源使用上来说,Spring 也是一个轻量级的框架,在其运行期间只需少量的操作系统资源便能稳定运行
- 控制反转:Spring 的控制反转指一个对象依赖的其他对象将会在容器的初始化完成后主动将其依赖的对象传递给它,而不需要这个对象自己创建或者查找其依赖的对象。Spring 基于控制反转技术实现系统对象之间依赖的解耦。
- 面向容器:Spring 实现了对象的配置化生成和对象的生命周期管理,通过 Spring 的 XML 文件或者注解方式,应用程序可以配置每个 Bean 对象被创建和销毁的时间,以及 Bean 对象被创建的先后顺序和依赖关系
- 面向切面:Spring 提供了面向切面的编程支持,面向切面技术通过分离系统逻辑和业务逻辑来提高系统的内聚性。在具体的使用过程中,业务层只需关注并实现和业务相关的代码逻辑,而不需要关注系统功能(例如系统日志、事务支持)
- 模块化:Spring 是模块化的,应用程序在使用过程中可以根据需求引入模块(以 JAR 包依赖方式引入)来实现不同的功能
Spring 的核心 Jar 包
- Spring Core:Spring 的核心工具包
- Spring Beans:SpingIoC 的实现,通过 XML 配置文件或注解的方式实现对 Spring Bean 的管理
- Spring Context:Spring 上下文环境。用于对 Bean 关系的管理和推护等
- Spring Aspects:Spring 对 AspectJ 框架的整合和支持
- Spring Context Support:SpringContext 的扩展支持,用于支持 MVC 方面的功能
- Spring Expression Language:Spring 的表达式语言
- Spring Framework Bom:处理不同的项目依赖不同版本的 Spring 引起的版本冲突
- Spring JDBC:Spring 针对 JDBC 的封装
- Spring ORM:Spring 整合第三方 ORM 的实现,例如 Mybatis
- Spring Test:Spring 对 JUnit 等测试框架的支持
- Spring TX:Spring 提供的一致性声明式事务管理和编程式事务管理
- Spring Web:基于 Spring 构建 Web 应用开发所需的核心类
- Spring WebMVC:包含 SpringMVC 框架相关的所有类
SpringIoC 原理
SpringIoC(Inversion of Control)即“控制反转”,是一种设计思想,将对象的创建和对象之间依赖关系的维护交给容器来负责,以实现对象与对象之间的松耦合
Spring 通过一个配置文件描述 Bean 和 Bean 之间的依赖关系,利用 Java 的反射功实例化 Bean 并建立 Bean 之间的依赖关系。
Spring 在启动时会从 XML 配置文件或注解中读取应用程序提供的 Bean 配置信息,并在 Spring Bean 容器中生成一份相应的 Bean 配置注册表,然后根据这张注册表实例化 Bean,装配好 Bean 之间的依赖关系,将 Bean 实例放入缓存池,Bean 缓存池采用 HashMap 实现
Spring 为 Bean 定义了五种作用域:
- Singleton:Singleton 是单例模式,当实例类型为单例模式时,在 SpringIoC 容器中只会存在一个共享的 Bean 实例,无论有多少个 Bean 引用它,都始终指向同一个 Bean 对象。该模式在多线程下是不安全的。Singleton 作用域是 Spring 中的默认作用域
- Prototype:Prototype 是原型模式,每次通过 Spring 容器获取 Prototype 定义的 Bean 时,容器都将创建一个新的 Bean 实例,每个 Bean 实例都有自己的属性和状态。因此,对有状态的 Bean 经常使用 Prototype 作用域,而对无状态的 Bean 则使用 Singleton 作用域
- Request:Request 指在一次 HTTP 请求中容器会返回该 Bean 的同一个实例,对不同的 HTTP 请求则会创建新的 Bean 实例,并且该 Bean 实例仅在当前 HTTP 请求内有效,在当前 HTTP 请求结束后,该 Bean 实例也将随之销毁
- Session:Session 指在一次 HTTP Session 中,容器会返回该 Bean 的同一个实例,对不同的 Session 请求则会创建新的 Bean 实例,该 Bean 实例仅在当前 Session 内有效,Session 每一次都会创建新的 Bean 实例,而不同的 Bean 实例之间不共享数据,请求结束,则 Bean 实例将随之销毁
- Global Session:Global Session 类似于 Session,不过仅在 Portlet Web 应用中使用。 portlet 规范定义了构成单个 Portlet Web 应用的所有 portlet 之间共享的全局会话的概念。如果不是 Portlet Web 应用,则与 Session 无异
Spring Bean 的生命周期如下所示:
- 实例化一个Bean
- 按照 Spring 上下文对实例化的 Bean 进行配置
- 根据配置加载执行:
- 如果 Bean 实现了 BeanNameAware接 口,则会执行它实现的 setBeanName(String) 方法。该方法传递的参数是 Spring 配置文件中 Bean 的 id 值
- 如果 Bean 实现了 BeanFactoryAware 接口,则会执行它实现的 setBeanFactory(BeanFactory) 方法,该方法传递的参数是 Spring 工厂自身
- 如果 Bean 实现了 ApplicationContextAware 接口,则会执行 setApplicationContext(ApplicationContext) 方法,该方法传递的参数是 Spring 上下文
- 如果 Bean 关联了 BeanPostProcessor 接口,则会执行 postProcessBeforeInitialization(Object obj, String s) 方法,该方法在 Bean 初始化前调用,常用于定义初始化 Bean 的前置工作,比如系统缓存的初始化
- 如果 Bean 在 Spring 配置文件中配置了 init-method 属性,则会自动执行其配置的初始化方法
- 如果 Bean 关联了 BeanPostProcessor 接口,将会执行 postProcessAfterInitialization(Object obj, String s) 方法,至此,Bean 的初始化工作就完成了,应用程序可以开始使用Bean实例了
- 当 Bean 不再被需要时,会在清理阶段被清理掉、如果 Bean 实现了 DisposableBean 接口,Spring 会在退出前调用实现类的 destroy 方法
- 如果 Bean 的 Spring 配置文件中配置了 destroy-method 属性,则在 Bean 销毁前会自动调用其配置的销毁方法
SpringAOP 原理
SpringAOP 通过面向切面技术将与业务无关却为业务模块所共用的逻辑代码封装起来。以提高代码的复用率,降低模块之间的耦合度
SpringAOP 核心概念如下:
- 横切关注点:定义对哪些方法进行拦裁,以及在拦被后执行哪些操作
- 切面(Aspect):横切关注点的抽象
- 连接点(JoinPoint):指被拦截到的方法
- 切入点(PointCut):对连接点进行拦戳的定义
- 通知(Advice):拦截到连接点之后要执行的具体操作,分为前置通知、后置通知、成功通知、异常通知和环绕通知
- 目标对象:代理的目标对象
- 织入(Weave):将切面应用到目标对象并执行代理对象创建的过程
- 引入(Introduction):在运行期为类动态地添加一些方法或字段而不用修改类的代码
SpringAOP 有五种通知类型:
- 前置通知:在一个方法执行之前执行通知
- 后置通知:在一个方法执行之后执行通知,无论方法执行成功还是失败
- 成功通知:在一个方法执行成功之后执行通知,只有在方法执行成功时才执行
- 异常通知:在一个方法抛出异常时才执行
- 环绕通知:在拦截方法调用之前和之后分别执行
Spring 提供了 JDK 和 CGLib 两种方式来生成代理对象,具体生成方式由 AopProxyFactory 根据 AdvisedSupport 对象的配置来决定。Spring 默认的代理对象生成策略:如果是目标类接口,则使用 JDK 动态代理技术,否则使用 CGLib 动态代理技术
CGLib 动态代理和 JDK 动态代理的区别:JDK 只能为接口创建代理实例,而对于没有通过接口定义业务方法的类,则只能通过 CGLib 创建动态代理来实现
SpringMVC 原理
SpringMVC 中的 MVC 即模型-视图-控制器,该框架围绕一个 DispatcherServlet 改计而成,DispatcherServlet 会把请求分发给各个处理器,并支持可配置的处理器映射和视图渲染等功能
SpringMVC 的工作流程如下所示:
- 客户端发起 HTTP 请求:客户端将请求提交到 DispatcherServlet
- 寻找处理器:DispatcherServlet 控制器查询一个或多个 HandlerMapping,找到处理该请求的 Controller
- 调用处理器:DispatcherServlet 将请求提交到 Controller
- 调用业务处理逻辑并返回结果:Controller 在调用业务处理逻辑后,返回 ModelAndView
- 处理视图映射并返回模型:DispatcherServlet 查询一个或多个 ViewResolver 视图解析器,找到 ModelAndView 指定的视图
- HTTP 响应:视图负责将结果在客户端浏览器上谊染和展示