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自定义注解的资料请关注代码网其它相关文章!
发表评论