当前位置: 首页 > news >正文

【Java】Java元注解

@Target(ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface OperatorLog {String source() default "WEB"; //日志操作来源 默认是web,还有socket的String model() default ""; //操作模块
}

这个代码中的 @Target@Retention元注解(meta-annotations),它们用于指定自定义注解的使用规则和行为。元注解本身并不直接影响注解的功能,而是控制注解如何被应用和如何被处理。

元注解解析:

  1. @Target

    • 作用:指定自定义注解可以应用于哪些程序元素。常见的元素类型有:
      • ElementType.METHOD:表示该注解只能应用于方法。
      • ElementType.TYPE:表示该注解可以应用于类、接口、枚举等类型。
      • ElementType.FIELD:表示该注解可以应用于字段。
      • ElementType.PARAMETER:表示该注解可以应用于方法参数。
      • ElementType.LOCAL_VARIABLE:表示该注解可以应用于局部变量。
      • ElementType.CONSTRUCTOR:表示该注解可以应用于构造函数。
      • ElementType.ANNOTATION_TYPE:表示该注解可以应用于其他注解。
      • ElementType.PACKAGE:表示该注解可以应用于包。

    在你的代码中,@Target(ElementType.METHOD) 表示 OperatorLog 注解只能应用于方法上。也就是说,你不能将该注解应用于字段或类上。

  2. @Retention

    • 作用:指定注解在什么时机可用。常见的保留策略有:
      • RetentionPolicy.SOURCE:注解仅存在于源代码中,编译后会被丢弃。
      • RetentionPolicy.CLASS:注解会被编译器保留在 .class 文件中,但在运行时不可用(默认行为)。
      • RetentionPolicy.RUNTIME:注解会被编译并保留在 .class 文件中,运行时可通过反射读取。通常自定义注解都使用 RUNTIME 保留策略,便于在运行时进行处理。

    在你的代码中,@Retention(value = RetentionPolicy.RUNTIME) 表示 OperatorLog 注解在运行时依然可用,可以通过反射来访问。

总结即为:

  • @Target 用来指定注解应用的场景,通常需要使用它来限制注解的应用范围。
  • @Retention 用来指定注解的生命周期,通常也需要使用它来确保注解在编译后仍然可以被访问(例如通过反射)。
  • 其他元注解:除了 @Target@Retention,Java 还提供了其他元注解,如:
    • @Documented:表示该注解会出现在 Javadoc 中,适用于文档化注解。
    • @Inherited:表示该注解可以被子类继承(仅对类注解有效)。
    • @Conditional(HAEnabledCheck.class)这是核心的元注解,表示 @HaEnabled 注解的启用依赖于条件判断。@Conditional 注解接收一个类(这里是 HAEnabledCheck)作为参数,只有当这个类的判断条件为 true 时,@HaEnabled 注解才会生效。
      HAEnabledCheck 是一个条件类,通常是一个实现了 Condition 接口的类,它决定是否启用带有 @HaEnabled 注解的功能。

如果你希望在自定义注解上使用反射,或者限制注解应用的范围,就需要使用这些元注解。

注解和反射

在Java中,“在注解上使用反射”指的是通过反射机制在运行时动态地读取和处理注解的内容。反射是一种在程序运行时检查和操作类、方法、字段等的能力,而注解是一种用于在代码中添加元数据的机制。

反射和注解的关系

注解本身只是对代码的标记,它不会自动执行某些操作,反而需要程序在运行时通过反射去读取它,基于注解的信息做一些逻辑上的处理。例如,AOP(面向切面编程)就是通过反射读取注解,来决定是否在方法执行前、后或者抛出异常时执行某些逻辑。

如何通过反射读取注解

  1. 定义注解
    首先,你需要定义一个注解,并在注解上使用元注解(如 @Target, @Retention)来指定注解的使用规则和生命周期。

    示例:

    @Retention(RetentionPolicy.RUNTIME)  // 保留到运行时
    @Target(ElementType.METHOD)         // 只允许用于方法
    public @interface MyAnnotation {String value() default "defaultValue";  // 注解中的属性
    }
    
  2. 在代码中使用注解
    然后,你可以在代码中的方法上使用该注解,来标记某些方法。

    示例:

    public class MyClass {@MyAnnotation(value = "Hello, World!")public void myMethod() {System.out.println("Executing myMethod...");}
    }
    
  3. 通过反射读取注解
    接下来,通过反射,你可以获取方法上的注解信息,并根据注解的内容来执行相应的操作。为了读取注解,你可以使用 Method 类的 getAnnotation 方法。

    示例:

    import java.lang.annotation.Annotation;
    import java.lang.reflect.Method;public class AnnotationExample {public static void main(String[] args) throws Exception {// 获取 MyClass 类的字节码对象Class<MyClass> clazz = MyClass.class;// 获取 myMethod 方法的 Method 对象Method method = clazz.getMethod("myMethod");// 检查该方法是否有 MyAnnotation 注解if (method.isAnnotationPresent(MyAnnotation.class)) {// 获取 MyAnnotation 注解MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);// 读取注解中的值System.out.println("Annotation value: " + annotation.value());}// 执行方法MyClass obj = new MyClass();obj.myMethod();}
    }
    
  4. 运行结果
    在运行时,程序会读取 myMethod 上的 MyAnnotation 注解,并输出注解中的 value 属性内容,执行结果如下:

    Annotation value: Hello, World!
    Executing myMethod...
    

为什么需要在注解上使用反射?

反射与注解的结合非常强大,它能够让你在程序运行时根据注解的内容动态地改变程序行为,这就是所谓的“注解驱动编程”。

常见的应用场景有:

  1. AOP(面向切面编程)
    使用注解标记方法,然后通过反射获取注解的值,执行一些逻辑(如日志、权限检查、事务控制等)对方法进行增强。比如Spring中的@Transactional注解,使用反射来判断方法是否需要事务支持。

    @Transactional
    public void someMethod() {// 业务逻辑
    }
    
  2. 依赖注入(DI)
    在Spring等框架中,通过注解(如 @Autowired@Inject)标记字段或方法,框架通过反射读取这些注解并自动注入依赖。

    @Autowired
    private MyService myService;
    
  3. ORM(对象关系映射)框架
    在ORM框架中,注解可以标记实体类与数据库表的映射关系,框架通过反射读取注解,在数据库中进行查询、插入等操作。

    @Entity
    public class User {@Idprivate Long id;private String name;
    }
    
  4. 自定义注解的处理
    可以创建自定义注解,并结合反射来控制程序的行为。例如,创建一个注解用于记录日志,或者控制某个方法的访问权限等。

小结:

“在注解上使用反射”就是通过反射机制,在程序运行时,动态地获取注解的值,并基于这些值来执行一些操作。反射提供了灵活的动态行为,注解则提供了丰富的元数据支持,两者结合能够实现很多灵活的功能,例如日志记录、事务管理、权限控制等。

相关文章:

  • YOLOv8检测头代码详解(示例展示数据变换过程)
  • 防火墙NAT地址组NAT策略安全策略
  • 香港中农国际集团启动“百校农业计划”,助力全球农业人才培养
  • AI练习:折叠效果
  • 2025 年高尔夫蓝牙音箱市场报告:需求激增下的机遇与挑战
  • 光电耦合器与数字容隔离器的“光速对话”
  • linux cpu占用高的故障怎么排除
  • 智能变电站——三层两网
  • python打卡day34@浙大疏锦行
  • md5升级scram-sha-256认证
  • 文档结构化专家:数字化转型的核心力量
  • 架构师论文《论软件可靠性模型的设计与实现》
  • CAD标注样式如何设置?详细教程来了
  • 解锁内心的冲突:神经症冲突的理解与解决之道
  • 某某观鸟记录(rsa加密、MD5加密)返回数据AES解密逆向分析
  • 回溯算法:解锁多种问题的解决之门
  • 前端可视化
  • 实用蓝牙耳机哪款好?先做好使用场景分析!
  • 爬虫IP代理技术深度解析:场景、选型与实战应用
  • 认知偏差:你的思维如何在工作中给你设置障碍以及如何克服它们
  • 加强两微一端和门户网站建设/广告推广方案怎么写
  • 算命网站该怎样做/百一度一下你就知道
  • 网站建设模块是什么意思/广州百度快速优化排名
  • 济南企业网站搭建/企业建站用什么好
  • 推广普通话绘画/奉化网站关键词优化费用
  • 做wow宏的网站/国外网站怎么推广