spring常用注解
@ResponseBody 和 @RequestBody
是 Spring 框架中用于处理 HTTP 请求和响应的两个重要注解。它们分别用于将数据写入 HTTP 响应体和从 HTTP 请求体中读取数据。
1. @ResponseBody
作用:
- 将控制器方法的返回值直接写入 HTTP 响应体中,而不是作为视图名称返回。
- 返回的数据会被自动序列化为 JSON 或 XML 格式(具体格式取决于配置和客户端请求头)。
使用场景:
- 通常与
@RestController配合使用,因为@RestController已经隐含了@ResponseBody的功能。
示例:
@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 的使用:
@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. 示例代码解释
以下是你的代码片段:
@Service
@SLF4J
public class DishServiceimpl implements DishService {
@Override
public void saveWithFlavor(DishDTO dishDto) {
// 业务逻辑实现
}
}解释:
@Service注解:- 将
DishServiceimpl类标记为一个服务层组件。 - Spring 会在启动时扫描到该类,并将其注册为一个 Bean。
- 将
@SLF4J注解:- 这是 Lombok 提供的一个注解,用于自动生成日志对象
log。 - 简化了日志记录的代码编写。
- 这是 Lombok 提供的一个注解,用于自动生成日志对象
业务方法:
saveWithFlavor(DishDTO dishDto)方法是业务逻辑的具体实现。- 该方法可能涉及保存菜品信息以及相关口味的逻辑。
4. @Service 的生命周期
Bean 的注册:
- 当 Spring 应用启动时,
@Service标记的类会被扫描并注册为一个 Bean。 - 默认情况下,Spring 中的 Bean 是单例模式(Singleton),即整个应用中只有一个实例。
- 当 Spring 应用启动时,
依赖注入:
- 其他类可以通过
@Autowired或构造函数注入的方式获取DishServiceimpl的实例。
- 其他类可以通过
5. 完整示例
以下是一个完整的示例,展示了 @Service 的使用:
// 服务层接口
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 "保存成功";
}
}解释:
DishService接口:- 定义了与菜品相关的业务方法。
DishServiceimpl实现类:- 使用
@Service注解标记为服务层组件。 - 实现了
saveWithFlavor方法的业务逻辑。
- 使用
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. 示例代码解释
以下是你的代码片段:
@Service
@Slf4j
public class DishServiceimpl implements DishService {
/**
* 新增菜品和对应的口味
* @param dishDto
*/
@Override
@Transactional
public void saveWithFlavor(DishDTO dishDto) {
// 业务逻辑实现
}
}解释:
@Transactional注解:- 标记在
saveWithFlavor方法上,表示该方法的操作需要在一个事务中执行。 - 如果方法执行过程中发生异常,默认情况下事务会回滚。
- 标记在
业务场景:
- 假设
saveWithFlavor方法需要完成以下操作:- 向
dish表插入一条菜品记录。 - 向
dish_flavor表插入多条口味记录。
- 向
- 如果第 2 步失败,第 1 步也需要回滚,以保证数据的一致性。
- 假设
4. @Transactional 的核心机制
事务的生命周期
- 开始事务:当方法开始执行时,Spring 会启动一个新的事务。
- 提交事务:如果方法正常结束(没有抛出异常),Spring 会自动提交事务。
- 回滚事务:
- 如果方法抛出了未被捕获的运行时异常(如
RuntimeException或其子类),默认情况下事务会回滚。 - 对于受检异常(如
Exception),需要显式配置@Transactional(rollbackFor = Exception.class)。
- 如果方法抛出了未被捕获的运行时异常(如
事务传播行为
@Transactional支持多种事务传播行为(Propagation),用于控制事务的创建和加入方式。REQUIRED(默认值):如果当前存在事务,则加入该事务;否则创建一个新的事务。REQUIRES_NEW:无论当前是否存在事务,都创建一个新的事务。SUPPORTS:如果当前存在事务,则加入该事务;否则以非事务方式执行。- 其他行为:
MANDATORY、NEVER、NOT_SUPPORTED等。
事务隔离级别
@Transactional还支持设置事务的隔离级别(Isolation),用于控制并发访问时的数据一致性。DEFAULT(默认值):使用底层数据库的默认隔离级别。READ_COMMITTED:只允许读取已提交的数据。REPEATABLE_READ:保证多次读取相同数据的结果一致。SERIALIZABLE:最高的隔离级别,完全防止脏读、不可重复读和幻读。
5. 完整示例
以下是一个完整的示例,展示了 @Transactional 的使用:
@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; // 抛出异常以触发事务回滚
}
}
}解释:
插入菜品信息:
- 将菜品信息保存到
dish表中。
- 将菜品信息保存到
插入口味信息:
- 将菜品对应的口味信息保存到
dish_flavor表中。
- 将菜品对应的口味信息保存到
事务管理:
- 如果任意一步失败(如数据库约束冲突),整个事务会回滚,保证数据的一致性。
6. 注意事项
异常类型:
默认情况下,只有抛出运行时异常(
RuntimeException)时才会触发事务回滚。如果需要对受检异常(
Exception)也进行回滚,可以使用rollbackFor属性:java@Transactional(rollbackFor = Exception.class)
只读事务:
如果方法只涉及查询操作,可以设置
readOnly = true,以优化性能:java@Transactional(readOnly = true)
事务失效场景:
- 同一类内部调用:如果在同一个类中通过方法直接调用另一个带有
@Transactional的方法,事务可能不会生效。 - 异常被捕获:如果方法中的异常被捕获并吞掉,事务不会回滚。
- 同一类内部调用:如果在同一个类中通过方法直接调用另一个带有
7. 总结
@Transactional的作用:声明式事务管理,简化事务代码的编写。- 适用场景:涉及多个数据库操作的场景,确保数据的一致性。
- 核心机制:通过 AOP 实现,控制事务的开始、提交和回滚。
- 注意事项:合理配置事务属性,避免事务失效场景。
@EnableTransactionManagement
- 作用
开启基于注解的事务管理功能,配合@Transactional使用。 - 使用场景
- 需要在方法或类上使用
@Transactional管理事务时。 - 适用于数据库操作、分布式事务等场景。
- 需要在方法或类上使用
- 核心机制
- 基于 AOP 实现,通过代理对象拦截方法调用。
- 自动管理事务的开始、提交和回滚。
- 注意事项
- 同一类内部调用可能导致事务失效(需通过代理对象调用)。
- 默认只对运行时异常回滚,受检异常需配置
rollbackFor。
@Autowired
作用
@Autowired 是 Spring 框架中的一个注解,用于实现依赖注入(Dependency Injection, DI)。它的主要作用是自动将 Spring 容器中管理的 Bean 注入到目标对象中。
1.使用场景
- 字段注入:直接标注在字段上,Spring 会自动注入对应的 Bean。
- 构造函数注入:标注在构造函数上,通常用于强制依赖。
- 方法注入:标注在 setter 方法或其他方法上。
2.核心机制
- 自动装配依赖:Spring 会根据类型(Type)查找匹配的 Bean,并将其注入到目标对象中。
- 减少手动创建对象的成本:开发者无需手动通过
new创建对象实例,Spring 会负责管理和提供这些依赖对象。
3.注意事项
Bean 必须存在于 Spring 容器中:
- 被注入的对象(如
DishService)必须是一个 Spring 管理的 Bean,通常需要使用@Service或其派生注解(如@Component)标记该类。
- 被注入的对象(如
可选注入:
- 如果某个依赖是可选的,可以结合
@Autowired(required = false)使用,表示即使找不到匹配的 Bean,也不会报错。
- 如果某个依赖是可选的,可以结合
推荐使用构造函数注入:
- 对于强制依赖的场景,推荐使用构造函数注入,以确保对象初始化时依赖已经存在。
