java retentionpolicy_Java注解之如何利用RetentionPolicy.SOURCE生存周期
上一篇文章简单讲了下Java注解的学习之元注解说明,学习了Java注解是如何定义的,怎么使用的,但是并没有介绍Java的注解是怎么起作用的,像Spring Boot里面的那些注解,到底是怎么让程序这样子运行起来的?特别是讲到RetentionPolicy这一块,到底在SOURCE阶段,在CLASS阶段,在RUNTIME阶段有什么差别,注解是如何在这三个阶段起作用的呢?而且,在SOURCE阶段,在CLASS阶段,程序又不运行,那注解到底会用来做些什么呢?
带着这些疑问,我就去了解下了如何让注解起作用,发现RUNTIME阶段的介绍到处都是,但是SOURCE和CLASS阶段就很少文章讲解到了,真的得搜刮好几十篇文章才能成功的把程序跑起来,几乎每一篇文章都少讲了些东西。
本文优先讲的是SOURCE阶段注解如何发挥作用,发现这一块涉及的知识非常多且难,资料还少,另外还发现,Java服务器端编程的人用这个反而不如Android开发的人用得多。对我学习SOURCE阶段的注解帮助最大的是Pluggable Annotation Processing API,JSR269插件化注解API以及JVM进阶 -- 浅谈注解处理器。搜索这方面的资料用“插件化注解处理API”这个关键词能搜得更全。
这几篇文章基本上把SOURCE阶段的注解实现和使用讲了,但是具体细节,比如用javac直接编译运行代码,javac使用jar包,使用maven等三个方式如何运行注解处理器,倒是基本上蜻蜓点水,摸索了我好久才搞定了。关于注解处理器的知识,可以从如上三篇文章了解,本文主要讲注解的定义和运行。
我用的代码是摘抄至 JVM进阶 -- 浅谈注解处理器 ,它定义了一个CheckGetter的注解,用来检查一个类里面的字段,哪个没有Getter方法,没有的话编译就报错。不过我的和他的稍稍不同,他的代码定义没有放到package里面,我的放到package里面了,这样子的使用和执行又有了点不同。
首先,定义CheckGetter注解:
package com.shahuwang.processor;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.SOURCE)
public @interface CheckGetter {
}
注意上面的代码,是放到 package com.shahuwang.processor 里面的,因此,先创建如下结构的文件夹
Processor
—— com
—— shuhuwang
—— processor
—— CheckGetter.java
注解已经定义好了,现在先来用一下这个注解:
package com.shahuwang.processor;
@CheckGetter
public class TestGetter {
String name;
String first;
public String getName(){
return this.name;
}
}
这个类有两个字段,但是有一个字段没有设置getter。
下面才是真正重要的代码,就是让CheckGetter这个注解真正能运行起来,发挥作用:
package com.shahuwang.processor;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.ElementFilter;
import javax.tools.Diagnostic;
import javax.lang.model.element.Element;
import java.util.Set;
// 这个地方换了包名就需要改过来,否则processor就不会执行了, 这里是最需要注意的地方,千万注意!!!!!
@SupportedAnnotationTypes("com.shahuwang.processor.CheckGetter")
@SupportedSourceVersion(SourceVersion.RELEASE_11)
public class CheckGetterProcessor extends AbstractProcessor {
@Override
public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (TypeElement annotatedClass : ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(CheckGetter.class))) {
for (VariableElement field : ElementFilter.fieldsIn(annotatedClass.getEnclosedElements())) {
if(!containsGetter(annotatedClass, field.getSimpleName().toString())){
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
String.format("getter not found for '%s.%s'.", annotatedClass.getSimpleName(), field.getSimpleName()));
}
}
}
return false;
}
private static boolean containsGetter(TypeElement typeElement, String name){
String getter = "get" + name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
for(ExecutableElement executableElement: ElementFilter.methodsIn(typeElement.getEnclosedElements())){
if(!executableElement.getModifiers().contains(Modifier.STATIC) &&
executableElement.getSimpleName().toString().equals(getter) &&
executableElement.getParameters().isEmpty()){
return true;
}
}
return false;
}
}
上面这段代码要理解的概念有点儿多,实际上我现在也不是很懂,但是本文的目标是先让注解处理器跑起来,所以先不管。这里最重要也是折磨我最惨的地方,就是这一句@SupportedAnnotationTypes("com.shahuwang.processor.CheckGetter"),你定义的注解在哪个package下,这里就要写完整了,如果写错了,注解处理器就不起作用了。
现在在Processor目录下,打开命令行,先编译CheckGetterProcessor.java: javac com/shahuwang/processor/CheckGetterProcessor.java,编译好之后就可以使用了,再执行命令:javac -processor com.shahuwang.processor.CheckGetterProcessor com/shahuwang/processor/TestGetter.java,便可以看到这样的提示:
错误: getter not found for 'TestGetter.first'.
上面这种方式,需要每次执行编译的时候,指定一下processor才能做到检查作用,那如果在团队开发中,希望自动执行一些检查,那可以用SPI 服务提供者发现机制或者maven来实现。
SPI 服务提供者发现机制就是配置META-INF文件夹和里面的文件,告诉Java你要执行某个东西,这个东西的路径在哪里。再把编译好的processor和META-INF打包成jar包,就可以很方便使用了。文件夹和文件结构如下:
processor
-com
-shahuwang
- processor
- CheckGetterProcessor.class
-META-INF
-services
- javax.annotation.processing.Processor
编译方式和上述一样。
javax.annotation.processing.Processor是一个普通的文本,就是告知java一些关于注解处理器的配置,里面的内容如下:
com.shahuwang.processor.CheckGetterProcessor
就是告知这个注解处理器要用哪些个,如果有多个的话,可以一行一个。
然后在processor目录下,执行指令:jar -cvf processor.jar com META-INF, 形成了一个 processor.jar 的包,此时可以执行指令:
javac -cp processor.jar com/shahuwang/processor/TestGetter.java
就会自动执行注解处理器检查字段有没有getter方法了。
jar包的这个方法,其实是把注解和注解的实现单独放一块作为一个插件来使用了,maven也是如此的。
现实的开发中,还是用maven最多,先用指令创建一个maven项目:mvn archetype:generate -DgroupId=com.shahuwang -DartifactId=Processor -Dpackage=com.shahuwang.processor
然后在pom.xml的层级下添加如下配置:
UTF-8
UTF-8
1.8
1.8
1.8
org.apache.maven.plugins
maven-compiler-plugin
3.5.1
1.8
1.8
UTF-8
com.shahuwang.processor.CheckGetterProcessor
代码目录结构如下:
Processor
- src
- main
- java
-com
-shahuwang
-processor
-CheckGetter.java
-CheckGetterProcessor.java
- pom.xml
然后Processor目录下执行: mvn clean install, 这个项目就会被安装到本地的maven库里面。
再用maven新建一个TestProcessor项目,项目结构如下:
TestProcessor
- src
- main
- java
-com
-shahuwang
-TestGetter.java
- pom.xml
TestGetter.java 的代码上面有。
修改pom.xml, 先在 下添加:
UTF-8
UTF-8
1.8
1.8
1.8
org.apache.maven.plugins
maven-compiler-plugin
3.5.1
1.8
1.8
UTF-8
com.shahuwang.processor.CheckGetterProcessor
再在dependencies添加:
com.shahuwang
Processor
1.0-SNAPSHOT
也就是引入上面编译好的处理器的包。
现在,在TestProcessor目录下执行:
mvn compile
就会看到熟悉的提示:
错误: getter not found for 'TestGetter.first'.
三种主流的注解处理器使用方式现在都搞懂怎么使用了。下一篇文章将会关注注解处理器的使用方法,各个注解处理器API的使用
java retentionpolicy_Java注解之如何利用RetentionPolicy.SOURCE生存周期相关推荐
- Java 基础 —— 注解
注解(annotation)不是注释(comment): 注解,是一种元数据(metadata),可为我们在代码中添加信息提供了一种形式化的方法.注解在一定程度上实现了元数据和源代码文件的结合,而不是 ...
- Java自定义注解Annotation的实现原理
文章目录 1.什么是注解? 2.注解的用处: 3.注解的原理: 4.元注解: 5.常见标准的Annotation: 6.自定义注解: 7.自定义注解实例: 1.什么是注解? 对于很多初次接触的开发 ...
- Java Annotation(注解)使用教程
Java Annotation(注解)使用教程 1 什么是注解 2 注解的使用语法 2.1 内置注解介绍以及使用 @Override @Deprecated @SuppressWarnings @Sa ...
- java 枚举 注解_Java枚举类和注解梳理
1. 枚举类 1. 枚举类的使用 枚举类的理解:类的对象只有有限个,确定的.我们称此类为枚举类. 当需要定义一组常量时,强烈建议使用枚举类. 如果枚举类中只有一个对象,则可以作为单例模式的实现方式. ...
- java自定义注解详解
一: 注解的概念 1.1 注解的官方定义 首先看看官方对注解的描述: An annotation is a form of metadata, that can be added to Java so ...
- java 封装优化工具_利用Java注解的简单封装的一次优化
悟红尘:zhuanlan.zhihu.com 在我们的项目中和后台的通信的时候,为了防止别人截获并篡改信息,于是决定启用一套自己验签规则,那就是将所有属性的值拼接起来进行SHA256签名,在这个字符 ...
- Java注解的Retention和RetentionPolicy
一 源码赏析 1 源码 @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) pub ...
- java中注解的使用_java中注解的使用
使用过ssh框架的人一定也使用过注解,尤其是在spring框架中,注解可谓是spring容器和AOP编程的重要环节.注解就是用于修饰类.全局变量.方法.参数或局部变量的接口,java中规定,注解的使用 ...
- java自定义注解为空值_java自定义注解
1. Java注解(Annotation) Java注解是附加在代码中的一些元信息,用于一些工具在编译. 运行时进行解析和使用,起到说明.配置的功能. 注解相关类都包含在java.lang.annot ...
最新文章
- CSS3无前缀脚本prefixfree.js与Animatable使用
- SAP几则常用的BASIS技巧整理
- 电脑开机3秒就重启循环_移动办公神器!电脑包秒变支架、鼠标垫,3合1设计超方便!...
- BCrypt加密怎么存入数据库_第6天 密码加密与微服务鉴权JWT(下)
- 前端学习(2787):完成推荐商品结构之商品栏样式书写
- 推荐一个配置linux服务的网站
- Top-down与Bottom-up
- 动态改变类名_反调试之检测类名与标题名
- shell条件检查原理:command echo ‘success‘ || echo ‘error‘
- 数据分析能不能替代Data Mining?
- 45.Linux/Unix 系统编程手册(下) -- System V IPC 介绍
- vim python一键执行、高亮等一键安装
- txt 文本文档中空格替换
- java8的Effectively final
- 项目经理的工作就是胡搅蛮缠满地打滚
- VBA程序升级,vba在线更新
- 2020年千兆路由器推荐 数码宅男来带路 赶紧M
- 鸿蒙事业单位专业技术,事业单位专业技术岗考什么?
- 盘点NBA历史上最强球员前十排行榜:沙奎尔·奥尼尔
- 2021城阳一中高考成绩查询,城阳一中2017届高考录取喜报
热门文章
- R语言赋值操作符:<−、<<-、=、->、->>、:、%in%、%*%
- 对于图像分类任务,相对于全连接的DNN,CNN模型的主要优点有哪些?
- 傅里叶(FFT)+小波变换+数据压缩
- java中getDelta是什么意思_Java IResourceDelta.getMarkerDeltas方法代码示例
- 生物信息学常见数据格式 • fasta • fastq • gff/gtf
- ubuntu18.04.4 没有声音
- lnmp架构——架构理解
- c++ 按键暂停继续 程序_CNC操作面板讲解,看看这些按键是什么意思
- 我的世界java版背景图更换_《我的世界手机版》如何修改界面背景 界面背景修改攻略图文教程...
- java pkcs1转pkcs8_.NET Core RSA密钥的xml、pkcs1、pkcs8格式转换和JavaScript、Java等语言进行对接...