Java元注解不是用来“炫技”的,而是让自定义注解真正具备可配置、可复用、可被正确处理的能力。没用好元注解,自定义注解就只是个标签;用对了,它就能成为业务逻辑的声明式入口。 四大核心元注解各自管辖的领域 @Target:指明注解的书写位置 @Target用于定义注解能够应用在哪些程序元素上——是类、
Java元注解编程:优雅声明式逻辑实现
作者:技术拾光
时间:2026-06-20
浏览:635
文章目录
Java元注解不是用来“炫技”的,而是让自定义注解真正具备可配置、可复用、可被正确处理的能力。没用好元注解,自定义注解就只是个标签;用对了,它就能成为业务逻辑的声明式入口。
四大核心元注解各自管辖的领域
@Target:指明注解的书写位置
@Target用于定义注解能够应用在哪些程序元素上——是类、方法、参数,还是连泛型参数都不放过?日常开发中,`ElementType.METHOD` 和 `ElementType.TYPE` 使用频率最高,但也不应忽略 `ElementType.PARAMETER`(用于校验入参)和 `ElementType.TYPE_PARAMETER`(泛型类型占位符),它们在框架扩展中越来越关键。@Retention:控制注解的存活周期
@Retention决定注解在哪个阶段有效。`SOURCE` 只在编译期有效(例如 `@Override`);`CLASS` 是默认值,注解会进入字节码但不加载到JVM;`RUNTIME` 才能让反射在运行时读取——只要需要反射解析注解(比如 Spring AOP 或自定义拦截器),就必须设为 `RUNTIME`,这一点很容易踩坑。@Documented:让注解出现在JavaDoc中
@Documented不改变运行行为,但对团队协作很实在。别人查看接口文档时,一眼就能看到 `@NonNull`、`@Deprecated` 等语义信息,省去反复翻代码的麻烦。@Inherited:允许子类继承父类注解
@Inherited注解只对类级别的注解生效,并且只作用于 `extends` 关系,不适用于接口实现或方法重写。换句话说,父类方法上的 `@Inherited` 注解,子类方法是不会自动继承的,这一点常被误解。
组合使用元注解:贴近真实场景的配置示例
单个元注解能力有限,组合使用才能贴近真实场景。例如定义一个权限检查注解,配置大致如下: - `@Target({ElementType.METHOD, ElementType.TYPE})` —— 支持加在控制器类或具体接口方法上 - `@Retention(RetentionPolicy.RUNTIME)` —— 运行时通过AOP切面读取并鉴权 - `@Documented` —— 在Swagger或JavaDoc中显式暴露权限要求 - 不加 `@Inherited` —— 权限策略通常需要显式声明,避免子类意外继承宽松策略 再比如一个配置绑定注解(类似Spring的 `@ConfigurationProperties`): - `@Target(ElementType.TYPE)` —— 只允许标注在配置类上 - `@Retention(RetentionPolicy.RUNTIME)` —— 需要在启动时扫描并注入属性值 - `@Repeatable(PropertySources.class)` —— 允许同一类上多次声明不同配置源,增强灵活性@Repeatable的使用隐性约束
要让注解支持重复声明,不能只加 `@Repeatable`,必须同时满足: - 被标记的注解(如 `@MyRole`)需要声明 `@Repeatable(MyRoles.class)`,其中 `MyRoles` 是容器注解 - 容器注解 `MyRoles` 必须有 `value()` 方法,且返回类型是该注解类型的数组(如 `MyRole[]`) 否则编译直接报错:“Repeatable annotation type must have a containing annotation type”。Spring 5+ 已经广泛使用这个机制(例如 `@Bean`、`@Scope`),但手写时容易漏掉容器注解的规范定义。常见误区:别把元注解当功能开关
元注解本身不执行逻辑——`@Target` 不会阻止你写错位置(IDE或编译器才做检查),`@Retention(RUNTIME)` 也不等于“自动生效”。真正起作用的是你写的处理器:可能是一个Aspect、一个BeanPostProcessor、或者一段反射遍历加条件判断的代码。 典型反例: - 定义 `@LogExecutionTime` 并标注 `@Retention(RUNTIME)`,却没写AOP切面——注解存在,但日志永远不会打 - 给字段加 `@NotBlank`,但没引入 Hibernate Validator 或没触发校验流程——空字符串照样入库 记住:元注解是“说明书”,不是“执行器”。声明之后,务必配套实现解析与响应逻辑。 不复杂,但容易忽略。实用工具推荐
电子包浆
使用 ›绿化、压缩、噪点和虚拟水印,自由调节做旧程度。
图片压缩
使用 ›选择画质和输出格式,预览压缩前后的大小。
相关文章