Java注解怎么用

news/2024/4/29 5:21:56/文章来源:https://blog.csdn.net/weixin_39570751/article/details/129682955

什么是注解

Java的注解(Annotation)是一种元数据,它可以提供程序的额外信息,帮助程序员更好地管理程序。注解通常被用作代码的标记或者指定某些行为的方式。在Java中,注解以@符号开头,放在代码的各个位置,包括类、方法、成员变量、参数等地方。注解可以通过反射机制在程序运行时获取到,并能对程序的执行产生一定的影响。Java提供了一些系统注解,例如@Override、@Deprecated等等,同时也支持自定义注解。

注解和注释有什么区别

注解和注释看似相似,但它们在意义和使用方式上有很大的不同。

注释(Comment)是程序员在代码中添加的一些说明信息,它们并不会对程序的运行产生任何影响,仅仅是为了方便程序员对代码的理解和维护。注释可以是单行或多行,以 // 或 /.../ 形式添加。

注解(Annotation)则是一种用来标记程序元素和提供编译器和框架额外信息的元数据。注解以 @ 符号开头,可以加在类、方法、变量等各种程序元素上,它们能够为程序的开发、维护、测试和部署等各个环节提供很多便利。注解的作用不限于提供说明信息,它还可以通过反射机制在程序运行时动态地检查和操作程序元素。

因此,注解和注释的主要区别在于:注释只是为了代码的可读性和辅助程序员理解,没有实际的功能;而注解则具有明确的语义和作用,并能够为程序的开发和维护提供各种服务。

自定义注解怎么用

自定义注解需要使用@interface定义,其内容可以由编程人员自行定义。下面是一个简单的自定义注解的例子:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {String value() default "";
}

该注解被定义为@Log,可以用于方法上,它有一个可选的value属性供注解使用者添加一些描述信息。

注意,以上代码是不能直接运行的,因为还涉及到aop切面和反射的知识,完整示例程序看文末。

自定义注解在实际开发中可以有很多用途,下面举几个例子:

@ParamName注解

在Java中,方法的参数没有名称,只能通过索引来访问。有时候代码可读性会因为这个问题而受到影响,因此我们可以用自定义注解来为方法的参数添加名称:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface ParamName {String value();
}

使用方式:

public void foo(@ParamName("param1") int param1, @ParamName("param2") double param2) {// do something
}

这样,在运行时我们就可以通过反射机制获取到每个参数的名称。

@Cacheable注解

在实际开发中,我们往往需要对一些计算量较大或者耗时较长的方法进行缓存,用自定义注解可以非常方便地实现这个功能:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Cacheable {String value();
}

然后我们可以用反射机制获取到被@Cacheable注解的方法,对其返回值做缓存。

@Encrypt注解

在实际开发中,我们可能需要对某些敏感数据进行加密,而不是直接存储明文。用自定义注解可以为某些变量添加自动加密的功能,例如:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Encrypt {boolean enable() default true;
}

然后我们可以通过反射机制获取到被@Encrypt注解的变量,如果该注解的enable属性为true,就对该变量进行加密操作。

SpringBoot中的常见注解

@SpringBootApplication:该注解为Spring Boot的入口注解,整合了@Configuration、@EnableAutoConfiguration和@ComponentScan三个注解。

@RestController:声明一个控制器类,并且该类中的所有方法都以JSON的形式返回。

@RequestBody:该注解用于接收请求体的数据,并将其转换为Java对象。

@RequestMapping:定义访问路由,可以设置请求方法、参数、请求头等。

@PathVariable:获取RESTful接口中的路径参数。

@RequestParam:获取请求参数。

@Autowired:该注解用于自动注入依赖,可以配合@Qualifier注解进行精确匹配。

@Value:该注解用于获取配置文件中的属性值。

@ConfigurationProperties:该注解用于将配置文件中的属性值注入到Java Bean中。

@EnableAutoConfiguration:该注解自动配置Spring应用程序,简化了Spring应用程序的配置。

