1.什么是注解
注解(annotation),也叫元数据。一种代码级别的说明。它是jdk1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
元注解
有一些注解可以修饰其他注解,这些注解就称为元注解(meta annotation)。java标准库已经定义了一些元注解,我们只需要使用元注解,通常不需要自己去编写元注解。
@target
最常用的元注解是@target
。使用@target
可以定义annotation
能够被应用于源码的哪些位置:
- 类或接口:
elementtype.type
; - 字段:
elementtype.field
; - 方法:
elementtype.method
; - 构造方法:
elementtype.constructor
; - 方法参数:
elementtype.parameter
。
例如,定义注解@report
可用在方法上,我们必须添加一个@target(elementtype.method)
:
@target(elementtype.method) public @interface report { int type() default 0; string level() default "info"; string value() default ""; }
定义注解@report
可用在方法或字段上,可以把@target
注解参数变为数组{ elementtype.method, elementtype.field }
:
@target({ elementtype.method, elementtype.field }) public @interface report { ... }
实际上@target
定义的value
是elementtype[]
数组,只有一个元素时,可以省略数组的写法。
@retention
另一个重要的元注解@retention
定义了annotation
的生命周期:
- 仅编译期:
retentionpolicy.source
; - 仅class文件:
retentionpolicy.class
; - 运行期:
retentionpolicy.runtime
。
如果@retention
不存在,则该annotation
默认为class
。因为通常我们自定义的annotation
都是runtime
,所以,务必要加上@retention(retentionpolicy.runtime)
这个元注解:
@retention(retentionpolicy.runtime) public @interface report { int type() default 0; string level() default "info"; string value() default ""; }
@repeatable
使用@repeatable
这个元注解可以定义annotation
是否可重复。这个注解应用不是特别广泛。
@repeatable(reports.class) @target(elementtype.type) public @interface report { int type() default 0; string level() default "info"; string value() default ""; } @target(elementtype.type) public @interface reports { report[] value(); }
经过@repeatable
修饰后,在某个类型声明处,就可以添加多个@report
注解:
@report(type=1, level="debug") @report(type=2, level="warning") public class hello { }
@inherited
使用@inherited
定义子类是否可继承父类定义的annotation
。@inherited
仅针对@target(elementtype.type)
类型的annotation
有效,并且仅针对class
的继承,对interface
的继承无效:
@inherited @target(elementtype.type) public @interface report { int type() default 0; string level() default "info"; string value() default ""; }
在使用的时候,如果一个类用到了@report
:
@report(type=1) public class person { }
则它的子类默认也定义了该注解:
public class student extends person { }
2.代码工程
实验目的
实现统计方法执行时间的注解
pom.xml
<?xml version="1.0" encoding="utf-8"?> <project xmlns="http://maven.apache.org/pom/4.0.0" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactid>springboot-demo</artifactid> <groupid>com.et</groupid> <version>1.0-snapshot</version> </parent> <modelversion>4.0.0</modelversion> <artifactid>annotations</artifactid> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-autoconfigure</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-test</artifactid> <scope>test</scope> </dependency> <dependency> <groupid>org.projectlombok</groupid> <artifactid>lombok</artifactid> </dependency> <dependency> <groupid>org.aspectj</groupid> <artifactid>aspectjweaver</artifactid> </dependency> <dependency> <groupid>org.assertj</groupid> <artifactid>assertj-core</artifactid> </dependency> <dependency> <groupid>org.aspectj</groupid> <artifactid>aspectjrt</artifactid> </dependency> <!-- fastjson --> <dependency> <groupid>com.alibaba</groupid> <artifactid>fastjson</artifactid> <version>1.2.21</version> </dependency> </dependencies> </project>
controller
使用自定义注解@requesttime
package com.et.annotation.controller; import com.et.annotation.requesttime; import org.springframework.web.bind.annotation.requestmapping; import org.springframework.web.bind.annotation.restcontroller; import java.util.hashmap; import java.util.map; @restcontroller public class helloworldcontroller { @requestmapping("/hello") @requesttime public map<string, object> showhelloworld(){ map<string, object> map = new hashmap<>(); map.put("msg", "helloworld"); return map; } }
custom annotation
自定义@requesttime注解
package com.et.annotation; import java.lang.annotation.*; /** * computa the excute time for the method */ @target({elementtype.method}) @retention(retentionpolicy.runtime) @inherited public @interface requesttime { }
具体的拦截逻辑类
package com.et.annotation; import com.et.annotation.util.aspectutil; import lombok.extern.slf4j.slf4j; import org.aspectj.lang.proceedingjoinpoint; import org.aspectj.lang.annotation.around; import org.aspectj.lang.annotation.aspect; import org.aspectj.lang.annotation.pointcut; import org.springframework.stereotype.component; import java.lang.reflect.method; @slf4j @aspect @component public class requesttimeaspect { @pointcut(value = "@annotation(com.et.annotation.requesttime)") public void pointcut() { } @around("pointcut()") public object handle(proceedingjoinpoint point) throws throwable { method currentmethod = aspectutil.getmethod(point); long starttime = system.currenttimemillis(); object result = point.proceed(); long endtime = system.currenttimemillis(); long requesttime =endtime-starttime; //if(requesttime>1000){ log.info(aspectutil.getclassname(point)+"."+currentmethod.getname()+"execute time:"+requesttime+" ms"); //} return result; } }
以上只是一些关键代码,所有代码请参见下面代码仓库
代码仓库
- https://github.com/harries/springboot-demo(annotations)
3.测试
启动spring boot应用程序
访问http://127.0.0.1:8088/hello
控制台输出 日志
2024-08-10 19:30:43.670 info 3343 --- [nio-8088-exec-1] com.et.annotation.requesttimeaspect : com_et_annotation_controller_helloworldcontroller.showhelloworldexecute time:41 ms
以上就是详解springboot如何自定义注解的详细内容,更多关于springboot自定义注解的资料请关注代码网其它相关文章!
发表评论