Spring Boot 核心注解详解与最佳实践
组件声明与自动扫描
Spring Boot 通过注解实现组件的自动发现与管理。使用 @ComponentScan 可指定 Spring 容器扫描的基础包路径,自动注册被标注的类为 Bean。默认情况下,它会扫描启动类所在包及其子包中所有带有组件注解的类。
@Controller、@Service 与 @Repository
这三个注解均继承自 @Component,用于标记不同层级的业务组件:
- @Controller:标识 Web 层控制器,通常配合
@RequestMapping使用。 - @Service:标注服务层逻辑处理类。
- @Repository:用于数据访问层,还能将数据库异常统一转换为 Spring 的非检查异常。
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
@ResponseBody
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
}
@Component
通用组件注解,适用于无法归类到上述三种场景的自定义组件,例如消息发送器或工具类服务。
@Component
public class EmailNotificationSender {
public void send(String to, String content) {
// 发送邮件逻辑
}
}
MyBatis 持久层接口管理:@Mapper vs @Repository
在整合 MyBatis 时,Mapper 接口需要被 Spring 管理以生成代理实例。常见方式有两种:
@Mapper
MyBatis 提供的注解,直接标注在接口上即可让框架为其创建动态代理。但若存在多个 Mapper,需重复添加该注解。
@Mapper
public interface UserMapper {
User selectById(Long id);
}
@MapperScan
更推荐的方式是在主配置类上使用 @MapperScan,批量扫描指定包下的所有 Mapper 接口,无需在每个接口上添加 @Mapper。
@Configuration
@MapperScan("com.example.demo.mapper")
public class MyBatisConfig {}
为何不单独使用 @Repository?
@Repository 虽可标记 DAO 层,但它本身不会触发代理生成。必须结合 MapperScannerConfigurer 或 @MapperScan 才能完成接口代理注入。否则会出现"找不到 Bean"的错误。
解决 IDEA 报红问题
尽管运行正常,IDEA 可能因无法识别 @Mapper 导致 @Autowired 显示红色警告。此时可在接口上同时添加 @Mapper 和 @Repository,增强语义并消除提示。
@Mapper
@Repository
public interface OrderMapper {
List<Order> findAll();
}
依赖注入控制
Spring 支持多种依赖注入方式,开发者可根据需求选择最合适的策略。
@Autowired
基于类型(byType)进行自动装配。若同一类型有多个实例,需配合 @Qualifier 指定名称。
@Autowired
@Qualifier("primaryDataSource")
private DataSource dataSource;
@Resource
JDK 提供的注解,默认按名称(byName)注入,也可通过 type 属性改为按类型匹配。
@Resource(name = "fileStorageService")
private StorageService storageService;
@Qualifier
与 @Autowired 配合使用,用于精确指定要注入的 Bean 名称,避免歧义。
Bean 生命周期与作用域
@Bean
在配置类中定义方法,并使用 @Bean 注解将其返回值注册为容器中的 Bean。
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@Scope
设置 Bean 的作用范围:singleton(默认)、prototype、request、session 等。
@Bean
@Scope("prototype")
public TaskProcessor taskProcessor() {
return new TaskProcessor();
}
@Primary
当存在多个相同类型的 Bean 时,标记其中一个为主要候选者,优先被注入。
@Bean
@Primary
public ObjectMapper jsonMapper() {
return new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
}
@PostConstruct 与 @PreDestroy
分别在 Bean 初始化完成后和销毁前执行,适合资源加载与释放操作。
@Component
public class CacheLoader {
@PostConstruct
public void init() {
System.out.println("缓存预热完成");
}
@PreDestroy
public void cleanup() {
System.out.println("清理缓存资源");
}
}
Web 请求映射
@RestController 与 @RequestMapping
@RestController 是 @Controller 和 @ResponseBody 的组合,表示该控制器所有方法返回 JSON 数据。
@RestController
@RequestMapping("/api/users")
public class UserApiController {
@GetMapping
public List<User> listUsers(@RequestParam(defaultValue = "0") int page) {
return userService.getPage(page);
}
@PostMapping
public Result createUser(@RequestBody User user) {
userService.save(user);
return Result.success();
}
}
便捷映射注解
@GetMapping:处理 GET 请求。@PostMapping:处理 POST 请求。@PutMapping、@DeleteMapping:对应更新与删除操作。
参数绑定注解
@PathVariable:提取 URL 路径变量。@RequestParam:获取查询参数或表单字段。@RequestBody:解析请求体中的 JSON 并映射为对象。@RequestPart:用于文件上传等 multipart 请求部分。
配置管理
@Configuration 与 @SpringBootApplication
@Configuration 声明 Java 配置类;而 @SpringBootApplication 是一个组合注解,集成了 @Configuration、@EnableAutoConfiguration 和 @ComponentScan,通常用于主启动类。
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@Value
从配置文件中读取单个属性值。
@Value("${app.name}")
private String appName;
@ConfigurationProperties
批量绑定具有共同前缀的配置项到一个 POJO 中,支持松散绑定和类型安全。
@Data
@ConfigurationProperties(prefix = "app.security")
public class SecurityProperties {
private List<String> ignoredUrls = new ArrayList<>();
}
条件化配置 @Conditional
根据特定条件决定是否创建某个 Bean,常用于自动配置场景。
@ConditionalOnClass:类路径存在某类时生效。@ConditionalOnMissingBean:容器中无指定 Bean 时生效。
事务管理
@EnableTransactionManagement
开启基于注解的事务支持。
@Transactional
标注在方法或类上,启用声明式事务管理。作用于类时,其所有公共方法都将受事务控制。
@Service
@Transactional
public class OrderService {
public void createOrder(Order order) {
orderDao.insert(order);
inventoryService.reduceStock(order.getItems());
}
}
安全控制
@EnableWebSecurity
启用 Spring Security 的 Web 安全功能。
@EnableGlobalMethodSecurity
开启方法级别的安全控制,如 @PreAuthorize 权限校验。
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// 配置省略
}
全局异常处理
@ControllerAdvice 与 @ExceptionHandler
实现跨控制器的统一异常捕获与响应处理。
@ControllerAdvice
@ResponseBody
public class GlobalExceptionTranslator {
@ExceptionHandler(BusinessException.class)
public Result handleBusinessError(BusinessException e) {
return Result.fail(e.getMessage());
}
}
面向切面编程(AOP)
@Aspect 与通知类型
使用 AOP 实现日志记录、性能监控等功能。
@Aspect
@Component
@Order(1)
public class LoggingAspect {
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceMethods() {}
@Around("serviceMethods()")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long duration = System.currentTimeMillis() - start;
System.out.printf("方法 %s 执行耗时: %d ms\n", joinPoint.getSignature(), duration);
return result;
}
}
测试支持
@SpringBootTest
用于集成测试,加载完整的 Spring 上下文环境。
@SpringBootTest
class UserServiceTest {
@Autowired
private UserService userService;
@Test
void shouldReturnUserWhenIdExists() {
User user = userService.findById(1L);
assertThat(user).isNotNull();
}
}