一:注解基础学习
注解从含义上讲是一种元数据,本质上只是对代码的一种注释说明,因为有了注解的解析才有了相应的功能。如果没有注解解析产生功能,它还不如注释清晰。从结构上看,注解编译后就是一个接口
元注解
元注解:元注解是一种基本注解,在定义注解时使用,主要定义注解的作用域,生命周期等等
- @Retention:定义注解的生命周期
- RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。
- RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。
- RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们
- @Documented
将注解中的元素包含到 Javadoc 中去。 - @Target
限定了运用的场景。方法,字段,类。ElementType列举了枚举值表示作用域 - @Inherited
如果一个注解使用@Inherited标记,那么使用当前注解的类的子类自动添加当前注解(子类没有显式使用注解) - @Repeatable
java8开始引入,定义的注解可以在同一个地方重复使用
注解的定义和属性
注解定义关键字是@interface,注解只有成员变量,没有方法。方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型
定义了 TestAnnotation 这个注解中拥有 id 和 msg 两个属性。在使用的时候,我们应该给它们进行赋值。赋值的方式是在注解的括号内以 value=”” 形式,多个属性之前用 ,隔开。
注意点:
- 定义属性时它的类型必须是 8 种基本数据类型外加 类、接口、注解及它们的数组
- 可以给属性设置默认值
public int id() default -1;
- 一个注解内仅仅只有一个名字为 value 的属性时,应用这个注解时可以直接接属性值填写到括号内。如果有多个属性,使用时省略属性名默认指的就是value属性
二:编译时解析注解
在使用javac编译java代码时,通过APT(注解处理器)技术获取.java文件中的注解信息,生成新的java代码(可以使用javapoet生成代码),可以实现一些功能。例如:lombok工具包
使用APT;
步骤1:继承AbstractProcessor,重写process方法
使用@AutoService生成META-INF\services\javax.annotation.processing.Processor
@AutoService的pom
<dependency>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service</artifactId>
<version>1.0-rc6</version>
</dependency>
使用:
process生成helloworld
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
System.out.println("------ process -----");
//MethodSpec这个类是要引入'com.squareup:javapoet:1.8.0'包,方便通过代码创建java文件
MethodSpec main = MethodSpec.methodBuilder("main")
//.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(void.class)
.addParameter(String[].class, "args")
.addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!")
.build();
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
//netstat -an | grep .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addMethod(main)
.build();
JavaFile javaFile = JavaFile.builder("com.txd.annotaionlearn", helloWorld)
.build();
try {
//这里的输出要在Gradle Console中看
javaFile.writeTo(System.out);
javaFile.writeTo(new File("E:\\10.workspace\\2.ST(4.0)\\test\\src\\main\\java\\com\\txd\\annotaionlearn\\model"));
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
编译,安装到本地仓库,clean install
步骤2:在maven工程中使用以上的自定义注解处理器,涉及2个插件
maven-processor-plugin和maven-compiler-plugin
此处我通过maven-compiler-plugin来使用自定义annotationprocessor
然后,mvn clean compile
会发现在控制台上:
本地生成helloworld文件
此次生成代码用到了java类库javapoet
三:运行时解析注解
注解类型必须是:@Retention(RetentionPolicy.RUNTIME)
运用反射技术提取注解:使用Class 对象的几个方法
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass){} ;
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {};
public Annotation[] getAnnotations() {};
然后就可以获取注解上的参数,做逻辑处理
四:spi使用@AutoService
spi在很多地方已经有使用:jdbc4.0以后,dubbo
五:常见的操作源代码字节码的库
字节码:javasist,cglib,ASM
源码:Javapoet
五:参考博客
- https://www.cnblogs.com/guyuehuanhuan/p/9185899.html
- https://juejin.im/entry/585617d6128fe1006994f992
- https://www.jianshu.com/p/c04619b37440
- https://blog.csdn.net/jjxojm/article/details/90349756
- https://www.jianshu.com/p/086fe09188ea