上海回合肥年初面试第五天😐

78 阅读9分钟

1.spring 事务传播行为是什么,默认是哪个

传播行为描述适用场景
REQUIRED(默认)如果有事务则加入,否则创建新事务大多数业务方法,默认行为。
SUPPORTS如果有事务则加入,否则不使用事务可选事务的方法。
MANDATORY当前必须在事务中执行,若无事务则抛出异常必须在事务中执行的方法。
REQUIRES_NEW每次执行都创建新的事务,挂起当前事务需要强制新建事务且不依赖于外部事务的场景。
NOT_SUPPORTED暂时挂起当前事务,执行时不使用事务方法不需要事务的场景。
NEVER必须没有事务,若有事务则抛出异常明确不需要事务的方法。
NESTED如果有事务,则创建一个嵌套事务,支持提交或回滚在事务中执行多个子事务,并允许子事务独立提交或回滚的场景。

2.spring实现事务的方式有哪些 事务原理是什么

  1. ​声明式事务(推荐)​​:

    • 优先使用 @Transactional,简洁高效。
    • 配合 TransactionManager 和 AOP,无侵入式管理。
  2. ​编程式事务​​:

    • 适用于需要动态控制事务或处理复杂逻辑的场景。
    • TransactionTemplate 比直接使用 PlatformTransactionManager 更简洁。
  3. ​AspectJ​​:

    • 当 Spring AOP 代理失效(如私有方法)时,可考虑使用,但需权衡复杂度。

这是 Spring 推荐的事务管理方式,通常使用 @Transactional 注解来声明事务。

@Transactional原理

@Transactional 是 Spring 提供的声明式事务管理注解,其核心原理基于 ​​AOP(面向切面编程)​​ 和 ​​动态代理​​,通过拦截方法调用并管理事务边界。以下是其关键机制:

方法调用 → 代理拦截 → 开启事务 → 执行方法 → 提交/回滚 → 释放资源

1. AOP 代理机制​

  • ​代理对象​​:Spring 为目标 Bean 生成代理(JDK 动态代理或 CGLIB),拦截带有 @Transactional 的方法。
  • ​自调用失效​​:同一类中方法 A 调用方法 B(均带 @Transactional),因绕过代理,事务失效。

​2. 事务拦截流程​

  1. ​方法调用拦截​​:代理对象捕获被 @Transactional 注解的方法调用。

  2. ​事务管理​​:通过 TransactionInterceptor 执行以下步骤:

    • ​开启事务​​:通过 PlatformTransactionManager 开启新事务。
    • ​执行方法​​:调用原始方法,执行数据库操作。
    • ​提交/回滚​​:根据执行结果(是否抛出异常)决定提交或回滚事务。

​3. 事务属性配置​

  • ​传播行为(Propagation)​​:定义事务边界(如 REQUIREDREQUIRES_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 事务失效场景

  1. ​检查代理机制​​:确认是否自调用,是否通过代理对象调用方法。
  2. ​验证数据库引擎​​:确保使用支持事务的引擎(如 InnoDB)。
  3. ​检查异常类型​​:确认是否抛出了 RuntimeException 或配置了 rollbackFor
  4. ​查看事务传播行为​​:确认传播属性是否符合预期。
  5. ​检查 Bean 管理​​:确认 @Transactional 类已被 Spring 管理。
  6. ​分析日志​​:通过 @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 的工作流程如下:

  1. 将内存位置的当前值与预期值进行比较。
  2. 如果两者相等,说明数据没有被其他线程修改过,于是将内存位置的值更新为新的值。
  3. 如果两者不相等,说明数据已经被其他线程修改过,操作失败。

这种机制通过硬件级别的支持(如 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 + 内存标记" 等机制),或者使用一些更高级的结构(如 CAS2StampedLock)。

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还会啥

就说客户对接,需求分析,业务功能梳理,技术选型