@ConditionalOnProperty:该注解用于控制某个配置项是否启用,可以设置默认值、匹配规则等。

@EnableAsync:该注解启用异步调用。

@Async:该注解将标记的方法异步执行。

@Scheduled:该注解用于定时任务。

我们日常开发会怎么用到自定义注解

校验参数

我们可以通过自定义注解来对控制器方法的参数做参数校验,例如:

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ValidParam {String value();
}public void update(@ValidParam("id") long id, @ValidParam("name") String name) {// do something
}

然后在方法执行前,我们可以根据@ValidParam注解的值对参数进行校验。

日志输出

我们可以通过自定义注解来标注一些需要进行日志输出的方法,例如:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {String value();
}@Log("更新订单状态")
public void updateOrderStatus() {// do something
}

然后在方法执行时,我们可以根据@Log注解的值来输出相应的日志。

缓存管理

我们可以通过自定义注解来标注一些需要进行缓存的方法,例如:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Cache {long expire() default 3600; // 缓存失效时间,默认为3600秒String key() default ""; // 缓存key
}@Cache(expire = 1800, key = "user_{#id}")
public User getUserById(long id) {// do something
}

然后在方法执行前,我们可以根据@Cache注解的值来判断是否从缓存中获取数据。

Spring AOP

我们可以通过自定义注解来搭配Spring AOP完成一些需求,例如:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CheckLogin {boolean required() default true; // 该接口是否需要登录
}
@CheckLogin
@RequestMapping("/getUserInfo")
public UserInfo getUserInfo() {// do something
}

然后在AOP切面中,我们可以通过@CheckLogin注解的值来判断是否需要进行登录验证。

完整实例代码

以第一个Log注解为例,让我们来看看怎么把程序跑起来。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {String value() default "";
}

用idea创建一个maven工程,打开pom.xml,添加spring的aop模块。除此之外,还需要引入Spring IoC容器和AspectJ依赖。

<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.9</version>
</dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.3.9</version>
</dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.6</version>
</dependency>

Log注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Log {String value();
}

Log切面

@Aspect
public class LogAspect {@Around("@annotation(com.zhujie.Log)")public Object log(ProceedingJoinPoint joinPoint) throws Throwable {MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();Log logAnnotation = method.getAnnotation(Log.class);if (logAnnotation != null) {String value = logAnnotation.value();System.out.println("Log: " + value);}return joinPoint.proceed();}}

@Around

@Around("@annotation(com.zhujie.Log)")

这个@Around注解中的参数是切点表达式,用来匹配需要被切入的方法。其中"@annotation(com.example.Log)"这部分是一个注解切点,表示需要匹配所有被@Log注解修饰的方法。

具体来说,@Around表示在方法执行前后都执行一段代码,包裹着原本要执行的方法。在执行这段代码时,可以获取到方法和参数的信息,对其进行处理或者记录日志等操作。

@annotation表示对注解的切面,后面跟着注解的类型,比如@annotation(com.zhujie.Log)就是表示对@Log注解的切面。这个切面就是指定了需要拦截所有被@Log注解修饰的方法,用来完成相应的操作。

UserService

@Service
class UserService {@Log("用户新增")public void add() {}
}

给add方法加上了@Log注解,只要add方法一执行,就会打印用户新增。

启动类:

