1.spring 事务传播行为是什么,默认是哪个
| 传播行为 | 描述 | 适用场景 |
|---|---|---|
| REQUIRED(默认) | 如果有事务则加入,否则创建新事务 | 大多数业务方法,默认行为。 |
| SUPPORTS | 如果有事务则加入,否则不使用事务 | 可选事务的方法。 |
| MANDATORY | 当前必须在事务中执行,若无事务则抛出异常 | 必须在事务中执行的方法。 |
| REQUIRES_NEW | 每次执行都创建新的事务,挂起当前事务 | 需要强制新建事务且不依赖于外部事务的场景。 |
| NOT_SUPPORTED | 暂时挂起当前事务,执行时不使用事务 | 方法不需要事务的场景。 |
| NEVER | 必须没有事务,若有事务则抛出异常 | 明确不需要事务的方法。 |
| NESTED | 如果有事务,则创建一个嵌套事务,支持提交或回滚 | 在事务中执行多个子事务,并允许子事务独立提交或回滚的场景。 |
2.spring实现事务的方式有哪些 事务原理是什么
-
声明式事务(推荐):
- 优先使用
@Transactional,简洁高效。 - 配合
TransactionManager和 AOP,无侵入式管理。
- 优先使用
-
编程式事务:
- 适用于需要动态控制事务或处理复杂逻辑的场景。
TransactionTemplate比直接使用PlatformTransactionManager更简洁。
-
AspectJ:
- 当 Spring AOP 代理失效(如私有方法)时,可考虑使用,但需权衡复杂度。
这是 Spring 推荐的事务管理方式,通常使用 @Transactional 注解来声明事务。
@Transactional原理
@Transactional 是 Spring 提供的声明式事务管理注解,其核心原理基于 AOP(面向切面编程) 和 动态代理,通过拦截方法调用并管理事务边界。以下是其关键机制:
方法调用 → 代理拦截 → 开启事务 → 执行方法 → 提交/回滚 → 释放资源
1. AOP 代理机制
- 代理对象:Spring 为目标 Bean 生成代理(JDK 动态代理或 CGLIB),拦截带有
@Transactional的方法。 - 自调用失效:同一类中方法 A 调用方法 B(均带
@Transactional),因绕过代理,事务失效。
2. 事务拦截流程
-
方法调用拦截:代理对象捕获被
@Transactional注解的方法调用。 -
事务管理:通过
TransactionInterceptor执行以下步骤:- 开启事务:通过
PlatformTransactionManager开启新事务。 - 执行方法:调用原始方法,执行数据库操作。
- 提交/回滚:根据执行结果(是否抛出异常)决定提交或回滚事务。
- 开启事务:通过
3. 事务属性配置
- 传播行为(Propagation):定义事务边界(如
REQUIRED、REQUIRES_NEW)。 - 隔离级别(Isolation):设置事务隔离级别(如
READ_COMMITTED)。 - 超时(Timeout):事务最大执行时间(秒)。
- 只读(ReadOnly):优化只读事务(如禁用脏读检查)。
- 回滚规则(RollbackFor):指定触发回滚的异常类型(默认
RuntimeException)。
4. 核心组件
-
TransactionManager:事务管理器(如DataSourceTransactionManager),实际管理数据库连接和事务。 -
TransactionAttribute:封装事务属性(传播行为、隔离级别等)。 -
TransactionSynchronizationManager:管理事务同步资源(如保存点、连接持有)。
5. 异常回滚机制
- 默认回滚:抛出
RuntimeException或Error时回滚。 - 自定义回滚:通过
rollbackFor指定其他异常类型(如@Transactional(rollbackFor = BusinessException.class))。
6. 实现关键类
-
TransactionInterceptor:核心拦截器,处理事务逻辑。 -
BeanFactoryTransactionAttributeSourceAdvisor:AOP 通知,关联事务属性与切点。
3.spring 事务失效场景
- 检查代理机制:确认是否自调用,是否通过代理对象调用方法。
- 验证数据库引擎:确保使用支持事务的引擎(如 InnoDB)。
- 检查异常类型:确认是否抛出了
RuntimeException或配置了rollbackFor。 - 查看事务传播行为:确认传播属性是否符合预期。
- 检查 Bean 管理:确认
@Transactional类已被 Spring 管理。 - 分析日志:通过
@Slf4j或 AOP 打印事务开启/提交/回滚日志。
4.spring 为什么自调用场景会失效
自调用为何绕过代理?
- 目标对象直接调用方法:
当类内部方法 A 调用方法 B(均带有@Transactional)时,方法 A 是直接通过目标对象(UserService实例)调用方法 B,而非通过代理对象。
代理对象未被介入,事务拦截逻辑(如开启事务)自然不会执行。
5.spring IOC和AOP
6.spring AOP原理是什么
- 核心机制:Spring AOP 通过动态代理(JDK/CGLIB)生成代理对象,拦截方法调用并执行切面逻辑。
- 适用场景:解耦横切关注点(如日志、事务、权限),避免代码重复。
- 局限性:仅能拦截通过代理对象调用的方法(自调用失效),无法处理非 Spring 管理的对象或私有方法。
- 进阶选择:复杂场景可结合 AspectJ 实现编译时织入,但 Spring AOP 已覆盖大多数业务需求。
7.有一列名称,查询出名字重复人的名称和数量
SELECT name, COUNT(*) AS count
FROM people
GROUP BY name
HAVING COUNT(*) > 1;
8.CAS是什么 原理是什么 会导致什么问题
CAS(Compare and Swap)是一种常见的并发控制机制,广泛应用于多线程和多进程环境中的数据同步和原子操作。它是一种硬件支持的原子操作,也可以被理解为一种无锁的同步方式。
1. CAS是什么
CAS(比较并交换)是一个原子操作,用于在并发环境中安全地更新数据。它的基本思想是:先比较数据的当前值与预期值是否一致,如果一致则将数据更新为新的值,否则什么都不做。这样做可以避免多个线程同时修改数据时发生冲突,确保数据的一致性。
CAS 操作通常由三个参数组成:
- 内存位置(V):要修改的变量或内存位置。
- 旧值(A):期望的当前值,即操作前变量的预期值。
- 新值(B):当当前值与期望值一致时,替换的新值。
CAS 的工作流程如下:
- 将内存位置的当前值与预期值进行比较。
- 如果两者相等,说明数据没有被其他线程修改过,于是将内存位置的值更新为新的值。
- 如果两者不相等,说明数据已经被其他线程修改过,操作失败。
这种机制通过硬件级别的支持(如 CPU 提供的指令)实现了数据修改的原子性,避免了加锁带来的性能开销。
2. CAS的原理
CAS 是一种典型的乐观锁(Optimistic Locking)机制。它依赖于以下几个原理:
- 原子性:CAS 操作本身是原子性的,即无论多少线程同时对同一个内存位置进行 CAS 操作,只有一个线程能够成功更新值,其他线程会失败并重试。
- 无锁:CAS 本身不需要使用传统的锁(如互斥锁),因此避免了加锁带来的性能瓶颈。它是通过 CPU 的特殊指令实现的原子操作。
CAS 原理在多核 CPU 上的工作方式:
- CPU 提供了类似
CMPXCHG(Compare and Exchange)这样的指令,这些指令可以保证操作在多线程环境中原子执行,即无论有多少线程同时对同一内存地址进行修改,只有一个线程会成功,其他线程会检测到值已被修改,从而重试。
3. CAS可能导致的问题
尽管 CAS 可以避免传统加锁带来的性能开销,但它在高并发场景中也可能会引发一些问题:
1. ABA 问题
- 问题描述:CAS 会将内存位置的值与预期值进行比较,如果它们相等,CAS 就会进行更新操作。但是,如果一个线程在执行 CAS 操作时,内存位置的值先被修改了一次再恢复原值,CAS 会认为值没有改变,依然执行成功。
- 解决方案:为了避免 ABA 问题,许多实现引入了版本号或者指针版本化的策略(例如,使用带有版本号的指针或通过使用 "加锁" 或 "CAS + 内存标记" 等机制),或者使用一些更高级的结构(如 CAS2 或 StampedLock)。
2. 自旋问题(忙等待)
- 问题描述:CAS 是一种自旋锁机制,即线程执行 CAS 操作时,如果操作失败,就会不断重试,直到成功为止。在高并发场景下,如果很多线程同时竞争一个共享资源,CAS 可能会导致大量的自旋和 CPU 资源浪费。
- 解决方案:通过引入适当的退避策略(如指数退避算法)来减少 CPU 消耗,避免无限自旋。
3. 资源竞争过度(CAS 自旋的消耗)
- 问题描述:当多个线程频繁竞争同一个内存位置时,CAS 操作可能导致大量的重试,浪费 CPU 时间。这种情况称为 资源竞争过度,尤其在高并发场景下,性能可能会大幅下降。
- 解决方案:采用适当的退避策略,或者结合其他同步机制(如锁)来避免过度竞争。
4. 不公平性问题
- 问题描述:CAS 操作并没有明确的线程排队机制,这可能导致某些线程长时间无法成功执行操作(尤其是线程频繁发生竞争时),这也会影响到系统的公平性。
- 解决方案:在高竞争场景中,可能需要使用其他更复杂的同步机制来确保公平性,如队列锁(如 CLH 锁)。
4. 总结
CAS 是一种非常高效且无锁的并发控制机制,在多线程编程中广泛应用,尤其是在 Java 中的 java.util.concurrent 包里,许多原子类(如 AtomicInteger, AtomicReference)都是基于 CAS 实现的。
但是,CAS 也有一定的局限性,尤其是在高并发环境下可能会出现 ABA 问题、资源竞争过度等情况。因此,在使用 CAS 时,需要特别注意这些潜在问题,并根据具体的应用场景来选择合适的并发控制策略。
7.除了CRUD还会啥
就说客户对接,需求分析,业务功能梳理,技术选型