Java篇-自定义注解

image.png

简介

Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。
Java 语言中的类、方法、变量、参数和包等都可以被标注。和 Javadoc 不同,Java 标注可以通过反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。Java 虚拟机可以保留标注内容,在运行时可以获取到标注内容 。 当然它也支持自定义 Java 标注。

元注解

  • @Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
  • @Documented - 标记这些注解是否包含在用户文档中。
  • @Target - 标记这个注解应该是哪种 Java 成员。
  • @Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)
    从 Java 7 开始,额外添加了 3 个注解:
  • @SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
  • @FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。
  • @Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。

自定义注解

注解

1
2
3
4
5
6
7
8
9
import java.lang.annotation.*;

@Documented
@Inherited
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Value {
public String value() default "";
}

实体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class User {

private String name;
private String introduce;

public String getName() {
return name;
}
@Value(value = "mikey")
public void setName(String name) {
this.name = name;
}

public String getIntroduce() {
return introduce;
}

@Value(value = "i am mikey")
public void setIntroduce(String introduce) {
this.introduce = introduce;
}
}

实体工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.lang.reflect.Method;

public class UserFactory {
public static User create(){
User user = new User();
Method[] methods = User.class.getMethods();
try {
for (Method method : methods) {
if (method.isAnnotationPresent(Value.class)){
Value annotation = method.getAnnotation(Value.class);
method.invoke(user,annotation.value());
}
}
}catch (Exception e){
e.printStackTrace();
return null;
}
return user;
}
}

调用

1
2
3
4
5
6
7
public class Main {
public static void main(String[] args) {
User user = UserFactory.create();
System.out.println(user.getName());
System.out.println(user.getIntroduce());
}
}

简单案例

打印日志注解的实现

1.定义注解

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.example.annotation.annotation;

import java.lang.annotation.*;

@Target(ElementType.METHOD)//作用于方法
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
//注解属性
String name() default "";;
String prot() default "";;
String value() default "默认值";
}

2.定义切面和解析

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
49
50
51
52
53
package com.example.annotation.aop;

import com.example.annotation.annotation.Log;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
* 切面
*/
@Aspect // 注解声明一个切面
@Component // 受spring管理的容器
public class LogAspect {
@Pointcut("@annotation(com.example.annotation.annotation.Log)") // 注解声明切点,注解的全限定名
public void annotationPointcut() {
};

/**
* befor
* @param joinPoint
*/
@Before("annotationPointcut()")
public void before(JoinPoint joinPoint){
MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
Method method = methodSignature.getMethod();
String name = method.getName();
//获取方法上的注解
Log annotation = method.getAnnotation(Log.class);
System.out.println(name+"方法执行之前执行");
System.out.println("name:"+annotation.name());
}

/**
* after
* @param joinPoint
*/
@After("annotationPointcut()")
public void after(JoinPoint joinPoint) {
MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
Method method = methodSignature.getMethod();
String name = method.getName();
//获取方法上的注解
Log annotation = method.getAnnotation(Log.class);
System.out.println(name+"方法执行之后执行");
System.out.println("name:"+annotation.name());
}
}

3.使用注解

1
2
3
4
5
6
7
8
9
10
@RestController
public class Controller {

@Log(name = "测试日志注解")
@RequestMapping("/")
public String logAnnoMethod(){
System.out.println("Controller logAnnoMethod Method body execute...");
return "success";
}
}

4.测试使用

1
2
3
4
5
6
7
8
@SpringBootApplication
@Configuration //注册被spring管理
@EnableAspectJAutoProxy //注解开启对aspectJ的支持
public class AnnotationApplication {
public static void main(String[] args) {
SpringApplication.run(AnnotationApplication.class, args);
}
}

5.使用效果

参考资料

Java自定义注解


Java篇-自定义注解
https://mikeygithub.github.io/2018/03/08/yuque/Java篇-自定义注解/
作者
Mikey
发布于
2018年3月8日
许可协议