Spring Boot 常用注解:功能与示例
注:
@Mapper、@MapperScan属于 MyBatis;@FeignClient属于 Spring Cloud OpenFeign;其余主要来自 Spring / Spring Boot。
Web 接口
@RestController
声明一个 REST Controller。等价于 @Controller + @ResponseBody,方法返回值会自动序列化为 JSON。
@RestController
public class UserController {
@GetMapping("/users/{id}")
public UserDTO getUser(@PathVariable Long id) {
return new UserDTO(id, "Alice");
}
}
适用场景:JSON API 服务。
@RequestMapping
定义请求路径、HTTP 方法、请求头或参数匹配规则。可标在类或方法上。
@RestController
@RequestMapping("/api/users")
public class UserController {
@RequestMapping(
value = "/{id}",
method = RequestMethod.GET
)
public UserDTO getUser(@PathVariable Long id) {
return userService.getUser(id);
}
}
通常更推荐语义更清晰的快捷注解:
@GetMapping("/{id}")
@PostMapping
@PutMapping("/{id}")
@DeleteMapping("/{id}")
Bean 注册与业务分层
@Service
将类注册为 Spring Bean,语义上表示业务服务层。
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
public UserDTO getUser(Long id) {
User user = userRepository.findById(id);
return UserDTO.from(user);
}
}
适用场景:业务规则、用例编排、事务边界、调用多个 Repository 或外部服务。
@Component
通用的 Bean 注册注解。没有明确层次语义时使用。
@Component
public class PasswordEncoder {
public String encode(String password) {
return DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8));
}
}
常用于:工具类、策略实现、事件处理器、任务执行器、非 Web/Service/Repository 的组件。
@Repository
将类注册为 Bean,语义上表示数据访问层。Spring 还会将底层持久化异常转换为统一的 DataAccessException 体系。
@Repository
@RequiredArgsConstructor
public class UserRepository {
private final JdbcTemplate jdbcTemplate;
public User findById(Long id) {
return jdbcTemplate.queryForObject(
"SELECT id, name FROM users WHERE id = ?",
(resultSet, rowNum) -> new User(
resultSet.getLong("id"),
resultSet.getString("name")
),
id
);
}
}
如果使用 Spring Data JPA,通常写接口即可:
@Repository
public interface UserJpaRepository extends JpaRepository<UserEntity, Long> {
}
MyBatis 数据访问
@Mapper
标记 MyBatis Mapper 接口,让 MyBatis 在运行时生成代理实现。
@Mapper
public interface UserMapper {
@Select("""
SELECT id, name
FROM users
WHERE id = #{id}
""")
UserEntity selectById(@Param("id") Long id);
}
更常见的 XML 写法:
@Mapper
public interface UserMapper {
UserEntity selectById(Long id);
}
<mapper namespace="com.example.user.UserMapper">
<select id="selectById" resultType="com.example.user.UserEntity">
SELECT id, name
FROM users
WHERE id = #{id}
</select>
</mapper>
UserMapper 没有手写 Impl 是正常的:MyBatis 会动态生成代理对象。
@MapperScan
批量扫描指定包下的 MyBatis Mapper,通常放在启动类或配置类上。
@SpringBootApplication
@MapperScan("com.example.user.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
使用了 @MapperScan 后,Mapper 接口一般无需再逐个写 @Mapper。
事务、异步与任务
@Transactional
声明式事务。方法正常结束时提交;出现符合回滚规则的异常时回滚。
@Service
@RequiredArgsConstructor
public class OrderService {
private final OrderMapper orderMapper;
private final InventoryService inventoryService;
@Transactional
public void createOrder(CreateOrderCommand command) {
inventoryService.deduct(command.productId(), command.quantity());
orderMapper.insert(new OrderEntity(
command.userId(),
command.productId(),
command.quantity()
));
}
}
常用属性:
@Transactional(
rollbackFor = Exception.class,
readOnly = true,
timeout = 5
)
public UserDTO getUser(Long id) {
// 只读查询
}
注意事项:
- 注解依赖 Spring AOP 代理生效。
- 同一个类内
this.someTransactionalMethod()调用,可能绕过事务代理。 - 默认主要对
RuntimeException和Error回滚;业务检查异常常需显式写rollbackFor。 - 事务通常放在 Service 层,不建议放在 Controller。
@Async
让方法异步在线程池中执行,调用方不会等待其完成。
先开启异步能力:
@Configuration
@EnableAsync
public class AsyncConfig {
}
再标注方法:
@Service
public class EmailService {
@Async
public CompletableFuture<Void> sendWelcomeEmail(String email) {
// 调用邮件服务
return CompletableFuture.completedFuture(null);
}
}
调用:
emailService.sendWelcomeEmail("user@example.com");
// 这里会继续执行,不等待邮件发送完成
注意:
- 通常返回
void、Future或CompletableFuture。 - 同类内部调用也可能绕过代理。
- 生产环境应配置专用线程池,避免使用默认线程池。
@Scheduled
声明定时任务。
先开启调度能力:
@Configuration
@EnableScheduling
public class SchedulerConfig {
}
@Component
public class ReportTask {
@Scheduled(cron = "0 0 2 * * ?")
public void generateDailyReport() {
// 每天凌晨 2 点执行
}
@Scheduled(fixedDelay = 60_000)
public void refreshCache() {
// 上一次执行完成后,间隔 60 秒再执行
}
}
常用参数:
@Scheduled(fixedRate = 10_000) // 每 10 秒触发一次
@Scheduled(fixedDelay = 10_000) // 上次执行完后等 10 秒
@Scheduled(cron = "0 */5 * * * ?") // 每 5 分钟
注意:多实例部署时,每个实例都会执行任务。需要分布式锁或任务调度平台避免重复执行。
事件机制
@EventListener
监听应用事件,实现发布者和消费者解耦。
定义事件:
public record UserRegisteredEvent(Long userId, String email) {
}
发布事件:
@Service
@RequiredArgsConstructor
public class UserService {
private final ApplicationEventPublisher eventPublisher;
public void register(RegisterUserCommand command) {
Long userId = 1001L;
eventPublisher.publishEvent(
new UserRegisteredEvent(userId, command.email())
);
}
}
监听事件:
@Component
public class UserRegisteredListener {
@EventListener
public void onUserRegistered(UserRegisteredEvent event) {
// 例如:初始化用户资料、发送欢迎邮件
}
}
若希望在事务提交后才处理,可使用:
@Component
public class UserRegisteredListener {
@TransactionalEventListener(
phase = TransactionPhase.AFTER_COMMIT
)
public void onUserRegistered(UserRegisteredEvent event) {
// 只有事务成功提交后执行
}
}
远程 HTTP 调用
@FeignClient
声明远程 HTTP 服务客户端接口,由 OpenFeign 生成实现。
先开启:
@SpringBootApplication
@EnableFeignClients
public class Application {
}
定义客户端:
@FeignClient(
name = "user-service",
url = "${clients.user-service.base-url}"
)
public interface UserClient {
@GetMapping("/api/users/{id}")
UserDTO getUser(@PathVariable Long id);
}
像调用本地接口一样使用:
@Service
@RequiredArgsConstructor
public class OrderService {
private final UserClient userClient;
public OrderView getOrder(Long orderId) {
UserDTO user = userClient.getUser(1001L);
return new OrderView(orderId, user.name());
}
}
注意:@FeignClient 接口通常没有本地实现类;框架会在启动时生成代理。应配置超时、重试、错误处理和熔断策略。
Java 配置与 Bean 装配
@Configuration
声明配置类,其中通常包含 @Bean 方法。
@Configuration
public class AppConfig {
@Bean
public Clock clock() {
return Clock.systemUTC();
}
}
@Configuration 常用于:第三方 SDK 初始化、线程池、HTTP Client、序列化器、条件化装配。
@Bean
将方法返回值注册到 Spring 容器。适用于无法直接修改源码、不能加 @Component 的第三方对象。
@Configuration
public class HttpClientConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
注入使用:
@Service
@RequiredArgsConstructor
public class RemoteService {
private final RestTemplate restTemplate;
}
@Component 是“扫描类并创建对象”;@Bean 是“调用指定方法,把返回对象注册进容器”。
@Qualifier
当同一接口有多个 Bean 实现时,明确指定要注入哪一个。
public interface PaymentService {
void pay(BigDecimal amount);
}
@Service("alipayService")
public class AlipayService implements PaymentService {
public void pay(BigDecimal amount) {
}
}
@Service("wechatPayService")
public class WechatPayService implements PaymentService {
public void pay(BigDecimal amount) {
}
}
注入指定实现:
@Service
public class CheckoutService {
private final PaymentService paymentService;
public CheckoutService(
@Qualifier("alipayService") PaymentService paymentService
) {
this.paymentService = paymentService;
}
}
适用场景:支付渠道、多存储实现、多第三方客户端、不同策略实现。
@Primary
当同一类型有多个 Bean 时,标记默认优先注入的实现。
@Service
@Primary
public class DefaultPaymentService implements PaymentService {
public void pay(BigDecimal amount) {
}
}
@Service
public class BackupPaymentService implements PaymentService {
public void pay(BigDecimal amount) {
}
}
@Service
@RequiredArgsConstructor
public class CheckoutService {
private final PaymentService paymentService;
// 注入 DefaultPaymentService
}
规则:
@Qualifier 优先级高于 @Primary
环境与条件装配
@Profile
仅在特定环境 Profile 激活时注册 Bean。
@Service
@Profile("dev")
public class MockSmsService implements SmsService {
public void send(String phone, String content) {
System.out.println("Mock SMS: " + content);
}
}
@Service
@Profile("prod")
public class RealSmsService implements SmsService {
public void send(String phone, String content) {
// 调用真实短信平台
}
}
激活 Profile:
spring:
profiles:
active: dev
或通过环境变量:
SPRING_PROFILES_ACTIVE=prod
@Conditional
按条件决定是否注册 Bean。它是底层通用注解,实际开发更常见 Spring Boot 提供的派生注解。
@Configuration
public class CacheConfig {
@Bean
@ConditionalOnProperty(
prefix = "app.cache",
name = "enabled",
havingValue = "true"
)
public CacheService cacheService() {
return new RedisCacheService();
}
}
配置:
app:
cache:
enabled: true
常用条件注解:
@ConditionalOnProperty // 配置项满足条件
@ConditionalOnClass // classpath 存在某个类
@ConditionalOnMissingBean // 容器中尚不存在某 Bean
@ConditionalOnBean // 容器中存在某 Bean
@ConditionalOnWebApplication // 当前是 Web 应用
典型用途:自动配置、可选能力、开发环境 Mock 实现、组件开关。
AOP 切面
@Aspect
声明切面,用于把日志、监控、鉴权、审计、统一异常处理等横切逻辑从业务代码中抽离。
@Aspect
@Component
@Slf4j
public class MethodLogAspect {
@Around("execution(* com.example.service..*(..))")
public Object logMethod(
ProceedingJoinPoint joinPoint
) throws Throwable {
long startTime = System.currentTimeMillis();
try {
return joinPoint.proceed();
} finally {
long duration = System.currentTimeMillis() - startTime;
log.info(
"method={}, duration={}ms",
joinPoint.getSignature(),
duration
);
}
}
}
常用通知类型:
@Before // 方法执行前
@After // 方法结束后,无论成功失败
@AfterReturning // 正常返回后
@AfterThrowing // 抛异常后
@Around // 完全包裹方法调用,最灵活
常见切点表达式:
execution(* com.example.service..*(..))
含义:
匹配 com.example.service 及其子包下,
所有类的所有方法,任意参数。
注意:@Transactional、@Async 本质上也主要依赖 AOP 代理机制。因此要警惕同类内部调用绕过代理的问题。