【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. 自定义注解的处理
    可以创建自定义注解,并结合反射来控制程序的行为。例如,创建一个注解用于记录日志,或者控制某个方法的访问权限等。

小结:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/84181.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

阿里云百炼(1) : 阿里云百炼应用问答_回答图片问题_方案1_提问时上传图片文件

直接用于拍照答题不大理想, 可能适用其他用途, 更好的方案: 阿里云百炼(1) : 阿里云百炼应用问答_回答图片问题_方案2_提取题目再提问-CSDN博客 1.实现代码 package cn.nordrassil.ly.test.拍照答题;import com.alibaba.dashscope.app.Application; import com.alibaba.dashsc…

深入探索 CSS 中的伪类:从基础到实战​

在前端开发的世界里&#xff0c;CSS 作为网页样式的 “化妆师”&#xff0c;有着至关重要的作用。而 CSS 伪类则像是这位 “化妆师” 手中的神奇画笔&#xff0c;能够基于元素的状态或位置为其添加独特的样式&#xff0c;极大地丰富了网页的交互性和视觉效果。接下来&#xff0…

c++ constexpr关键字

constexpr字面意思为常量表格式&#xff0c; 用于指示编译器在编译时计算表达式的值。 1、作为常量表格式&#xff0c;必须在编译时就能确定其值。如&#xff1a;constexpr int size 9527; 2、可以修饰函数&#xff0c;要求能在编译时求值&#xff0c;所以传的参数也必须是编…

服务器硬盘分类

以下是服务器硬盘的综合性分类与技术特性分析&#xff0c;依据当前行业标准及技术演进整理&#xff1a; 一、按存储介质分类 1. ‌机械硬盘&#xff08;HDD&#xff09;‌ ‌ 核心特性‌&#xff1a;采用旋转磁盘与机械磁头结构&#xff0c;通过磁道寻址实现数据读写 …

图解深度学习 - 机器学习简史

前言 深度学习并非总是解决问题的最佳方案&#xff1a;缺乏足够数据时&#xff0c;深度学习难以施展&#xff1b;某些情况下&#xff0c;其他机器学习算法可能更为高效。 若初学者首次接触的是深度学习&#xff0c;可能会形成一种偏见&#xff0c;视所有机器学习问题为深度学…

ConceptAttention:Diffusion Transformers learn highly interpretable features

ConceptAttention: Diffusion Transformers Learn Highly Interpretable Featureshttps://arxiv.org/html/2502.04320?_immersive_translate_auto_translate=1用flux的attention来做图文的显著性分析。 1.i

【Python正则表达式终极指南】从零到工程级实战

目录 &#x1f31f; 前言&#x1f3d7;️ 技术背景与价值&#x1fa79; 当前技术痛点&#x1f6e0;️ 解决方案概述&#x1f465; 目标读者说明 &#x1f9e0; 一、技术原理剖析&#x1f4ca; 核心概念图解&#x1f4a1; 核心作用讲解&#x1f527; 关键技术模块说明⚖️ 技术选…

C++对象的内存模型

C++对象的内存模型涉及对象的数据成员(包括静态成员和非静态成员)、成员函数以及虚函数表等在内存中的布局和管理方式。以下是C++对象的内存模型的主要组成部分: 1. C++对象的组成 一个C++对象通常由以下几个部分组成: 非静态数据成员 对象的核心组成部分,每个对象都有自己…

hugging-face数据集快速下载

开发机配置外网代理并使用 git lfs 高速下载 Hugging Face 数据集流程 本文档将介绍如何配置开发机的代理&#xff0c;登录 Hugging Face&#xff0c;并使用 git-lfs &#xff08;Git Large File Storage&#xff09;进行数据集的高速下载。 1. 配置代理连接外网 开发机在某些…

17、Python对象操作全解析:同一运算符、成员运算符与整数缓存机制实战

适合人群&#xff1a;零基础自学者 | 编程小白快速入门 阅读时长&#xff1a;约8分钟 文章目录 一、问题&#xff1a;Python 同一运算符的本质与实战&#xff1f;1、例子1&#xff1a;双胞胎身份证验证2、答案&#xff1a;&#xff08;1&#xff09;is 同一运算符介绍&#xff…

使用auto-coder将kotti项目的pyramid依赖从1.x升级到2.x,将SQLALchemy从1.x升级到2.x

缘起 kotti是一个非常好的基于pyramid框架的web搭建项目&#xff0c;但是由于作者离世&#xff0c;已经3年没有更新了。 尝试使用auto-coder将kotti项目的pyramid依赖从1.x升级到2.x&#xff0c;同时发现SQLALchemy依赖也有问题&#xff0c;将SQLALchemy从1.x升级到2.x 开始…

luckysheet的使用——17.将表格作为pdf下载到本地

luckysheet源码里面自带有打印按钮&#xff0c;但是功能是无法使用的&#xff0c;所以我把该功能重写了一遍 1.在menuButton.js文件中找到源码打印按钮的触发事件&#xff1a; $("#luckysheet-icon-print").click(function () {}2.使用自己写的挂载方法 window.pr…

仿真APP助力提升卡车驾驶室驾乘舒适度与安全性

驾驶室作为卡车的重要组成部分&#xff0c;其振动特性对于驾驶员的舒适度和长期健康具有至关重要的影响。振动不仅会导致驾驶员疲劳、分散注意力&#xff0c;还可能引发一系列健康问题。为了确保卡车在复杂路面工况下驾驶室结构不受破坏&#xff0c;并保持良好的NVH性能&#x…

功能强大且易于使用的 JavaScript 音频库howler.js 和AI里如何同时文字跟音频构思想法

howler.js 是一个功能强大且易于使用的 JavaScript 音频库&#xff0c;它提供了跨浏览器的音频播放功能&#xff0c;支持多种音频格式&#xff0c;并且具有丰富的 API&#xff0c;可以方便地控制音频的播放、暂停、循环、音量等。下面是如何在 Vue 项目中使用 howler.js 实现音…

JUC入门(七)

14、ForkJoin ForkJoin框架是Java中用于并行执行任务的框架&#xff0c;特别适合处理可以分解为多个子任务的复杂计算。它基于“分而治之”的思想&#xff0c;将一个大任务分解为多个小任务&#xff0c;这些小任务可以并行执行&#xff0c;最后将结果合并。 ForkJoin框架的核…

第 7 章:综合回顾与性能优化

本章目标: 系统化地回顾各类外设接口选型原则 深入探讨多接口并存时的资源冲突与管理策略 掌握软硬件协同的性能分析方法,快速定位并消除瓶颈 总结一整套从架构设计到现场调试的最佳实践与防坑指南 7.1 综合选型决策矩阵(深度分析) 除了前文的基础矩阵,这里引入两个更细化…

交换机的连接方式堆叠和级联

以下是交换机的堆叠和级联各自的优缺点总结&#xff0c;帮助快速对比选择&#xff1a; ​一、堆叠&#xff08;Stacking&#xff09;​ ​优点 ​高性能 堆叠链路带宽高&#xff08;如10G/40G/100G&#xff09;&#xff0c;成员间数据通过背板直连&#xff0c;无带宽瓶颈。支…

C++高效求解非线性方程组的实践指南

非线性方程组的求解是科学与工程计算中的核心问题之一&#xff0c;涉及物理建模、机器学习、金融分析等多个领域。C因其高性能和底层控制能力成为此类问题的首选语言&#xff0c;但如何高效实现求解仍存在诸多挑战。本文从算法选择、工具应用、稳定性优化及性能提升四个维度&am…

2025年- H42-Lc150 --146. LRU缓存(哈希表,双链表)需二刷--Java版

1.题目描述 2.思路 LRU(最近最少使用&#xff09;&#xff1a;如果缓存的容量为2&#xff0c;刚开始的两个元素都入栈。之后该2元素中有其中一个元素&#xff08;重点元素&#xff09;被访问。把最近访问过的重点元素保留&#xff0c;另一个边缘元素就得离开缓存了。 下面是l…

5G 网络中 DNN 的深度解析:从基础概念到核心应用

摘要 本文深度剖析 5G 网络中 DNN(数据网络名称)的核心作用与运行机制,从基础概念入手,详细阐述 DNN 在会话管理、用户面资源分配、切片选择等方面的关键功能。通过实际应用场景分析与技术实现细节探讨,揭示 DNN 如何助力 5G 网络满足多样化业务需求,为 5G 网络部署、优…