注解
2025/12/3大约 2 分钟
Java 注解是什么,是如何实现的?
Java 注解的本质其实就是:
一个继承了 Annotation 接口的“接口 + 动态代理对象”组合。
注解的底层是什么?
当你写:
public @interface MyAnnotation {
String value();
}编译器会把它变成一个 接口:
public interface MyAnnotation extends Annotation {
String value();
}真正的注解对象并不是这个接口的实现类,而是 JVM 在运行时为它生成的动态代理对象。
注解的实现原理
注解 = 接口 + 动态代理对象
- 注解定义:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() default "";
}- 使用注解:
public class UserService {
@MyAnnotation("test")
public void query() {
// 方法实现
}
}- 运行时获取:
Method method = UserService.class.getMethod("query");
MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
System.out.println(annotation.value()); // 输出: test核心原理:JVM为每个注解生成动态代理对象,通过代理获取注解值。
Java 注解的作用域如何确定的(作用在哪里?)
注解的作用范围由 @Target 决定,对应 ElementType:
- TYPE:类、接口、枚举
- METHOD:方法
- FIELD:字段
- CONSTRUCTOR:构造器
- PARAMETER:方法参数
- LOCAL_VARIABLE:局部变量
- PACKAGE:包
@Target(ElementType.METHOD)
public @interface MyMethodAnno {}
public class UserService {
@MyMethodAnno
public void query() {}
}这些位置只是告诉编译器:注解能被贴在哪。
说一下常用的注解使用场景
依赖注入(DI)
- 用于告诉框架由谁来创建对象、注入对象
- 常见:
@Autowired、@Resource、@Inject - 场景:自动注入 Service、Mapper、Component
声明 Bean / 组件扫描
- 用于让容器管理对象
- 常见:
@Component、@Service、@Repository、@Controller - 场景:Spring 扫描并注册 Bean
配置类相关
- 用于定义配置文件、配置属性注入
- 常见:
@Configuration、@Bean、@ConfigurationProperties - 场景:声明 Java 配置类/封装 yml 配置
AOP 切面相关
- 用于定义切点、增强逻辑
- 常见:
@Aspect、@Before、@Around、@After - 场景:日志、权限校验、事务、分布式锁
Web 开发相关
- 用于映射接口、绑定参数、限定访问
- 常见:
@RequestMapping、@GetMapping、@PostMapping - 参数绑定:
@RequestParam、@PathVariable、@RequestBody - 限制:
@CrossOrigin、@ResponseStatus
校验相关(JSR 303)
- 用于校验请求参数合法性
- 常见:
@NotNull、@NotBlank、@Min、@Max、@Valid - 场景:新增/更新接口入参校验
事务管理
- 用于声明方法是否开启事务
- 常见:
@Transactional - 场景:多表操作、保证一致性
序列化 / 反序列化控制
- 常见:
@JsonIgnore、@JsonProperty - 场景:控制 JSON 输出字段、别名
- 常见:
自定义注解
用于开发自己的通用能力
场景:
- 日志注解:
@OperationLog - 接口幂等:
@Idempotent - 分布式锁:
@ServiceLock/@RedissonLock - 权限控制:
@RequiresPermission
- 日志注解: