Java 注解的位置与用法详解
一、类级别注解(写在类上)
// ==================== Spring 核心 ====================
@Configuration // 位置:配置类上
public class AppConfig {
@Bean
public DataSource dataSource() { ... }
}
@Component // 位置:通用组件类上(无法用其他注解标注时)
@Service // 位置:业务逻辑层类上
@Repository // 位置:数据访问层类上
@Controller // 位置:控制器类上(传统 MVC)
@RestController // 位置:REST 控制器类上(= @Controller + @ResponseBody)
public class UserController { ... }
@Scope("prototype") // 位置:Bean 类上,指定作用域(singleton/prototype/request/session)
public class PrototypeBean { ... }
@Primary // 位置:Bean 类上,同类优先注入
public class PrimaryService implements MyService { ... }
@Profile("dev") // 位置:类上,指定环境激活
public class DevConfig { ... }
@Mapper // 位置:MyBatis Mapper 接口上
public interface UserMapper {
@Select("SELECT * FROM user WHERE id = #{id}")
User selectById(Long id);
}
@TableName("t_user") // 位置:实体类上,映射数据库表名
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class User {
@TableId(type = IdType.AUTO) // 位置:主键字段上
private Long id;
@TableField("user_name") // 位置:普通字段上,映射列名
private String username;
}
@MapperScan("com.hmdp.mapper") // 位置:启动类或配置类上
@SpringBootApplication
public class HmDianPingApplication { ... }
@Aspect // 位置:切面类上
@Component
public class LogAspect { ... }
@Data // 位置:实体类上(Lombok)
@Builder // 位置:实体类上(Lombok)
@NoArgsConstructor // 位置:实体类上(Lombok)
@AllArgsConstructor // 位置:实体类上(Lombok)
@RequiredArgsConstructor // 位置:类上(有 final 字段时自动构造器注入)
@Slf4j // 位置:类上(Lombok 生成日志对象)
@ToString // 位置:类上(Lombok)
@EqualsAndHashCode // 位置:类上(Lombok)
@Accessors(chain = true) // 位置:类上(Lombok 链式调用)
public class UserVO { ... }
@EnableCaching // 位置:启动类或配置类上(开启缓存)
@EnableScheduling // 位置:启动类或配置类上(开启定时任务)
@EnableWebSecurity // 位置:配置类上(开启安全框架)
@EnableTransactionManagement // 位置:配置类上(开启事务管理)
二、方法级别注解(写在方法上)
// ==================== Bean 定义 ====================
@Bean // 位置:@Configuration 类中的方法上
@Scope("prototype")
public RedisTemplate<String, Object> redisTemplate() {
return new RedisTemplate<>();
}
// ==================== HTTP 请求映射 ====================
@GetMapping("/list") // 位置:Controller 方法上
@PostMapping("/add") // 位置:Controller 方法上
@PutMapping("/update") // 位置:Controller 方法上
@DeleteMapping("/delete") // 位置:Controller 方法上
@RequestMapping(value = "/search", // 位置:Controller 方法上
method = RequestMethod.POST)
public Result<List<Shop>> search(@RequestBody ShopSearchDTO dto) {
return Result.success(shopService.search(dto));
}
// ==================== AOP 通知 ====================
@Around("@annotation(com.hmdp.annotation.Log)") // 位置:切面方法上
public Object around(ProceedingJoinPoint joinPoint) throws Throwable { ... }
@Before("execution(* com.hmdp.service.*.*(..))") // 位置:切面方法上
public void before(JoinPoint joinPoint) { ... }
// ==================== 事务 ====================
@Transactional(rollbackFor = Exception.class) // 位置:Service 方法或类上
public void createOrder(OrderDTO dto) {
// 数据库操作
}
@Transactional(readOnly = true) // 只读事务,性能优化
public User getUserById(Long id) { ... }
// ==================== 缓存 ====================
@Cacheable(value = "user", key = "#id") // 位置:查询方法上
public User getById(Long id) { // 命中缓存直接返回,不执行方法体
return userMapper.selectById(id);
}
@CachePut(value = "user", key = "#user.id") // 位置:更新方法上
public User update(User user) { // 总是执行方法体,更新缓存
userMapper.updateById(user);
return user;
}
@CacheEvict(value = "user", key = "#id") // 位置:删除方法上
public void deleteById(Long id) { // 执行后清除缓存
userMapper.deleteById(id);
}
@Caching( // 位置:方法上,组合多个缓存操作
cacheable = @Cacheable(value = "user", key = "#id"),
evict = @CacheEvict(value = "user-list", allEntries = true)
)
public User getByIdAndClearList(Long id) { ... }
// ==================== 定时任务 ====================
@Scheduled(fixedRate = 5000) // 位置:定时方法上,每5秒
public void refreshCache() { ... }
@Scheduled(fixedDelay = 10000) // 位置:定时方法上,上次结束后等10秒
public void cleanup() { ... }
@Scheduled(cron = "0 0 2 * * ?") // 位置:定时方法上,每天凌晨2点
public void dailyReport() { ... }
// ==================== 安全鉴权 ====================
@PreAuthorize("hasRole('ADMIN')") // 位置:Controller 方法上
@Secured("ROLE_ADMIN") // 位置:Controller 方法上
public Result<Void> deleteUser(@PathVariable Long id) { ... }
// ==================== 重写与弃用 ====================
@Override // 位置:重写父类/接口方法上
public void save(User user) { ... }
@Deprecated // 位置:已弃用的方法上
public void oldMethod() { ... }
// ==================== 异常处理 ====================
@ExceptionHandler(UserNotFoundException.class) // 位置:全局异常处理方法上
public Result<Void> handleNotFound(UserNotFoundException e) {
return Result.fail("用户不存在");
}
三、参数级别注解(写在方法参数前)
// ==================== Controller 参数绑定 ====================
@GetMapping("/{id}")
public Result<User> getById(
@PathVariable Long id // 路径参数:/api/user/123 → id = 123
) { ... }
@GetMapping("/list")
public Result<PageResult> list(
@RequestParam(defaultValue = "1") Integer page, // 查询参数:?page=1&size=10
@RequestParam(defaultValue = "10") Integer size,
@RequestParam(required = false) String keyword // 可选参数
) { ... }
@PostMapping("/add")
public Result<Void> add(
@RequestBody @Valid ShopDTO dto // JSON 请求体 → 反序列化为对象,并触发校验
) { ... }
@GetMapping("/current")
public Result<UserVO> getCurrentUser(
@RequestHeader("Authorization") String token // 从请求头取值
) { ... }
@PostMapping("/upload")
public Result<Void> upload(
@RequestParam("file") MultipartFile file // 接收上传文件
) { ... }
// ==================== 校验注解(写在实体字段上,由 @Valid 触发) ====================
@Data
public class ShopDTO {
@NotNull(message = "店铺ID不能为空")
private Long id;
@NotBlank(message = "店铺名称不能为空")
@Size(min = 2, max = 32, message = "名称长度 2-32 位")
private String name;
@NotNull(message = "评分不能为空")
@Min(value = 0, message = "评分最低为 0")
@Max(value = 5, message = "评分最高为 5")
private Double score;
@NotBlank
@Email(message = "邮箱格式不正确")
private String email;
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
}
// ==================== MyBatis 参数绑定 ====================
@Select("SELECT * FROM user WHERE name = #{name} AND age = #{age}")
User selectByNameAndAge(@Param("name") String name, // @Param 绑定多个参数
@Param("age") Integer age);
// ==================== 异常处理参数 ====================
@ExceptionHandler({MethodArgumentNotValidException.class})
public Result<Void> handleValidation(
MethodArgumentNotValidException e // 异常对象自动注入
) { ... }
四、字段级别注解(写在字段/属性上)
public class UserVO {
@TableId(type = IdType.AUTO) // 字段:主键
private Long id;
@TableField("user_name") // 字段:映射数据库列名
private String username;
@TableField(exist = false) // 字段:该字段不映射数据库
private String otherInfo;
@TableField(fill = FieldFill.INSERT) // 字段:自动填充
private LocalDateTime createTime;
@Value("${jwt.secret}") // 字段:注入配置值
private String secret;
@Autowired // 字段:注入 Bean(不推荐,推荐构造器注入)
private UserService userService;
@Resource // 字段:按名称注入
private RedisTemplate redisTemplate;
}
五、注解叠加使用(实际项目最常见)
// ===== 启动类 =====
@Slf4j
@SpringBootApplication
@MapperScan("com.hmdp.mapper")
@EnableCaching
@EnableScheduling
@Import({SwaggerConfig.class, RedisConfig.class})
public class HmDianPingApplication {
public static void main(String[] args) {
SpringApplication.run(HmDianPingApplication.class, args);
}
}
// ===== Controller =====
@RestController
@RequestMapping("/api/shop")
@RequiredArgsConstructor // 自动注入所有 final 依赖
@Slf4j
public class ShopController {
private final ShopService shopService;
@GetMapping("/{id}")
@Cacheable(value = "shop", key = "#id") // 方法+缓存注解叠加
@ApiOperation("查询店铺") // Swagger 接口文档
public Result<ShopVO> getById(
@PathVariable @NotNull Long id // 路径参数+校验叠加
) {
return Result.success(shopService.getById(id));
}
@PostMapping
@PreAuthorize("hasRole('ADMIN')") // 方法+权限注解叠加
public Result<Void> add(
@RequestBody @Valid ShopDTO dto // 参数+校验注解叠加
) {
shopService.add(dto);
return Result.success();
}
}
// ===== Service =====
@Service
@Slf4j
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class) // 类级别事务(所有 public 方法生效)
public class ShopServiceImpl implements ShopService {
private final ShopMapper shopMapper;
@Override // 重写接口方法
@Transactional(readOnly = true) // 覆盖类级别事务为只读
@Cacheable(value = "shop", key = "#id")
public Shop getById(Long id) {
return shopMapper.selectById(id);
}
}
// ===== 异常处理 =====
@Slf4j
@RestControllerAdvice // 全局异常处理(= @ControllerAdvice + @ResponseBody)
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<Void> handleValidation(
MethodArgumentNotValidException e // 参数:异常对象
) {
String msg = e.getBindingResult().getFieldError().getDefaultMessage();
return Result.fail(msg);
}
@ExceptionHandler(RuntimeException.class)
public Result<Void> handleRuntime(
RuntimeException e
) {
log.error("运行时异常", e);
return Result.fail("服务器内部错误");
}
}
六、速查表
| 位置 | 常用注解 |
|---|---|
| 启动/配置类上 | @SpringBootApplication @Configuration @EnableCaching @EnableScheduling @MapperScan @ComponentScan @Import |
| 普通类上 | @Service @Repository @Component @RestController @Controller @Aspect @Slf4j @Data @RequiredArgsConstructor |
| 方法上 | @Bean @GetMapping @PostMapping @Transactional @Cacheable @CacheEvict @Scheduled @PreAuthorize @Override @ExceptionHandler |
| 方法参数上 | @PathVariable @RequestParam @RequestBody @Valid @RequestHeader @Param @NotNull |
| 字段上 | @Autowired @Resource @Value @TableId @TableField |
更多推荐

所有评论(0)