三、Java 第二春 - Spring 框架
Spring 是一个支持快速开发 Java EE 应用程序的框架。它提供了一系列底层容器和基础设施,并可以和大量常用的开源框架无缝集成,是开发 Java EE 程序的必备。
1. 技能点
1.1 IOC 容器
Spring 的核心就是提供了一个 IoC 容器,它可以管理所有轻量级的 JavaBean 组件,提供的底层服务包括组件的生命周期管理、配置和组装服务、AOP 支持,以及建立在 AOP 基础上的声明式事务服务等。
1.1.1 IOC
简单解释:IoC 全称 Inversion of Control(控制反转,也叫 DI:Dependency Injection 依赖注入),它解决了一个很重要的问题:将组件的创建+配置与组件的使用相分离,并且,由IoC容器负责管理组件的生命周期。
之前的模式:传统的应用程序中,控制权在程序本身,程序的控制流程完全由开发者控制,一个组件如果要使用另一个组件,必须先知道如何正确地创建它。
使用 IOC 容器后:控制权发生了反转,即从应用程序转移到了IoC容器,所有组件不再由应用程序自己创建和配置,而是由IoC容器负责,这样,应用程序只需要直接使用已经创建好并且配置好的组件。
直观感受:之前各组件间嵌套使用时,会写很多 new 代码,但使用 Spring 后,只需简单注入,即可使用该组件。
核心思想:由 spring 来负责对象的创建,在创建对象的过程中,spring 会自动根据依赖关系将他依赖的对象注入到当前对象中,这就是依赖注入,依赖注入本质上是 spring bean 属性注入的一种,只不过这个属性是一个对象属性而已。
1.1.2 相关注解
- @Component:定义了一个 Bean;自动为我们创建一个单例(Singleton),即容器初始化时创建 Bean,容器关闭前销毁 Bean。在容器运行期间,我们调用
getBean(Class)
获取到的Bean总是同一个实例。 - @Autowired:把指定类型的 Bean 注入到指定的字段中;
- @ComponentScan:告诉容器,自动搜索当前类所在的包以及子包,把所有标注为
@Component
的 Bean 自动创建出来,并根据@Autowired
进行装配; - Bean 的初始化和清理方法上可以使用标记
@PostConstruct
和@PreDestroy;
- @PropertySource:自动读取配置文件
- 先通过一个简单的 JavaBean 持有所有的配置,例如,一个
SmtpConfig,
然后,在需要读取的地方,使用#{smtpConfig.host}
注入。
1.2 AOP
AOP:本质就是一个动态代理,让我们把一些常用功能如权限检查、日志、事务等,从每个业务方法中剥离出来。AOP 对调用方法进行拦截,并在拦截前后进行安全检查、日志、事务等处理,就相当于完成了所有业务功能。
现在是 “迷惑时间”,来看看在 AOP 中,能创造出多少使人困惑的概念(看看就行):
- Aspect:切面,即一个横跨多个核心逻辑的功能,或者称之为系统关注点;
- Joinpoint:连接点,即定义在应用程序流程的何处插入切面的执行;
- Pointcut:切入点,即一组连接点的集合;
- Advice:增强,指特定连接点上执行的动作;
- Introduction:引介,指为一个已有的Java对象动态地增加新的接口;
- Weaving:织入,指将切面整合到程序的执行流程中;
- Interceptor:拦截器,是一种实现增强的方式;
- Target Object:目标对象,即真正执行业务的核心逻辑对象;
- AOP Proxy:AOP代理,是客户端持有的增强后的对象引用。
参考文章:装配AOP - 廖雪峰的官方网站
如何在 Spring 中使用 AOP(不推荐,最佳实践看下文):
- 定义执行方法,并在方法上通过 AspectJ 的注解告诉 Spring 应该在何处调用此方法;
- 标记
@Component
和@Aspect
; - 在
@Configuration
类上标注@EnableAspectJAutoProxy
。
拦截器类型:
-
@Before:这种拦截器先执行拦截代码,再执行目标代码。如果拦截器抛异常,那么目标代码就不执行了;
-
@After:这种拦截器先执行目标代码,再执行拦截器代码。无论目标代码是否抛异常,拦截器代码都会执行;
-
@AfterReturning:和@After不同的是,只有当目标代码正常返回时,才执行拦截器代码;
-
@AfterThrowing:和@After不同的是,只有当目标代码抛出了异常时,才执行拦截器代码;
-
@Around:能完全控制目标代码是否执行,并可以在执行前后、抛异常后执行任意拦截代码,可以说是包含了上面所有功能。
最佳实践:使用注解装配 AOP(参考文章:使用注解装配AOP - 廖雪峰的官方网站)
定义注解 -> 定义 Aspect,使用 @Around("@annotation(name)")
实现装配 -> 在需要使用的方法上加上注解。
1.3 MyBatis
一种半自动化 ORM 框架,只负责把 ResultSet 自动映射到 Java Bean,或者自动填充 Java Bean 参数,但仍需自己写出SQL。
四、Web 开发利器 - Spring MVC 框架
在经历了手撸 Servlet 进行 Web 开发后,我们终于可以使用基于 Servlet 封装的 MVC 框架了。果然,计算机世界的永恒定律:封装封装再封装、缓存缓存再缓存,无限套娃。
1. 技能点
1.1 启动顺序
使用 Spring MVC 时,整个 Web 应用程序按如下顺序启动:
- 启动 Tomcat 服务器;
- Tomcat 读取 web.xml 并初始化 DispatcherServlet;
- DispatcherServlet 创建 IoC 容器并自动注册到 ServletContext 中。
启动后,浏览器发出的 HTTP 请求全部由 DispatcherServlet 接收,并根据配置转发到指定 Controller 的指定方法处理。
1.2 Interceptor 拦截器
拦截范围:拦截 Controller 方法,它实际上就相当于基于AOP的方法拦截。
使用Interceptor的好处:Interceptor 本身是 Spring 管理的 Bean,因此注入任意 Bean 都非常简单。此外,可以应用多个Interceptor,并通过简单的 @Order
指定顺序。
最佳实践:实现一个 Interceptor -> 在 WebMvcConfigurer 中注册所有的 Interceptor
具体实现:一个 Interceptor 必须实现
HandlerInterceptor
接口,可以选择实现preHandle()
、postHandle()
和afterCompletion()
方法。
preHandle()
是 Controller 方法调用前执行,postHandle()
是Controller方法正常返回后执行。afterCompletion()
无论 Controller 方法是否抛异常都会执行,参数ex
就是Controller方法抛出的异常(未抛出异常是null
)。- 在
preHandle()
中,也可以直接处理响应,然后返回false
表示无需调用Controller方法继续处理了,通常在认证或者安全检查失败时直接返回错误响应。
五、开箱即用 - Spring Boot 套件
Spring Boot 是一个基于 Spring 的套件,它帮我们预组装了 Spring 的一系列组件,以便以尽可能少的代码和配置来开发基于 Spring 的Java 应用程序。Spring Boot 的目标就是提供一个开箱即用的应用程序架构,我们基于 Spring Boot 的预置结构继续开发,省时省力。
启动 Spring Boot 应用程序只需要一行代码加上一个注解 @SpringBootApplication
,该注解实际上又包含了:
- @SpringBootConfiguration
- @Configuration
- @EnableAutoConfiguration
- @AutoConfigurationPackage
- @ComponentScan
这样一个注解就相当于启动了自动配置和自动扫描。
Spring Boot 有非常强大的 AutoConfiguration 功能,它是通过自动扫描+条件装配实现的。
TODO(挖坑,闲了再写):
- 事务相关
- 分布式
- 云原生
参考文章: