跳到主要内容

Spring 常用注解

问题

Spring/Spring Boot 中有哪些常用注解?它们的作用和使用场景是什么?

答案

注解分类总览

1. 组件注册注解

将类注册为 Spring Bean,本质都是 @Component 的派生注解:

注解语义典型场景
@Component通用组件工具类、通用组件
@Service业务逻辑层Service 类
@Repository数据访问层DAO 类(自动转换数据库异常)
@Controller表示层MVC Controller
@RestControllerREST 控制器@Controller + @ResponseBody
@Repository 的特殊之处

@Repository 除了注册 Bean 外,还会启用异常转换——将数据库特定异常(如 SQLException)转换为 Spring 统一的 DataAccessException 体系。这样业务层不需要关心底层数据库类型。

2. 依赖注入注解

依赖注入
@Service
public class OrderService {

// @Autowired:按类型注入
@Autowired
private UserService userService;

// @Qualifier:指定 Bean 名称(同类型多个 Bean 时消歧)
@Autowired
@Qualifier("mysqlOrderRepository")
private OrderRepository orderRepository;

// @Value:注入配置值
@Value("${order.max-retry:3}")
private int maxRetry;

// @Resource(JSR-250):先按名称、再按类型注入
@Resource(name = "redisTemplate")
private RedisTemplate<String, Object> redisTemplate;
}

@Autowired vs @Resource:

对比@Autowired@Resource
来源SpringJSR-250(JDK 标准)
匹配方式先按类型,再按名称先按名称,再按类型
必须存在默认是(required=false 可选)默认是
推荐Spring 项目首选需要按名称注入时使用

3. 配置类注解

配置类
@Configuration // 标记为配置类(Full 模式,Bean 方法调用会被代理)
@ComponentScan("com.example") // 指定包扫描路径
@PropertySource("classpath:app.properties") // 加载额外的配置文件
@Import(RedisConfig.class) // 导入其他配置类
public class AppConfig {

// @Bean:将方法返回值注册为 Bean
@Bean
@Scope("prototype") // 指定作用域
public RestTemplate restTemplate() {
return new RestTemplate();
}

// @Bean 的 name 默认为方法名
@Bean(name = "customExecutor", initMethod = "init", destroyMethod = "cleanup")
public ThreadPoolExecutor executor() {
return new ThreadPoolExecutor(4, 8, 60, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100));
}
}
@Configuration Full 模式 vs Lite 模式
  • Full 模式@Configuration):配置类会被 CGLIB 代理,Bean 方法间调用会从容器中获取(保证单例)
  • Lite 模式@Component 上的 @Bean 方法):不会被代理,Bean 方法间调用是普通 Java 调用(每次 new 新实例)

Spring Boot 推荐使用 @Configuration(proxyBeanMethods = false) 提升启动速度。

4. AOP 注解

AOP 注解
@Aspect
@Component
public class LogAspect {

// 切点表达式
@Pointcut("execution(* com.example.service.*.*(..))")
public void servicePointcut() {}

@Before("servicePointcut()")
public void before(JoinPoint jp) { /* 前置通知 */ }

@AfterReturning(pointcut = "servicePointcut()", returning = "result")
public void afterReturning(Object result) { /* 返回通知 */ }

@AfterThrowing(pointcut = "servicePointcut()", throwing = "ex")
public void afterThrowing(Exception ex) { /* 异常通知 */ }

@After("servicePointcut()")
public void after() { /* 最终通知 */ }

// 环绕通知(功能最强)
@Around("servicePointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
Object result = pjp.proceed();
log.info("耗时: {}ms", System.currentTimeMillis() - start);
return result;
}
}

5. MVC 注解

注解作用示例
@RequestMappingURL 映射@RequestMapping("/api")
@GetMappingGET 请求@GetMapping("/{id}")
@PostMappingPOST 请求@PostMapping
@RequestBody请求体 → 对象@RequestBody UserDTO dto
@ResponseBody返回值 → JSON方法或类级别
@PathVariableURL 路径变量@PathVariable Long id
@RequestParam查询参数@RequestParam String name
@RequestHeader请求头@RequestHeader("Token") String token
@CookieValueCookie 值@CookieValue("sid") String sid
@Valid参数校验@Valid @RequestBody UserDTO dto
@RestControllerAdvice全局异常处理配合 @ExceptionHandler

6. 事务注解

事务注解
@Service
public class OrderService {

@Transactional(
propagation = Propagation.REQUIRED, // 传播行为
isolation = Isolation.READ_COMMITTED, // 隔离级别
timeout = 30, // 超时(秒)
rollbackFor = Exception.class, // 哪些异常回滚
readOnly = false // 是否只读
)
public void createOrder(Order order) {
// 事务中的操作
}
}

7. 条件与生命周期注解

条件注解
// 条件注解(Spring Boot 大量使用)
@ConditionalOnProperty(name = "cache.enabled", havingValue = "true")
@ConditionalOnClass(RedisTemplate.class) // classpath 中有该类才生效
@ConditionalOnMissingBean(CacheManager.class) // 容器中没有该 Bean 才生效
@ConditionalOnBean(DataSource.class) // 容器中有该 Bean 才生效

// 生命周期回调
@Component
public class CacheWarmer {
@PostConstruct // Bean 初始化后执行
public void init() { /* 预热缓存 */ }

@PreDestroy // Bean 销毁前执行
public void cleanup() { /* 清理资源 */ }
}

8. Spring Boot 核心注解

SpringBoot 注解
// @SpringBootApplication = @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
注解作用
@SpringBootApplication启动类标记(组合注解)
@EnableAutoConfiguration开启自动配置
@ConfigurationProperties将配置文件属性绑定到 Bean
@ConditionalOnXxx条件化 Bean 注册

常见面试问题

Q1: @Autowired 的注入过程是怎样的?

答案

  1. Spring 在创建 Bean 时,通过 AutowiredAnnotationBeanPostProcessor 处理 @Autowired
  2. 按类型(byType)在容器中查找匹配的 Bean
  3. 如果找到多个同类型的 Bean,再按名称(byName)匹配
  4. 如果还有歧义,查找 @Qualifier@Primary 标记的 Bean
  5. 都不满足则抛出 NoUniqueBeanDefinitionException

Q2: @Autowired 和 @Resource 的区别?

答案

@Autowired 是 Spring 注解,先按类型后按名称匹配;@Resource 是 JDK 标准注解(JSR-250),先按名称后按类型匹配。Spring 官方推荐使用构造器注入(不需要注解),也可以用 @Autowired

Q3: @Configuration 和 @Component 有什么区别?

答案

@Configuration 是 Full 模式,类会被 CGLIB 代理,其中的 @Bean 方法互相调用时会从 IoC 容器获取(保证单例语义)。@Component 中的 @Bean 方法是 Lite 模式,方法互调是普通 Java 方法调用,每次都会创建新实例。

Q4: @Bean 和 @Component 有什么区别?

答案

  • @Component:标注在上,通过 @ComponentScan 自动扫描注册
  • @Bean:标注在方法上(配置类中),手动将方法返回值注册为 Bean

@Bean 适合注册第三方库的类(无法修改源码添加 @Component),@Component 适合注册自己写的类

Q5: @Transactional 失效的常见场景?

答案

  1. 方法非 public:Spring AOP 无法代理
  2. 自调用:同一个类内部方法调用,不经过代理
  3. 异常被 catch:事务管理器感知不到异常
  4. 抛出的是 checked 异常:默认只回滚 RuntimeException
  5. 传播行为设置不当:如 NOT_SUPPORTED 会挂起事务
  6. 数据库引擎不支持:如 MySQL 的 MyISAM
  7. Bean 未被 Spring 管理:没有 @Service 等注解

详细分析见 事务管理

Q6: @PostConstruct 的执行时机?

答案

在 Bean 的属性注入完成后InitializingBean.afterPropertiesSet() 之前执行。完整顺序是:

构造方法 → 属性注入 → @PostConstructInitializingBean.afterPropertiesSet()init-method

详细生命周期见 Bean 生命周期

相关链接