DukeDuke
主页
文档转换
关于我们
主页
文档转换
关于我们
  • 目录

    • Spring简介
    • Springboot简介
    • Spring Security简介
    • SpringBoot 中的事件详解
    • SpringBoot 中的定时任务详解
    • SpringBoot 自动装配原理与源码解释
    • Spring 面试题
    • Spring 核心概念
    • Spring IoC 容器
    • Spring AOP
    • Spring Bean 生命周期
    • Spring 事务管理
    • SpringMVC
    • SpringBoot
    • Spring 性能优化
    • Spring 安全
    • 实际应用场景

Spring Framework 面试与学习指南

1. Spring Framework 简介

Spring Framework 是一个开源的 Java 平台,为开发企业级 Java 应用提供全面的基础设施支持。Spring 以其依赖注入(DI)和面向切面编程(AOP)等核心特性而闻名。

1.1 Spring Framework 的优势

  • 轻量级:框架本身的代码量小,对应用的影响最小
  • 控制反转(IoC):通过依赖注入实现松耦合,提高代码可测试性
  • 面向切面编程(AOP):允许将横切关注点与业务逻辑分离
  • 容器:管理应用中的对象的配置和生命周期
  • 框架集成:易于与其他框架集成(如 Hibernate、MyBatis 等)
  • 事务管理:统一的事务管理接口,支持声明式和编程式事务
  • MVC 框架:用于开发灵活、松耦合的 Web 应用

1.2 Spring 生态体系

Spring Framework (核心)
├── Spring Boot (快速开发)
├── Spring Cloud (微服务)
├── Spring Security (安全)
├── Spring Data (数据访问)
└── Spring Batch (批处理)

2. 核心特性详解

2.1 依赖注入(DI)

依赖注入是 Spring 框架最核心的特性之一,它有助于实现松耦合的应用设计。

2.1.1 三种注入方式

1. 构造器注入(推荐)

@Component
public class UserService {
    private final UserRepository userRepository;
    private final EmailService emailService;

    @Autowired // 可以省略,Spring 4.3+ 支持隐式注入
    public UserService(UserRepository userRepository, EmailService emailService) {
        this.userRepository = userRepository;
        this.emailService = emailService;
    }
}

2. Setter 注入

@Component
public class UserService {
    private UserRepository userRepository;
    private EmailService emailService;

    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Autowired
    public void setEmailService(EmailService emailService) {
        this.emailService = emailService;
    }
}

3. 字段注入(不推荐)

@Component
public class UserService {
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private EmailService emailService;
}

2.1.2 面试常见问题

Q: 为什么推荐使用构造器注入? A:

  • 保证依赖不可变性(final 修饰)
  • 确保必要的依赖在对象创建时就被注入
  • 便于单元测试
  • 避免循环依赖问题

Q: @Autowired 和 @Resource 的区别? A:

  • @Autowired 是 Spring 提供的注解,默认按类型注入
  • @Resource 是 JSR-250 规范,默认按名称注入
  • @Autowired 可以配合 @Qualifier 指定名称
  • @Resource 可以通过 name 属性指定名称

2.2 Spring Bean

Spring Bean 是被 Spring 容器管理的对象。

2.2.1 Bean 作用域

@Component
@Scope("singleton") // 默认作用域
public class SingletonBean {}

@Component
@Scope("prototype")
public class PrototypeBean {}

@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestBean {}

@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class SessionBean {}

作用域说明:

  • singleton(默认):每个 Spring IoC 容器仅创建一个实例
  • prototype:每次请求都会创建新的实例
  • request:每个 HTTP 请求都会创建新的实例
  • session:每个 HTTP 会话都会创建新的实例
  • application:ServletContext 生命周期内只有一个实例
  • websocket:WebSocket 会话生命周期内只有一个实例

2.2.2 Bean 生命周期详解

Spring Bean 的实例化过程包含以下几个关键步骤:

1. 实例化 (Instantiation)
   ↓
2. 属性注入 (Population)
   ↓
3. Aware 接口回调
   ↓
4. BeanPostProcessor 前置处理
   ↓
5. 初始化 (Initialization)
   ↓
6. BeanPostProcessor 后置处理
   ↓
7. Bean 就绪 (Ready)
   ↓
8. 销毁 (Destruction) - 容器关闭时

详细生命周期示例:

@Component
public class LifecycleBean implements BeanNameAware, BeanFactoryAware,
                                   InitializingBean, DisposableBean {

    private String beanName;
    private BeanFactory beanFactory;

    public LifecycleBean() {
        System.out.println("1. 构造方法执行");
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println("5. @PostConstruct 执行");
    }

    @Override
    public void setBeanName(String name) {
        this.beanName = name;
        System.out.println("3. BeanNameAware 回调: " + name);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
        System.out.println("3. BeanFactoryAware 回调");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("6. InitializingBean.afterPropertiesSet() 执行");
    }

    public void customInit() {
        System.out.println("6. 自定义初始化方法执行");
    }

    @PreDestroy
    public void preDestroy() {
        System.out.println("8. @PreDestroy 执行");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("8. DisposableBean.destroy() 执行");
    }

    public void customDestroy() {
        System.out.println("8. 自定义销毁方法执行");
    }
}

面试常见问题:

Q: Bean 的生命周期中,哪些是必须的? A: 只有实例化和属性注入是必须的,其他步骤都是可选的。

Q: BeanPostProcessor 的作用是什么? A: BeanPostProcessor 是 Spring 提供的扩展点,可以在 Bean 初始化前后进行自定义处理,常用于 AOP 代理的创建。

Q: 如何自定义 Bean 的初始化方法? A: 可以通过 @PostConstruct 注解、实现 InitializingBean 接口,或在 XML 中配置 init-method 属性。

2.3 循环依赖问题

2.3.1 循环依赖的解决方案

Spring 通过三级缓存解决循环依赖:

@Service
public class AService {
    @Autowired
    private BService bService;

    public void methodA() {
        bService.methodB();
    }
}

@Service
public class BService {
    @Autowired
    private AService aService;

    public void methodB() {
        aService.methodA();
    }
}

三级缓存机制:

  • 一级缓存:singletonObjects - 存放完全初始化好的 Bean
  • 二级缓存:earlySingletonObjects - 存放早期暴露的 Bean(未完全初始化)
  • 三级缓存:singletonFactories - 存放 Bean 的工厂对象

2.3.2 面试常见问题

Q: Spring 如何解决循环依赖? A: Spring 通过三级缓存机制解决循环依赖:

  1. 创建 A 的实例,放入三级缓存
  2. 注入 B 时,发现 B 不存在,创建 B 的实例
  3. B 注入 A 时,从三级缓存中获取 A 的早期引用
  4. B 创建完成,放入一级缓存
  5. A 继续完成初始化,放入一级缓存

Q: 构造器注入的循环依赖能解决吗? A: 不能。Spring 只能解决 setter 注入和字段注入的循环依赖,构造器注入的循环依赖无法解决。

3. Spring IoC 容器

IoC 容器是 Spring 框架的核心。它负责管理对象的创建、配置和组装。

3.1 配置方式对比

3.1.1 XML 配置(传统方式)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 开启注解扫描 -->
    <context:component-scan base-package="com.example"/>

    <!-- 配置数据源 -->
    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"/>
        <property name="username" value="root"/>
        <property name="password" value="password"/>
    </bean>

    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 开启事务注解 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

3.1.2 Java 配置(推荐)

@Configuration
@ComponentScan("com.example")
@EnableTransactionManagement
@PropertySource("classpath:application.properties")
public class AppConfig {

    @Value("${db.driver}")
    private String driverClassName;

    @Value("${db.url}")
    private String jdbcUrl;

    @Value("${db.username}")
    private String username;

    @Value("${db.password}")
    private String password;

    @Bean
    public DataSource dataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setJdbcUrl(jdbcUrl);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

3.1.3 注解配置(最常用)

@SpringBootApplication
@EnableTransactionManagement
@EnableCaching
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@Service
@Transactional
public class UserService {
    @Autowired
    private UserRepository userRepository;

    @Cacheable("users")
    public User findById(Long id) {
        return userRepository.findById(id);
    }
}

3.2 面试常见问题

Q: @Configuration 和 @Component 的区别? A:

  • @Configuration 标识的类会被 CGLIB 增强,确保 @Bean 方法返回单例
  • @Component 是普通的组件注解,不会被增强
  • @Configuration 类中的 @Bean 方法可以相互调用

Q: @ComponentScan 的作用是什么? A: @ComponentScan 用于扫描指定包下的组件,将带有 @Component、@Service、@Repository、@Controller 注解的类注册为 Spring Bean。

Q: 如何排除某些 Bean 的自动装配? A: 可以使用 @ConditionalOnMissingBean、@ConditionalOnProperty 等条件注解,或者在 @ComponentScan 中使用 excludeFilters。

4. Spring AOP

AOP(面向切面编程)允许将横切关注点(如日志、事务、安全等)与业务逻辑分离。

4.1 AOP 核心概念

  • Aspect(切面):横切关注点的模块化
  • Join point(连接点):程序执行过程中的某个特定点
  • Pointcut(切入点):匹配连接点的表达式
  • Advice(通知):在切入点执行的代码
  • Target Object(目标对象):被代理的对象
  • Proxy(代理):AOP 框架创建的对象

4.2 通知类型

@Aspect
@Component
public class LoggingAspect {

    // 前置通知:在目标方法执行前执行
    @Before("execution(* com.example.service.*.*(..))")
    public void logBefore(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("方法 " + methodName + " 开始执行");
    }

    // 后置通知:在目标方法执行后执行(无论是否异常)
    @After("execution(* com.example.service.*.*(..))")
    public void logAfter(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("方法 " + methodName + " 执行完成");
    }

    // 返回通知:在目标方法正常返回后执行
    @AfterReturning(pointcut = "execution(* com.example.service.*.*(..))",
                    returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("方法 " + methodName + " 返回结果: " + result);
    }

    // 异常通知:在目标方法抛出异常后执行
    @AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))",
                   throwing = "ex")
    public void logAfterThrowing(JoinPoint joinPoint, Exception ex) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("方法 " + methodName + " 抛出异常: " + ex.getMessage());
    }

    // 环绕通知:在目标方法执行前后都执行
    @Around("execution(* com.example.service.*.*(..))")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        long startTime = System.currentTimeMillis();

        try {
            Object result = joinPoint.proceed();
            long endTime = System.currentTimeMillis();
            System.out.println("方法 " + methodName + " 执行时间: " + (endTime - startTime) + "ms");
            return result;
        } catch (Exception e) {
            System.out.println("方法 " + methodName + " 执行异常");
            throw e;
        }
    }
}

4.3 切入点表达式

@Aspect
@Component
public class PointcutExamples {

    // 匹配所有 public 方法
    @Pointcut("execution(public * *(..))")
    public void publicMethods() {}

    // 匹配特定包下的所有方法
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceMethods() {}

    // 匹配带有特定注解的方法
    @Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")
    public void transactionalMethods() {}

    // 匹配特定参数类型的方法
    @Pointcut("execution(* *(String, int))")
    public void stringIntMethods() {}

    // 组合切入点
    @Pointcut("serviceMethods() && publicMethods()")
    public void publicServiceMethods() {}

    @Before("publicServiceMethods()")
    public void beforePublicService() {
        System.out.println("执行公共服务方法");
    }
}

4.4 面试常见问题

Q: Spring AOP 的代理方式有哪些? A:

  • JDK 动态代理:基于接口的代理,目标类必须实现接口
  • CGLIB 代理:基于继承的代理,可以代理没有实现接口的类
  • Spring 默认优先使用 JDK 动态代理,如果目标类没有实现接口则使用 CGLIB

Q: AOP 的底层原理是什么? A: AOP 的底层原理是动态代理:

  1. 在运行时动态创建代理对象
  2. 代理对象拦截目标方法的调用
  3. 在方法调用前后执行切面逻辑

Q: @Aspect 和 @Component 的区别? A: @Aspect 标识这是一个切面类,@Component 标识这是一个 Spring 组件。通常两者结合使用,让切面类被 Spring 容器管理。

5. Spring MVC

Spring MVC 是一个用于构建 Web 应用的框架,它实现了 MVC 设计模式。

5.1 Spring MVC 核心组件

HTTP 请求
    ↓
DispatcherServlet (前端控制器)
    ↓
HandlerMapping (处理器映射)
    ↓
HandlerAdapter (处理器适配器)
    ↓
Controller (控制器)
    ↓
ViewResolver (视图解析器)
    ↓
View (视图)
    ↓
HTTP 响应

5.2 控制器开发

@Controller
@RequestMapping("/api/users")
@Validated
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    // GET 请求 - 获取用户列表
    @GetMapping
    public ResponseEntity<List<User>> getUsers(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        List<User> users = userService.findAll(page, size);
        return ResponseEntity.ok(users);
    }

    // GET 请求 - 获取单个用户
    @GetMapping("/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        User user = userService.findById(id);
        if (user == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(user);
    }

    // POST 请求 - 创建用户
    @PostMapping
    public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
        User createdUser = userService.create(user);
        return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
    }

    // PUT 请求 - 更新用户
    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id,
                                         @Valid @RequestBody User user) {
        User updatedUser = userService.update(id, user);
        if (updatedUser == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(updatedUser);
    }

    // DELETE 请求 - 删除用户
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        boolean deleted = userService.delete(id);
        if (!deleted) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.noContent().build();
    }

    // 异常处理
    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleUserNotFound(UserNotFoundException ex) {
        ErrorResponse error = new ErrorResponse("USER_NOT_FOUND", ex.getMessage());
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
    }
}

5.3 数据绑定和验证

@Data
@Validated
public class User {
    @NotNull(message = "用户ID不能为空")
    private Long id;

    @NotBlank(message = "用户名不能为空")
    @Size(min = 2, max = 50, message = "用户名长度必须在2-50之间")
    private String username;

    @Email(message = "邮箱格式不正确")
    private String email;

    @Min(value = 0, message = "年龄不能为负数")
    @Max(value = 150, message = "年龄不能超过150")
    private Integer age;
}

@RestController
@RequestMapping("/api/users")
public class UserController {

    @PostMapping
    public ResponseEntity<User> createUser(@Valid @RequestBody User user,
                                         BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            List<String> errors = bindingResult.getFieldErrors()
                .stream()
                .map(FieldError::getDefaultMessage)
                .collect(Collectors.toList());
            throw new ValidationException("验证失败: " + errors);
        }

        User createdUser = userService.create(user);
        return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
    }
}

5.4 面试常见问题

Q: @Controller 和 @RestController 的区别? A:

  • @Controller 标识这是一个控制器,返回视图名称
  • @RestController 是 @Controller 和 @ResponseBody 的组合,直接返回数据

Q: Spring MVC 的请求处理流程是什么? A:

  1. 请求到达 DispatcherServlet
  2. DispatcherServlet 通过 HandlerMapping 找到对应的 Handler
  3. HandlerAdapter 调用 Handler 处理请求
  4. Handler 返回 ModelAndView
  5. ViewResolver 解析视图
  6. 渲染视图并返回响应

Q: 如何自定义异常处理? A: 可以使用 @ExceptionHandler 注解处理特定异常,或使用 @ControllerAdvice 创建全局异常处理器。

6. Spring 事务管理

Spring 提供了一致的事务管理抽象,支持声明式事务和编程式事务。

6.1 事务传播行为

@Service
@Transactional
public class UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private OrderService orderService;

    // REQUIRED(默认):支持当前事务,如果不存在则创建新事务
    @Transactional(propagation = Propagation.REQUIRED)
    public void createUser(User user) {
        userRepository.save(user);
        // 如果这里抛出异常,整个事务回滚
    }

    // REQUIRES_NEW:总是创建新事务
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void createUserInNewTransaction(User user) {
        userRepository.save(user);
        // 即使外层事务回滚,这个事务也会提交
    }

    // SUPPORTS:支持当前事务,如果不存在则以非事务方式执行
    @Transactional(propagation = Propagation.SUPPORTS)
    public User findUser(Long id) {
        return userRepository.findById(id);
    }

    // NOT_SUPPORTED:以非事务方式执行
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void sendEmail(String email) {
        // 发送邮件,不参与事务
    }

    // MANDATORY:必须在事务中执行,否则抛出异常
    @Transactional(propagation = Propagation.MANDATORY)
    public void updateUser(User user) {
        userRepository.save(user);
    }

    // NEVER:不能在事务中执行,否则抛出异常
    @Transactional(propagation = Propagation.NEVER)
    public void readOnlyOperation() {
        // 只读操作
    }

    // NESTED:如果存在事务则在嵌套事务中执行
    @Transactional(propagation = Propagation.NESTED)
    public void nestedOperation() {
        // 嵌套事务操作
    }
}

6.2 事务隔离级别

@Service
public class TransactionIsolationService {

    // 读未提交:允许脏读
    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    public void readUncommitted() {
        // 可以读取其他事务未提交的数据
    }

    // 读已提交:防止脏读
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void readCommitted() {
        // 只能读取已提交的数据
    }