@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class AppConfig {@Beanpublic LogAspect logAspect() {return new LogAspect();}public static void main(String[] args) {// 使用Spring上下文来管理BeanApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);// 获取LogService BeanUserService userService = context.getBean(UserService.class);// 调用含有@Log注解的方法userService.add();}
}

@ComponentScan注解是用来扫描指定包及其子包下的所有组件,自动将其注入到容器中。但是,对于一些比较特殊的组件,如AOP切面等,需要手动在配置类中将其注入到容器中。

在使用AOP时,有两种方式:一种是使用XML配置来创建切面,另一种是使用注解方式来创建切面。使用注解方式创建切面时,需要在配置类中使用@Bean注解来创建切面实例,并使用@EnableAspectJAutoProxy注解来开启AOP代理支持。

运行AppConfig,效果如预期。

 

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

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

相关文章

【数据结构】千字深入浅出讲解队列(附原码 | 超详解)

&#x1f680;write in front&#x1f680; &#x1f4dd;个人主页&#xff1a;认真写博客的夏目浅石. &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f4e3;系列专栏&#xff1a;C语言实现数据结构 &#x1f4ac;总结&#xff1a;希望你看完…

linux驱动学习加强版-2(文件驱动的书写)

文章目录一、驱动的外设二、驱动操作文件原理三、编写一个驱动程序3.1 编写驱动程序的步骤3.1.2 确定主设备号以及注册驱动3.1.3 实现对应的函数四、一些错误现象一、驱动的外设 我们的设备硬件都需要驱动才能工作&#xff0c;没有驱动的硬件可以称之为废铁&#xff0c;没有硬…

spacesniffer文件大小查看工具安装和使用

软件描述 spacesniffer是一块可以快速查看电脑中所有文件大小的工具&#xff0c;当电脑空间不够时&#xff0c;可以迅速找出不需要的大提及文件。 一、软件下载 1、从网盘下载 spacesniffer文件大小查看工具 2、从官网下载 http://www.uderzo.it/main_products/space_sni…

供水管网微观水力模型

国外在管网建模方面起步于20世纪60年代。20世纪80年代&#xff0c;随着计算机及相应技术的发展&#xff0c;遥测远传设备的应用进入了实用化阶段&#xff0c;国内已有很多供水企业实现了供水管网建模。给水管网系统建模&#xff0c;就是为仿真模拟管网系统动态实时运行情况建立…

【论文阅读总结】用于目标检测的特征金字塔网络(FPN)

Feature Pyramid Networks for Object Detection1.摘要2.引言2.1 低级特征对于检测小物体很重要2.2 算法目标3. 文献综述3.1 Hand-engineered features and early neural networks3.2 Deep ConvNet object detectors3.3 Methods using multiple layers4.Feature Pyramid Networ…

LangChain:Prompt Templates介绍及应用

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️&#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

WPF+WebView2+react/vue/angular

创建WPF项目 安装WbeView2 Nuget包 在窗体中添加命名空间 xmlns:wv2"clr-namespace:Microsoft.Web.WebView2.Wpf;assemblyMicrosoft.Web.WebView2.Wpf"使用控件 <wv2:WebView2 x:Name"webview"/>在MainWindow中初始化 public MainWindow(){Initia…

什么是语法糖?Java中有哪些语法糖?

本文从 Java 编译原理角度&#xff0c;深入字节码及 class 文件&#xff0c;抽丝剥茧&#xff0c;了解 Java 中的语法糖原理及用法&#xff0c;帮助大家在学会如何使用 Java 语法糖的同时&#xff0c;了解这些语法糖背后的原理1 语法糖语法糖&#xff08;Syntactic Sugar&#…

Linux syslog 日志服务

文章目录Syslog 概述syslog 协议标准syslog APIsyslog 日志文件日志文件介绍日志配置产生本地日志参考文章Syslog 概述 syslog 常被称为系统日志或系统记录&#xff0c;系统日志通过 syslog 进程记录系统的有关事件&#xff0c;也可以记录应用程序运作事件。通过适当配置&…

Python批量删除或移动指定图像

Python批量删除或移动指定图像前言一、批量删除指定名称的图像二、批量移动指定名称的图像前言 笔者的研究方向为计算机视觉&#xff0c;因此经常和大量图像打交道&#xff0c;有时需要批量删除一些图像&#xff0c;有时需要批量移动一些图像&#xff0c;因此编写了下述代码。下…

flink 读取文件数据写入ElasticSearch

前言 es是大数据存储的必备中间件之一,通过flink可以读取来自日志文件,kafka等外部数据源的数据,然后写入到es中,本篇将通过实例演示下完整的操作过程; 一、前置准备 1、提前搭建并开启es服务(本文使用docker搭建的es7.6的服务); 2、提前搭建并开启kibana服务(便于操…

【Java 】Java NIO 底层原理

文章目录1、 Java IO读写原理1.1 内核缓冲与进程缓冲区1.2 java IO读写的底层流程2、 四种主要的IO模型3、 同步阻塞IO&#xff08;Blocking IO&#xff09;4、 同步非阻塞NIO&#xff08;None Blocking IO&#xff09;5、 IO多路复用模型(I/O multiplexing&#xff09;6、 异步…

Cursor编程初体验,搭载GPT-4大模型,你的AI助手,自然语言编程来了

背景 这两天体验了下最新生产力工具Cursor&#xff0c;基于最新的 GPT-4 大模型&#xff0c;目前免费&#xff0c;国内可访问&#xff0c;不限次数&#xff0c;跨平台&#xff0c;你确定不来体验一把&#xff1f;官方的 Slogan &#xff1a; Build Software. Fast. Write, edi…

差速巡线机器人设计-良好(80+)的报告-2023

如何提分&#xff1f;将一篇报告提升20分以上呢&#xff1f;差速巡线机器人设计-及格&#xff08;60&#xff09;的报告-2023_zhangrelay的博客-CSDN博客姓名&#xff1a; 学号&#xff1a; 实践项目1名称&#xff1a;差速巡线机器人设计 60分&#xff1a;缺乏思考、没有对比、…

攻防世界-first

题目下载&#xff1a;下载 IDA载入 __int64 __fastcall main(int a1, char **a2, char **a3) {__useconds_t *v3; // rbpunsigned int v4; // eaxint *v5; // rcxint v6; // edxunsigned int v7; // eaxsigned __int64 v8; // rcx__int64 v9; // raxchar v10; // blchar v11;…

为知笔记私有化部署

前言 原来一直买的为知笔记vip&#xff0c;但是随着内容越来越&#xff0c;并且不好整理。同时还不能一键全部导出&#xff0c;最后决定将数据迁移到自己服务器上。为止笔记提供了docker镜像&#xff0c;这也方便了部署&#xff08;其实吧&#xff0c;从产品层面&#xff0c;可…

C++ Lambda表达式的常见用法

⭐️我叫忆_恒心&#xff0c;一名喜欢书写博客的在读研究生&#x1f468;‍&#x1f393;。 如果觉得本文能帮到您&#xff0c;麻烦点个赞&#x1f44d;呗&#xff01; 近期会不断在专栏里进行更新讲解博客~~~ 有什么问题的小伙伴 欢迎留言提问欧&#xff0c;喜欢的小伙伴给个三…

【Django 网页Web开发】05. 数据库操作,实战用户管理(保姆级图文)

目录1. 安装第三方模块2. ORM2.1 自己手动创建数据库2.2 django连接数据库2.3 建表语句写在哪里&#xff1f;2.4 建表语句写好后如何运行生效&#xff1f;3. 操作表3.1 创建数据表3.2 修改数据表4. 操作数据4.1 插入数据4.2 删除数据4.3 修改数据4.4 查询数据5. 实战&#xff1…

pytest学习和使用22-allure特性 丨总览中的Environment、Categories设置以及Flaky test使用

22-allure特性 丨总览中的Environment和Categories设置1 Environment设置1.1 设置方法1.2 创建文件2 Categories设置2.1 设置方式2.2 创建文件3 关于Flaky test3.1 Flaky test介绍3.2 产生Flaky Tests的原因3.3 Flaky安装3.4 Flaky使用3.5 小结小结1小结2如下图&#xff0c;我们…

开始学习HTML5

HTML5 简介 HTML5是HTML最新的修订版本&#xff0c;2014年10月由万维网联盟&#xff08;W3C&#xff09;完成标准制定。 HTML5的设计目的是为了在移动设备上支持多媒体。 HTML5简单易学。 什么是 HTML5? HTML5 是下一代 HTML 标准。 HTML , HTML 4.01的上一个版本诞生于 1…