是什么

在java中注解有两种,元注解和自定义注解

自定义注解

开发者自己定义的注解,包括框架中提供的 @Autowired等等

元注解

描述注解的注解
元注解 作用 @Target 指定注解使用的适用范围(类、方法、字段等) @Retention 指定注解的生命周期(源码、class文件、运行时等) @Documented 表示该注解会被javadoc文档记录 @Inherited 表示该注解的子类可以继承父类的注解,只能作用于类上的注解

元注解参数说明

@Target

  • ElementType.METHOD:用于描述方法。
  • ElementType.TYPE:用于描述类、接口(包括注解类型)或者enum声明。
  • ElementType.CONSTRUCTOR:用于描述构造器。
  • ElementType.FIELD:用于描述成员变量、对象、属性(包括enum实例)。
  • ElementType.LOCAL_VARIABLE:用于描述局部变量。
  • ElementType.PACKAGE:用于描述包。
  • ElementType.PARAMETER:用于描述参数。
  • ElementType.ANNOTATION_TYPE:用于描述参数。

@Retention

  • RetentionPolicy.RUNTIME:始终不会丢弃,运行且保留该注解,因此可以使用反射机制读取该注解的信息。 自定义注解常用
  • RetentionPolicy.SOURCE:在编译阶段丢弃,这些注解在编译结束之后就不再有任何意义,所以他们不会写入字节码 例如@Override @SuppressWarnings
  • RetentionPolicy.CLASS:在类加载的时候丢弃,在字节码文件的处理中有用,注解默认使用这种方式。

案例

问题提出

记录方法的参数、返回参数以及运行时间

实现

由于用到切面需要导入jar包

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

注解定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.example.mytest.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//作用在方法上
@Target(ElementType.METHOD)
//运行时
@Retention(RetentionPolicy.RUNTIME)
public @interface JhjLog {


//描述方法
String value() default "JhjLog注解";
}

环绕切面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.example.mytest.aspect;

import com.example.mytest.annotation.JhjLog;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class JhjLogAspect {

/**
* 环绕通知切入点带有JhjLog注解的方法
*
*/
@Around("@annotation(jhjLog)")
public Object around(ProceedingJoinPoint point, JhjLog jhjLog) throws Throwable{

//通过反射获取切入点class对象
Class<?> aClass = point.getTarget().getClass();
//获取类名
String name = aClass.getName();
//获取目标方法名称
String name1 = point.getSignature().getName();
//获取JhjLog注解参数
String value = jhjLog.value();

//方法入参
Object[] args = point.getArgs();
StringBuffer buffer = new StringBuffer();
for (Object arg:args){

buffer.append(arg).append("\\");
}
System.out.println(buffer.toString());
//获取运行时间差
long l = System.currentTimeMillis();
//方法返回
Object proceed = point.proceed();
long l1 = System.currentTimeMillis();
System.out.println("时间戳"+(Long)(l1-l)+"返回值"+proceed.toString());

return proceed;


}
}

作者声明

1
如有问题,欢迎指正!