    // 可重复读:防止不可重复读
    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public void repeatableRead() {
        // 在同一事务中多次读取同一数据,结果一致
    }

    // 串行化:最高隔离级别
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public void serializable() {
        // 完全串行化执行,性能最低
    }
}

6.3 声明式事务

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private OrderRepository orderRepository;

    // 基本事务
    @Transactional
    public void createUser(User user) {
        userRepository.save(user);
    }

    // 只读事务
    @Transactional(readOnly = true)
    public User findUser(Long id) {
        return userRepository.findById(id);
    }

    // 指定超时时间
    @Transactional(timeout = 30)
    public void longRunningOperation() {
        // 30秒超时
    }

    // 指定回滚异常
    @Transactional(rollbackFor = {UserException.class, OrderException.class})
    public void createUserWithOrder(User user, Order order) {
        userRepository.save(user);
        orderRepository.save(order);
        // 如果抛出 UserException 或 OrderException,事务回滚
    }

    // 指定不回滚异常
    @Transactional(noRollbackFor = {ValidationException.class})
    public void createUserWithValidation(User user) {
        userRepository.save(user);
        // 如果抛出 ValidationException,事务不回滚
    }
}

6.4 编程式事务

6.4.1 使用 TransactionTemplate

@Service
public class UserService {

    private final TransactionTemplate transactionTemplate;
    private final UserRepository userRepository;

    public UserService(TransactionTemplate transactionTemplate, UserRepository userRepository) {
        this.transactionTemplate = transactionTemplate;
        this.userRepository = userRepository;
    }

    public void createUserWithTransaction(User user) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    userRepository.save(user);
                    // 其他业务逻辑
                } catch (Exception e) {
                    status.setRollbackOnly();
                    throw e;
                }
            }
        });
    }

    // 使用 Lambda 表达式的简化写法
    public void createUserWithLambda(User user) {
        transactionTemplate.execute(status -> {
            userRepository.save(user);
            return null;
        });
    }

    // 带返回值的事务
    public User createUserAndReturn(User user) {
        return transactionTemplate.execute(status -> {
            User savedUser = userRepository.save(user);
            return savedUser;
        });
    }
}

6.4.2 使用 PlatformTransactionManager

@Service
public class ComplexTransactionService {

    private final PlatformTransactionManager transactionManager;
    private final UserRepository userRepository;

    public ComplexTransactionService(PlatformTransactionManager transactionManager,
                                   UserRepository userRepository) {
        this.transactionManager = transactionManager;
        this.userRepository = userRepository;
    }

    public void complexTransaction(User user, Order order) {
        // 定义事务属性
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        def.setTimeout(30); // 30秒超时
        def.setReadOnly(false);

        TransactionStatus status = transactionManager.getTransaction(def);

        try {
            // 执行业务逻辑
            userRepository.save(user);
            // 其他操作...

            // 提交事务
            transactionManager.commit(status);
        } catch (Exception e) {
            // 回滚事务
            transactionManager.rollback(status);
            throw e;
        }
    }
}

6.5 面试常见问题

Q: 事务的 ACID 特性是什么? A:

  • 原子性(Atomicity):事务是不可分割的工作单位
  • 一致性(Consistency):事务执行前后数据保持一致
  • 隔离性(Isolation):并发事务之间相互隔离
  • 持久性(Durability):事务提交后数据永久保存

Q: 事务传播行为有哪些? A:

  • REQUIRED:支持当前事务,如果不存在则创建新事务
  • REQUIRES_NEW:总是创建新事务
  • SUPPORTS:支持当前事务,如果不存在则以非事务方式执行
  • NOT_SUPPORTED:以非事务方式执行
  • MANDATORY:必须在事务中执行
  • NEVER:不能在事务中执行
  • NESTED:如果存在事务则在嵌套事务中执行

Q: 事务隔离级别有哪些? A:

  • READ_UNCOMMITTED:读未提交,允许脏读
  • READ_COMMITTED:读已提交,防止脏读
  • REPEATABLE_READ:可重复读,防止不可重复读
  • SERIALIZABLE:串行化,最高隔离级别

Q: 声明式事务和编程式事务的区别? A:

  • 声明式事务:通过注解配置,代码侵入性小,推荐使用
  • 编程式事务:通过代码控制,灵活性高,适用于复杂场景
最近更新:: 2026/4/17 13:21
Contributors: Duke
Next
Springboot简介