Spring 整体

什么是 Spring Framework?

Spring 是一个开源应用框架,旨在降低应用程序开发的复杂度。

  • 它是轻量级、松散耦合的。
  • 它具有分层体系结构,允许用户选择组件,同时还为 J2EE 应用程序开发提供了一个有凝聚力的框架。
  • 它可以集成其他框架,如 Spring MVC、Hibernate、MyBatis等,所以又称为框架的框架( 粘合剂、脚手架 )。

Spring Framework 中有多少个模块,它们分别是什么?

  • Spring 核心容器
    • Spring Core
    • Spring Bean
      • 核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC)模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
    • Spring Context
      • Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、事件机制、校验和调度功能。
    • SpEL (Spring Expression Language)
      • Spring 表达式语言全称为 “Spring Expression Language”,缩写为 “SpEL” ,类似于 Struts2 中使用的 OGNL 表达式语言,能在运行时构建复杂表达式、存取对象图属性、对象方法调用等等,并且能与 Spring 功能完美整合,如能用来配置 Bean 定义。
  • 数据访问
    • JDBC (Java DataBase Connectivity)
      • Spring 对 JDBC 的封装模块,提供了对关系数据库的访问。
    • ORM (Object Relational Mapping)
      • Spring ORM 模块,提供了对 hibernate5 和 JPA 的集成。
      • hibernate5 是一个 ORM 框架。
      • JPA 是一个 Java 持久化 API 。
    • OXM (Object XML Mappers)
      • Spring 提供了一套类似 ORM 的映射机制,用来将 Java 对象和 XML 文件进行映射。这就是 Spring 的对象 XML 映射功能,有时候也成为 XML 的序列化和反序列化。
    • Transaction
      • Spring 简单而强大的事务管理功能,包括声明式事务和编程式事务。
  • Web
    • WebMVC
      • MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。
    • WebFlux
      • 基于 Reactive 库的响应式的 Web 开发框架
    • WebSocket
      • Spring 4.0 的一个最大更新是增加了对 Websocket 的支持。
      • Websocket 提供了一个在 Web 应用中实现高效、双向通讯,需考虑客户端(浏览器)和服务端之间高频和低延时消息交换的机制。
      • 一般的应用场景有:在线交易、网页聊天、游戏、协作、数据可视化等。
  • AOP
    • AOP
      • 通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。
      • Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
    • Aspects
      • 该模块为与 AspectJ 的集成提供支持。
    • Instrumentation
      • 该层为类检测和类加载器实现提供支持。
  • 其它
    • JMS (Java Messaging Service)
      • 提供了一个 JMS 集成框架,简化了 JMS API 的使用。
    • Test
      • 该模块为使用 JUnit 和 TestNG 进行测试提供支持。
    • Messaging
      • 该模块为 STOMP 提供支持。它还支持注解编程模型,该模型用于从 WebSocket 客户端路由和处理 STOMP 消息。

使用 Spring 框架能带来哪些好处?

  • DI :Dependency Injection(DI) 方法,使得构造器和 JavaBean、properties 文件中的依赖关系一目了然。
  • 轻量级:与 EJB 容器相比较,IoC 容器更加趋向于轻量级。这样一来 IoC 容器在有限的内存和 CPU 资源的情况下,进行应用程序的开发和发布就变得十分有利。
  • 面向切面编程(AOP): Spring 支持面向切面编程,同时把应用的业务逻辑与系统的服务分离开来。
  • 集成主流框架:Spring 并没有闭门造车,Spring 集成了已有的技术栈,比如 ORM 框架、Logging 日期框架、J2EE、Quartz 和 JDK Timer ,以及其他视图技术。
  • 模块化:Spring 框架是按照模块的形式来组织的。由包和类的命名,就可以看出其所属的模块,开发者仅仅需要选用他们需要的模块即可。
  • 便捷的测试:要 测试一项用Spring开发的应用程序 十分简单,因为测试相关的环境代码都已经囊括在框架中了。更加简单的是,利用 JavaBean 形式的 POJO 类,可以很方便的利用依赖注入来写入测试数据。
  • Web 框架:Spring 的 Web 框架亦是一个精心设计的 Web MVC 框架,为开发者们在 Web 框架的选择上提供了一个除了主流框架比如 Struts 、过度设计的、不流行 Web 框架的以外的有力选项。
  • 事务管理:Spring 提供了一个便捷的事务管理接口,适用于小型的本地事物处理(比如在单 DB 的环境下)和复杂的共同事物处理(比如利用 JTA 的复杂 DB 环境)。
  • 异常处理:Spring 提供一个方便的 API ,将特定技术的异常(由JDBC, Hibernate, 或 JDO 抛出)转化为一致的、Unchecked 异常。

