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 简单而强大的事务管理功能,包括声明式事务和编程式事务。
- JDBC (Java DataBase Connectivity)
- Web
- WebMVC
- MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。
- WebFlux
- 基于 Reactive 库的响应式的 Web 开发框架
- WebSocket
- Spring 4.0 的一个最大更新是增加了对 Websocket 的支持。
- Websocket 提供了一个在 Web 应用中实现高效、双向通讯,需考虑客户端(浏览器)和服务端之间高频和低延时消息交换的机制。
- 一般的应用场景有:在线交易、网页聊天、游戏、协作、数据可视化等。
- WebMVC
- AOP
- AOP
- 通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。
- Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
- Aspects
- 该模块为与 AspectJ 的集成提供支持。
- Instrumentation
- 该层为类检测和类加载器实现提供支持。
- AOP
- 其它
- JMS (Java Messaging Service)
- 提供了一个 JMS 集成框架,简化了 JMS API 的使用。
- Test
- 该模块为使用 JUnit 和 TestNG 进行测试提供支持。
- Messaging
- 该模块为 STOMP 提供支持。它还支持注解编程模型,该模型用于从 WebSocket 客户端路由和处理 STOMP 消息。
- JMS (Java Messaging Service)
使用 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 对象
- 销毁
- 如果 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
- JDK 动态代理
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 。