Skip to content

spring常用注解

@ResponseBody@RequestBody

是 Spring 框架中用于处理 HTTP 请求和响应的两个重要注解。它们分别用于将数据写入 HTTP 响应体和从 HTTP 请求体中读取数据。


1. @ResponseBody

作用

  • 将控制器方法的返回值直接写入 HTTP 响应体中,而不是作为视图名称返回。
  • 返回的数据会被自动序列化为 JSON 或 XML 格式(具体格式取决于配置和客户端请求头)。

使用场景

  • 通常与 @RestController 配合使用,因为 @RestController 已经隐含了 @ResponseBody 的功能。

示例

java
@RestController
@RequestMapping("/api")
public class MyController {

    @GetMapping("/data")
    public Map<String, Object> getData() {
        Map<String, Object> data = new HashMap<>();
        data.put("name", "John");
        data.put("age", 30);
        return data; // 自动序列化为 JSON 并写入响应体
    }
}

工作原理

  • 当方法返回一个 Java 对象时,Spring 会通过消息转换器(如 Jackson 或 Gson)将对象序列化为 JSON 或 XML 格式。
  • 序列化后的数据直接写入 HTTP 响应体中。

2. @RequestBody

作用

  • 用于将 HTTP 请求体中的数据绑定到控制器方法的参数上。
  • 请求体中的数据通常是 JSON 或 XML 格式,Spring 会自动将其反序列化为对应的 Java 对象。

工作原理

  • 客户端发送的请求体中的数据(如 JSON)会被 Spring 通过消息转换器(如 Jackson 或 Gson)反序列化为指定类型的 Java 对象。
  • 反序列化后的对象作为方法参数传递给控制器方法。

3. 对比总结

特性@ResponseBody@RequestBody
作用将返回值写入 HTTP 响应体从 HTTP 请求体中读取数据并绑定到参数
位置方法或类上方法参数前
数据流向控制器 -> 客户端客户端 -> 控制器
常见配合注解通常与 @RestController 配合使用通常与 @PostMapping@PutMapping 配合使用

4. 实际应用示例

以下是一个完整的示例,展示了 @ResponseBody@RequestBody 的使用:

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

    // 使用 @ResponseBody(隐含在 @RestController 中)
    @GetMapping("/user/{id}")
    public User getUserById(@PathVariable Long id) {
        return userService.getUserById(id); // 返回的 User 对象会被序列化为 JSON
    }

    // 使用 @RequestBody
    @PostMapping("/user")
    public User createUser(@RequestBody User user) {
        return userService.saveUser(user); // 接收前端发送的 JSON 数据并反序列化为 User 对象
    }
}

@Service

是 Spring 框架中的一个注解,用于标识一个类是 服务层组件。它是 Spring 的核心注解之一,主要用于分层架构中的业务逻辑层(Service Layer)。


1. @Service 的作用

  • 标识服务层组件

    • @Service 注解告诉 Spring 容器,该类是一个服务层的 Bean,属于业务逻辑层。
    • Spring 会自动将带有 @Service 注解的类注册为一个 Spring 管理的 Bean,并将其纳入依赖注入(DI)和控制反转(IoC)的管理范围。
  • 简化依赖注入

    • 使用 @Service 后,可以通过 @Autowired 或构造函数注入的方式轻松获取该类的实例,而无需手动创建对象。

2. @Service 的使用场景

  • 业务逻辑层

    • 在分层架构中,@Service 通常用于标记服务层的类,负责处理业务逻辑。
    • 例如,DishServiceimpl 类实现了 DishService 接口,提供与菜品相关的业务逻辑。
  • 与其他注解的区别

    • @Service:用于服务层。
    • @Controller:用于控制器层(Web 层)。
    • @Repository:用于数据访问层(DAO 层)。
    • @Component:通用注解,可以标注任何 Spring 管理的组件。

3. 示例代码解释

以下是你的代码片段:

java
@Service
@SLF4J
public class DishServiceimpl implements DishService {
    @Override
    public void saveWithFlavor(DishDTO dishDto) {
        // 业务逻辑实现
    }
}

解释:

  1. @Service 注解

    • DishServiceimpl 类标记为一个服务层组件。
    • Spring 会在启动时扫描到该类,并将其注册为一个 Bean。
  2. @SLF4J 注解

    • 这是 Lombok 提供的一个注解,用于自动生成日志对象 log
    • 简化了日志记录的代码编写。
  3. 业务方法

    • saveWithFlavor(DishDTO dishDto) 方法是业务逻辑的具体实现。
    • 该方法可能涉及保存菜品信息以及相关口味的逻辑。

4. @Service 的生命周期

  • Bean 的注册

    • 当 Spring 应用启动时,@Service 标记的类会被扫描并注册为一个 Bean。
    • 默认情况下,Spring 中的 Bean 是单例模式(Singleton),即整个应用中只有一个实例。
  • 依赖注入

    • 其他类可以通过 @Autowired 或构造函数注入的方式获取 DishServiceimpl 的实例。

5. 完整示例

以下是一个完整的示例,展示了 @Service 的使用:

java
// 服务层接口
public interface DishService {
    void saveWithFlavor(DishDTO dishDto);
}

// 服务层实现类
@Service
public class DishServiceimpl implements DishService {

    @Override
    public void saveWithFlavor(DishDTO dishDto) {
        // 业务逻辑实现
        System.out.println("保存菜品信息:" + dishDto.getName());
    }
}

// 控制器层
@RestController
@RequestMapping("/dish")
public class DishController {

    @Autowired
    private DishService dishService;

    @PostMapping("/save")
    public String saveDish(@RequestBody DishDTO dishDto) {
        dishService.saveWithFlavor(dishDto); // 调用服务层方法
        return "保存成功";
    }
}

解释:

  1. DishService 接口

    • 定义了与菜品相关的业务方法。
  2. DishServiceimpl 实现类

    • 使用 @Service 注解标记为服务层组件。
    • 实现了 saveWithFlavor 方法的业务逻辑。
  3. DishController 控制器

    • 通过 @Autowired 注入 DishService 的实例。
    • 调用服务层方法完成业务操作。

6. 总结

  • @Service 的作用:标识服务层组件,简化依赖注入和业务逻辑的管理。
  • 适用场景:用于分层架构中的业务逻辑层。
  • 与其他注解的关系@Service@Component 的特化注解,专门用于服务层。

如果你正在开发基于 Spring 的项目,理解 @Service 的作用及其在分层架构中的位置是非常重要的。


@Transactional

是 Spring 框架中的一个注解,用于声明式事务管理。它的主要作用是确保方法或类的操作在事务中执行,并根据业务逻辑自动提交回滚事务


1. @Transactional 的作用

  • 声明式事务管理

    • @Transactional 注解告诉 Spring,该方法或类需要在一个事务中执行。
    • 如果方法执行成功,Spring 会自动提交事务;如果发生异常,默认情况下会回滚事务。
  • 简化事务管理

    • 使用 @Transactional 可以避免手动编写复杂的事务代码(如 beginTransaction()commit()rollback())。
    • 提高了代码的可读性和维护性。

2. @Transactional 的使用场景

  • 数据库操作

    • 在涉及多个数据库操作(如插入、更新、删除)的场景中,通常需要使用事务来保证数据的一致性。
    • 例如,新增菜品和对应的口味时,可能需要同时向两个表插入数据。如果其中一个操作失败,另一个操作也需要回滚。
  • 分布式事务

    • 在微服务架构中,@Transactional 也可以结合分布式事务管理工具(如 Seata、Spring Cloud Sleuth)来处理跨服务的事务。

3. 示例代码解释

以下是你的代码片段:

java
@Service
@Slf4j
public class DishServiceimpl implements DishService {

    /**
     * 新增菜品和对应的口味
     * @param dishDto
     */
    @Override
    @Transactional
    public void saveWithFlavor(DishDTO dishDto) {
        // 业务逻辑实现
    }
}

解释:

  1. @Transactional 注解

    • 标记在 saveWithFlavor 方法上,表示该方法的操作需要在一个事务中执行。
    • 如果方法执行过程中发生异常,默认情况下事务会回滚。
  2. 业务场景

    • 假设 saveWithFlavor 方法需要完成以下操作:
      1. dish 表插入一条菜品记录。
      2. dish_flavor 表插入多条口味记录。
    • 如果第 2 步失败,第 1 步也需要回滚,以保证数据的一致性。

4. @Transactional 的核心机制

事务的生命周期

  • 开始事务:当方法开始执行时,Spring 会启动一个新的事务。
  • 提交事务:如果方法正常结束(没有抛出异常),Spring 会自动提交事务。
  • 回滚事务
    • 如果方法抛出了未被捕获的运行时异常(如 RuntimeException 或其子类),默认情况下事务会回滚。
    • 对于受检异常(如 Exception),需要显式配置 @Transactional(rollbackFor = Exception.class)

事务传播行为

  • @Transactional 支持多种事务传播行为(Propagation),用于控制事务的创建和加入方式。
    • REQUIRED(默认值):如果当前存在事务,则加入该事务;否则创建一个新的事务。
    • REQUIRES_NEW:无论当前是否存在事务,都创建一个新的事务。
    • SUPPORTS:如果当前存在事务,则加入该事务;否则以非事务方式执行。
    • 其他行为MANDATORYNEVERNOT_SUPPORTED 等。

事务隔离级别

  • @Transactional 还支持设置事务的隔离级别(Isolation),用于控制并发访问时的数据一致性。
    • DEFAULT(默认值):使用底层数据库的默认隔离级别。
    • READ_COMMITTED:只允许读取已提交的数据。
    • REPEATABLE_READ:保证多次读取相同数据的结果一致。
    • SERIALIZABLE:最高的隔离级别,完全防止脏读、不可重复读和幻读。

5. 完整示例

以下是一个完整的示例,展示了 @Transactional 的使用:

java
@Service
public class DishServiceimpl implements DishService {

    @Autowired
    private DishRepository dishRepository;

    @Autowired
    private DishFlavorRepository dishFlavorRepository;

    @Override
    @Transactional
    public void saveWithFlavor(DishDTO dishDto) {
        try {
            // 插入菜品信息
            Dish dish = new Dish();
            dish.setName(dishDto.getName());
            dish.setPrice(dishDto.getPrice());
            dishRepository.save(dish);

            // 插入口味信息
            List<DishFlavor> flavors = dishDto.getFlavors().stream()
                    .map(flavor -> {
                        DishFlavor df = new DishFlavor();
                        df.setDishId(dish.getId());
                        df.setName(flavor.getName());
                        return df;
                    }).collect(Collectors.toList());
            dishFlavorRepository.saveAll(flavors);

        } catch (Exception e) {
            log.error("保存菜品失败:{}", e.getMessage());
            throw e; // 抛出异常以触发事务回滚
        }
    }
}

解释:

  1. 插入菜品信息

    • 将菜品信息保存到 dish 表中。
  2. 插入口味信息

    • 将菜品对应的口味信息保存到 dish_flavor 表中。
  3. 事务管理

    • 如果任意一步失败(如数据库约束冲突),整个事务会回滚,保证数据的一致性。

6. 注意事项

  1. 异常类型

    • 默认情况下,只有抛出运行时异常(RuntimeException)时才会触发事务回滚。

    • 如果需要对受检异常(Exception)也进行回滚,可以使用 rollbackFor 属性:

      java
      @Transactional(rollbackFor = Exception.class)
  2. 只读事务

    • 如果方法只涉及查询操作,可以设置 readOnly = true,以优化性能:

      java
      @Transactional(readOnly = true)
  3. 事务失效场景

    • 同一类内部调用:如果在同一个类中通过方法直接调用另一个带有 @Transactional 的方法,事务可能不会生效。
    • 异常被捕获:如果方法中的异常被捕获并吞掉,事务不会回滚。

7. 总结

  • @Transactional 的作用:声明式事务管理,简化事务代码的编写。
  • 适用场景:涉及多个数据库操作的场景,确保数据的一致性。
  • 核心机制:通过 AOP 实现,控制事务的开始、提交和回滚。
  • 注意事项:合理配置事务属性,避免事务失效场景。

@EnableTransactionManagement

  1. 作用
    开启基于注解的事务管理功能,配合 @Transactional 使用。
  2. 使用场景
    • 需要在方法或类上使用 @Transactional 管理事务时。
    • 适用于数据库操作、分布式事务等场景。
  3. 核心机制
    • 基于 AOP 实现,通过代理对象拦截方法调用。
    • 自动管理事务的开始、提交和回滚。
  4. 注意事项
    • 同一类内部调用可能导致事务失效(需通过代理对象调用)。
    • 默认只对运行时异常回滚,受检异常需配置 rollbackFor

@Autowired

作用

@Autowired 是 Spring 框架中的一个注解,用于实现依赖注入(Dependency Injection, DI)。它的主要作用是自动将 Spring 容器中管理的 Bean 注入到目标对象中

1.使用场景

  • 字段注入:直接标注在字段上,Spring 会自动注入对应的 Bean。
  • 构造函数注入:标注在构造函数上,通常用于强制依赖。
  • 方法注入:标注在 setter 方法或其他方法上。

2.核心机制

  • 自动装配依赖:Spring 会根据类型(Type)查找匹配的 Bean,并将其注入到目标对象中。
  • 减少手动创建对象的成本:开发者无需手动通过 new 创建对象实例,Spring 会负责管理和提供这些依赖对象。

3.注意事项

  1. Bean 必须存在于 Spring 容器中

    • 被注入的对象(如 DishService)必须是一个 Spring 管理的 Bean,通常需要使用 @Service 或其派生注解(如 @Component)标记该类。
  2. 可选注入

    • 如果某个依赖是可选的,可以结合 @Autowired(required = false) 使用,表示即使找不到匹配的 Bean,也不会报错。
  3. 推荐使用构造函数注入

    • 对于强制依赖的场景,推荐使用构造函数注入,以确保对象初始化时依赖已经存在。