缺点:

  • 每个框架都有的问题,调试阶段不直观,后期的 bug 对应阶段,不容易判断问题所在。要花一定的时间去理解它。
  • 把很多 JavaEE 的东西封装了,在满足快速开发高质量程序的同时,隐藏了实现细节。

Spring 框架中都用到了哪些设计模式?

  • 代理模式 — 在 AOP 和 remoting 中被用的比较多。
  • 单例模式 — 在 Spring 配置文件中定义的 Bean 默认为单例模式。
  • 模板方法 — 用来解决代码重复的问题。比如 RestTemplate、JmsTemplate、JdbcTemplate 。
  • 前端控制器 — Spring提供了 DispatcherServlet 来对请求进行分发。
  • 视图帮助(View Helper) — Spring 提供了一系列的 JSP 标签,高效宏来辅助将分散的代码整合在视图里。
  • 依赖注入 — 贯穿于 BeanFactory / ApplicationContext 接口的核心理念。
  • 工厂模式 — BeanFactory 用来创建对象的实例。

Spring IoC

什么是 Spring IoC 容器?

Spring 框架的核心是 Spring IoC 容器。容器创建 Bean 对象,将它们装配在一起,配置它们并管理它们的完整生命周期。

  • Spring 容器使用依赖注入来管理组成应用程序的 Bean 对象。
  • 容器通过读取提供的配置元数据 Bean Definition 来接收对象进行实例化,配置和组装的指令。
  • 该配置元数据 Bean Definition 可以通过 XML,Java 注解或 Java Config 代码提供。

什么是依赖注入?

  • 在依赖注入中,你不必主动、手动创建对象,但必须描述如何创建它们。
  • 你不是直接在代码中将组件和服务连接在一起,而是描述配置文件中哪些组件需要哪些服务。
  • 然后,再由 IoC 容器将它们装配在一起。
  • 另外,依赖注入的英文缩写是 Dependency Injection ,简称 DI 。

IoC 和 DI 有什么区别?

IoC是思想,DI是实现

可以通过多少种方式完成依赖注入?

  • 接口注入
  • 构造函数注入
  • setter 注入

目前,在 Spring Framework 中,仅使用构造函数和 setter 注入这两种方式。

构造函数注入 setter 注入
没有部分注入 有部分注入
不会覆盖 setter 属性 会覆盖 setter 属性
任意修改都会创建一个新实例 任意修改不会创建一个新实例
适用于设置很多属性 适用于设置少量属性

Spring 中有多少种 IoC 容器?

Spring 提供了两种( 不是“个” ) IoC 容器,分别是 BeanFactory、ApplicationContext 。

  • BeanFactory
    • BeanFactory ,就像一个包含 Bean 集合的工厂类。它会在客户端要求时实例化 Bean 对象。
  • ApplicationContext
    • ApplicationContext 接口扩展了 BeanFactory 接口,它在 BeanFactory 基础上提供了一些额外的功能。
    • MessageSource :管理 message ,实现国际化等功能。
    • ApplicationEventPublisher :事件发布。
    • ResourcePatternResolver :多资源加载。
    • EnvironmentCapable :系统 Environment(profile + Properties)相关。
    • Lifecycle :管理生命周期。
    • Closable :关闭,释放资源
    • InitializingBean:自定义初始化。
    • BeanNameAware:设置 beanName 的 Aware 接口。
    • ApplicationContext 会自动初始化非懒加载的 Bean 对象们。
