Java注解逻辑位置、差异化机制及自定义方法咨询
Java注解核心问题解答
一、注解逻辑实现的位置
注解本身只是元数据标记,没有自带逻辑。它的功能实现分两类场景:
- 编译期逻辑:由注解处理器(Annotation Processor)执行,比如编译器内置处理器处理
@Override,第三方框架的处理器处理JPA、Lombok等注解,这类逻辑在编译阶段完成,生成字节码或做语法校验。 - 运行期逻辑:通过Java反射API读取注解信息,由业务代码或框架逻辑执行,比如Spring、JPA在程序运行时扫描注解,触发依赖注入、ORM映射等操作。
二、结构相同的注解差异在哪里
两个结构相似的注解,核心差异体现在两点:
- 元注解配置:元注解(
@Retention、@Target等)决定了注解的生命周期、作用目标、是否可继承等属性,这是注解功能的基础。 - 语义与配套逻辑:不同注解被不同的工具/框架识别,绑定了完全不同的处理逻辑——注解的名字本身就是一种语义约定,工具会根据注解名执行对应的逻辑。
以@Id、@Override、@Embeddable为例,它们的源码结构(interface定义)看似一致,但本质差异极大:
@Override:元注解是@Retention(SOURCE),仅在编译期有效。编译器会在编译时检查被标记的方法是否真的重写了父类方法,编译完成后该注解会被直接丢弃,不会进入字节码。@Id:元注解是@Retention(RUNTIME),运行时可被反射读取。JPA框架在运行时扫描实体类,将标记@Id的字段识别为主键,自动生成主键映射的SQL逻辑。@Embeddable:同样是@Retention(RUNTIME)级别,但JPA会将标记的类视为嵌入式组件,把类中的字段直接映射到宿主实体的数据库表字段中,而非单独生成表。
三、无法查看逻辑代码时,如何创建自定义注解
按以下步骤落地:
- 明确注解用途:先确定是做编译期校验/代码生成,还是运行时的逻辑触发(比如日志、权限校验)。
- 定义注解类:用
@interface关键字声明,搭配必要的元注解:@Retention:指定生命周期(SOURCE仅编译期、CLASS字节码保留、RUNTIME运行时可反射)@Target:指定可标记的元素(METHOD、FIELD、TYPE等)- 可选
@Documented(生成Javadoc时包含)、@Inherited(子类可继承父类注解)
- 实现处理逻辑:
- 编译期场景:编写继承
AbstractProcessor的处理器,注册到META-INF/services/javax.annotation.processing.Processor,在process方法中处理注解,完成代码生成或语法校验。 - 运行期场景:用反射API(如
Class.getAnnotations()、Method.getAnnotation())扫描带有自定义注解的元素,编写对应的业务逻辑触发代码。
- 编译期场景:编写继承
- 测试验证:将注解标记到目标元素上,编译或运行程序,验证是否达到预期效果。
举个简单的运行时自定义注解示例:
// 自定义注解 import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.annotation.ElementType; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface LogMethod { String value() default "执行方法"; } // 注解处理逻辑 public class LogProcessor { public static void process(Object obj) throws Exception { for (var method : obj.getClass().getDeclaredMethods()) { LogMethod logAnno = method.getAnnotation(LogMethod.class); if (logAnno != null) { System.out.println(logAnno.value() + ": " + method.getName()); method.invoke(obj); } } } } // 注解使用 public class Test { @LogMethod("调用测试方法") public void test() { System.out.println("方法执行中"); } public static void main(String[] args) throws Exception { LogProcessor.process(new Test()); } }
内容的提问来源于stack exchange,提问作者v0ld3m0rt
相关产品推荐
相关产品推荐