BeanFactory ApplicationContext
它使用懒加载 它使用即时加载
它使用语法显式提供资源对象 它自己创建和管理资源对象
不支持国际化 支持国际化
不支持基于依赖的注解 支持基于依赖的注解

BeanFactory 也被称为低级容器,而 ApplicationContext 被称为高级容器。

请介绍下常用的 BeanFactory 容器?

BeanFactory 最常用的是 XmlBeanFactory 。它可以根据 XML 文件中定义的内容,创建相应的 Bean。

请介绍下常用的 ApplicationContext 容器?

  • ClassPathXmlApplicationContext :从 ClassPath 的 XML 配置文件中读取上下文,并生成上下文定义。应用程序上下文从程序环境变量中取得。
  • FileSystemXmlApplicationContext :由文件系统中的XML配置文件读取上下文。
  • XmlWebApplicationContext :由 Web 应用的XML文件读取上下文。
  • springboot:ConfigServletWebServerApplicationContext

列举一些 IoC 的一些好处?

  • 它将最小化应用程序中的代码量。
  • 它以最小的影响和最少的侵入机制促进松耦合。
  • 它支持即时的实例化和延迟加载 Bean 对象。
  • 它将使您的应用程序易于测试,因为它不需要单元测试用例中的任何单例或 JNDI 查找机制。

简述 Spring IoC 的实现机制?

Spring 中的 IoC 的实现原理,就是工厂模式加反射机制。

Spring 框架中有哪些不同类型的事件?

  • 上下文更新事件(ContextRefreshedEvent):该事件会在ApplicationContext 被初始化或者更新时发布。也可以在调用ConfigurableApplicationContext 接口中的 #refresh() 方法时被触发。
  • 上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext 的 #start() 方法开始/重新开始容器时触发该事件。
  • 上下文停止事件(ContextStoppedEvent):当容器调用 ConfigurableApplicationContext 的 #stop() 方法停止容器时触发该事件。
  • 上下文关闭事件(ContextClosedEvent):当ApplicationContext 被关闭时触发该事件。容器被关闭时,其管理的所有单例 Bean 都被销毁。
  • 请求处理事件(RequestHandledEvent):在 Web应用中,当一个HTTP 请求(request)结束触发该事件。
  • 自定义事件
    • 继承ApplicationContext。
    • 为了监听这个事件,还需要创建一个监听器。
    • 之后通过 ApplicationContext 接口的 #publishEvent(Object event) 方法,来发布自定义事件。

Spring Bean

什么是 Spring Bean ?

  • Bean 由 Spring IoC 容器实例化,配置,装配和管理。
  • Bean 是基于用户提供给 IoC 容器的配置元数据 Bean Definition 创建。

Spring 有哪些配置方式

  • XML 配置文件
    • Bean 所需的依赖项和服务在 XML 格式的配置文件中指定。这些配置文件通常包含许多 bean 定义和特定于应用程序的配置选项。它们通常以 bean 标签开头。
  • 注解配置
    • 需要在xml中开启
  • Java Config 配置
    • Spring 的 Java 配置是通过使用 @Bean 和 @Configuration 来实现。

Spring 支持几种 Bean Scope ?

  • Singleton - 每个 Spring IoC 容器仅有一个单 Bean 实例。默认
  • Prototype - 每次请求都会产生一个新的实例。
  • Request - 每一次 HTTP 请求都会产生一个新的 Bean 实例,并且该 Bean 仅在当前 HTTP 请求内有效。
  • Session - 每一个的 Session 都会产生一个新的 Bean 实例,同时该 Bean 仅在当前 HTTP Session 内有效。
  • Application - 每一个 Web Application 都会产生一个新的 Bean ,同时该 Bean 仅在当前 Web Application 内有效。
  • 自定义Scope

Spring Bean 在容器的生命周期是什么样的?

  • 初始化
    • 实例化 Bean 对象
      • Spring 容器根据配置中的 Bean Definition(定义)中实例化 Bean 对象。
      • Spring 使用依赖注入填充所有属性,如 Bean 中所定义的配置。
    • Aware 相关的属性,注入到 Bean 对象
      • 如果 Bean 实现 BeanNameAware 接口,则工厂通过传递 Bean 的 beanName 来调用 #setBeanName(String name) 方法。
      • 如果 Bean 实现 BeanFactoryAware 接口,工厂通过传递自身的实例来调用 #setBeanFactory(BeanFactory beanFactory) 方法。
    • 调用相应的方法,进一步初始化 Bean 对象
      • 如果存在与 Bean 关联的任何 BeanPostProcessor 们,则调用 #preProcessBeforeInitialization(Object bean, String beanName) 方法。
      • 如果 Bean 实现 InitializingBean 接口,则会调用 #afterPropertiesSet() 方法。
      • 如果为 Bean 指定了 init 方法(例如 的 init-method 属性),那么将调用该方法。
      • 如果存在与 Bean 关联的任何 BeanPostProcessor 们,则将调用 #postProcessAfterInitialization(Object bean, String beanName) 方法。
  • 销毁
    • 如果 Bean 实现 DisposableBean 接口,当 spring 容器关闭时,会调用 #destroy() 方法。
    • 如果为 bean 指定了 destroy 方法(例如 的 destroy-method 属性),那么将调用该方法。

什么是 Spring 的内部 bean?

只有将 Bean 仅用作另一个 Bean 的属性时,才能将 Bean 声明为内部 Bean。

什么是 Spring 装配?

当 Bean 在 Spring 容器中组合在一起时,它被称为装配或 Bean 装配。Spring 容器需要知道需要什么 Bean 以及容器应该如何使用依赖注入来将 Bean 绑定在一起,同时装配 Bean 。
DI的过程

自动装配有哪些方式?

  • no - 这是默认设置,表示没有自动装配。应使用显式 Bean 引用进行装配。
  • byName - 它根据 Bean 的名称注入对象依赖项。它匹配并装配其属性与 XML 文件中由相同名称定义的 Bean 。
  • 【最常用】byType - 它根据类型注入对象依赖项。如果属性的类型与 XML 文件中的一个 Bean 类型匹配,则匹配并装配属性。
  • 构造函数 - 它通过调用类的构造函数来注入依赖项。它有大量的参数。
  • autodetect - 首先容器尝试通过构造函数使用 autowire 装配,如果不能,则尝试通过 byType 自动装配。

自动装配有什么局限?

  • 覆盖的可能性 - 您始终可以使用 设置指定依赖项,这将覆盖自动装配。
  • 基本元数据类型 - 简单属性(如原数据类型,字符串和类)无法自动装配。
  • 令人困惑的性质 - 总是喜欢使用明确的装配,因为自动装配不太精确。

解释什么叫延迟加载?

默认情况下,容器启动之后会将所有作用域为单例的 Bean 都创建好,但是有的业务场景我们并不需要它提前都创建好。此时,我们可以在Bean 中设置 lzay-init = “true” 。

Spring 框架中的单例 Bean 是线程安全的么?

Spring 框架并没有对单例 Bean 进行任何多线程的封装处理。
安全问题需要开发者自行去搞定
当然,但实际上,大部分的 Spring Bean 并没有可变的状态(比如Serview 类和 DAO 类),所以在某种程度上说 Spring 的单例 Bean 是线程安全的。

Spring Bean 怎么解决循环依赖的问题?

三级缓存

  • singletonObjects
  • earlySingletonObjects
  • singletonFactories

在singletonObjects获取不到时,在earlySingletonObjects获取
在earlySingletonObjects获取不到时,在singletonFactories获取
在singletonFactories获取不到时,bean初始化,并可以由ObjectFactory#getObject()
在singletonFactories获取到时,放入earlySingletonObjects,并在singletonFactories删除
直到bean创建完成,会从earlySingletonObjects转移动到singletonObjects,供其他对象使用

Spring 注解

什么是基于注解的容器配置?

Spring 的 Java 配置是通过使用 @Bean 和 @Configuration 来实现。

如何在 Spring 中启动注解装配?

<context:annotation-config />

@Component, @Controller, @Repository, @Service 有何区别?

  • @Component :它将 Java 类标记为 Bean 。它是任何 Spring 管理组件的通用构造型。
  • @Controller :它将一个类标记为 Spring Web MVC 控制器。
  • @Service :此注解是组件注解的特化。它不会对 @Component 注解提供任何其他行为。您可以在服务层类中使用 @Service 而不是 @Component ,因为它以更好的方式指定了意图。
  • @Repository :这个注解是具有类似用途和功能的 @Component 注解的特化。它为 DAO 提供了额外的好处。它将 DAO 导入 IoC 容器,并使未经检查的异常有资格转换为 Spring DataAccessException 。

实质都是封装了@Component,只是为了区分功能

@Required 注解有什么用?

@Required 注解,应用于 Bean 属性 setter 方法。

  • 此注解仅指示必须在配置时使用 Bean 定义中的显式属性值或使用自动装配填充受影响的 Bean 属性。
  • 如果尚未填充受影响的 Bean 属性,则容器将抛出 BeanInitializationException 异常。

@Autowired 注解有什么用?

@Autowired 注解,可以更准确地控制应该在何处以及如何进行自动装配。

  • 此注解用于在 setter 方法,构造函数,具有任意名称或多个参数的属性或方法上自动装配 Bean。
  • 默认情况下,它是类型驱动的注入。

@Qualifier 注解有什么用?

当你创建多个相同类型的 Bean ,并希望仅使用属性装配其中一个 Bean 时,您可以使用 @Qualifier 注解和 @Autowired 通过指定 ID 应该装配哪个确切的 Bean 来消除歧义。

Spring AOP

  • AOP
  • Aspect
  • JoinPoint
  • PointCut
  • Advice
  • Target
  • AOP Proxy
  • Weaving

什么是 AOP ?

AOP(Aspect-Oriented Programming),即面向切面编程, 它与 OOP( Object-Oriented Programming, 面向对象编程) 相辅相成, 提供了与 OOP 不同的抽象软件结构的视角。

  • 在 OOP 中,以类( Class )作为基本单元
  • 在 AOP 中,以切面( Aspect )作为基本单元。

什么是 Aspect ?

Aspect 由 PointCut 和 Advice 组成。

  • 它既包含了横切逻辑的定义,也包括了连接点的定义。
  • Spring AOP 就是负责实施切面的框架,它将切面所定义的横切逻辑编织到切面所指定的连接点中。

什么是 JoinPoint ?

切点,嵌入点,连接点
在 Spring AOP 中,JoinPoint 总是方法的执行点。

什么是 PointCut ?

PointCut ,匹配 JoinPoint 的谓词(a predicate that matches join points)。

  • Advice 是和特定的 PointCut 关联的,并且在 PointCut 相匹配的 JoinPoint 中执行。即 Advice => PointCut => JoinPoint
  • 在 Spring 中, 所有的方法都可以认为是 JoinPoint ,但是我们并不希望在所有的方法上都添加 Advice 。而 PointCut 的作用,就是提供一组规则(使用 AspectJ PointCut expression language 来描述) 来匹配 JoinPoint ,给满足规则的 JoinPoint 添加 Advice 。

关于 JoinPoint 和 PointCut 的区别

JoinPoint 和 PointCut 本质上就是两个不同纬度上的东西。

  • 在 Spring AOP 中,所有的方法执行都是 JoinPoint 。而 PointCut 是一个描述信息,它修饰的是 JoinPoint ,通过 PointCut ,我们就可以确定哪些 JoinPoint 可以被织入 Advice 。
  • Advice 是在 JoinPoint 上执行的,而 PointCut 规定了哪些 JoinPoint 可以执行哪些 Advice 。

什么是 Advice ?

Advice ,通知。

  • 特定 JoinPoint 处的 Aspect 所采取的动作称为 Advice 。
  • Spring AOP 使用一个 Advice 作为拦截器,在 JoinPoint “周围”维护一系列的拦截器。

有哪些类型的 Advice?

  • Before - 这些类型的 Advice 在 JoinPoint 方法之前执行,并使用 @Before 注解标记进行配置。
  • After Returning - 这些类型的 Advice 在连接点方法正常执行后执行,并使用 @AfterReturning 注解标记进行配置。
  • After Throwing - 这些类型的 Advice 仅在 JoinPoint 方法通过抛出异常退出并使用 @AfterThrowing 注解标记配置时执行。
  • After Finally - 这些类型的 Advice 在连接点方法之后执行,无论方法退出是正常还是异常返回,并使用 @After 注解标记进行配置。
  • Around - 这些类型的 Advice 在连接点之前和之后执行,并使用 @Around 注解标记进行配置。

什么是 Target ?

Target ,织入 Advice 的目标对象。目标对象也被称为 Advised Object 。

  • 因为 Spring AOP 使用运行时代理的方式来实现 Aspect ,因此 Advised Object 总是一个代理对象(Proxied Object) 。
  • 注意, Advised Object 指的不是原来的对象,而是织入 Advice 后所产生的代理对象。
  • Advice + Target Object = Advised Object = Proxy 。

AOP 有哪些实现方式?

  • 静态代理 - 指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强。
    • 编译时编织(特殊编译器实现)
    • 类加载时编织(特殊的类加载器实现)
  • 动态代理 - 在运行时在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强。
    • JDK 动态代理
      • JDK 动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是 InvocationHandler 接口和 Proxy 类。
    • CGLIB
      • 如果目标类没有实现接口,那么 Spring AOP 会选择使用 CGLIB 来动态代理目标类。当然,Spring 也支持配置,强制使用 CGLIB 动态代理。
      • CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为 final ,那么它是无法使用 CGLIB 做动态代理的。
    • spring boot 2.0 默认CGLIB 切换的话需要spring.aop.proxy-target-class = false

Spring AOP and AspectJ AOP 有什么区别?

  • 代理方式不同
    • Spring AOP 基于动态代理方式实现。
    • AspectJ AOP 基于静态代理方式实现。
  • PointCut 支持力度不同
    • Spring AOP 仅支持方法级别的 PointCut 。
    • AspectJ AOP 提供了完全的 AOP 支持,它还支持属性级别的 PointCut 。

什么是编织(Weaving)?

为了创建一个 Advice 对象而链接一个 Aspect 和其它应用类型或对象,称为编织(Weaving)。

Spring 如何使用 AOP 切面?

  • 基于 XML 方式的切面实现。
  • 基于 注解 方式的切面实现。

Spring Transaction

什么是事务?

事务就是对一系列的数据库操作(比如插入多条数据)进行统一的提交或回滚操作,如果插入成功,那么一起成功,如果中间有一条出现异常,那么回滚之前的所有操作。

事务的特性指的是?

  • A 原子性
  • C 一致性
  • I 隔离性
  • D 持久性

列举 Spring 支持的事务管理类型?

  • 声明式事务:通过使用注解或基于 XML 的配置事务,从而事务管理与业务代码分离。
  • 编程式事务:通过编码的方式实现事务管理,需要在代码中显式的调用事务的获得、提交、回滚。它为您提供极大的灵活性,但维护起来非常困难。

Spring 事务如何和不同的数据持久层框架做集成?

  • 首先,我们先明确下,这里数据持久层框架,指的是 Spring JDBC、Hibernate、Spring JPA、MyBatis 等等。
  • 然后,Spring 事务的管理,是通过 org.springframework.transaction.PlatformTransactionManager 进行管理
    • PlatformTransactionManager 是负责事务管理的接口,一共有三个接口方法,分别负责事务的获得、提交、回滚。
    • #getTransaction(TransactionDefinition definition) 方法,根据事务定义 TransactionDefinition ,获得 TransactionStatus 。
      • 为什么不是创建事务呢?因为如果当前如果已经有事务,则不会进行创建,一般来说会跟当前线程进行绑定。如果不存在事务,则进行创建。
      • 为什么返回的是 TransactionStatus 对象?在 TransactionStatus 中,不仅仅包含事务属性,还包含事务的其它信息,例如是否只读、是否为新创建的事务等等。😈 下面,也会详细解析 TransactionStatus 。
      • 事务 TransactionDefinition 是什么?😈 下面,也会详细解析 TransactionStatus 。