编译时注解学习一之 Element元素

前面的文章学习java基础之注解,掌握了注解的基本用法。使用系统或者大神写的框架库提供给我们注解,可以省略好多配置,特别是java Spring开发中注解更是多的眼花缭乱。最近需要用到编译时注解,所以就对AbstractProcessor进行深入的学习,首先对javax.lang.model.element进行学习。

Element 是一个接口,它只在编译期存在和Type有区别,表示程序的一个元素,可以是package,class,interface,method,成员变量,函数参数,泛型类型等。
它的子类包括ExecutableElement, PackageElement, Parameterizable, QualifiedNameable, TypeElement, TypeParameterElement, VariableElement。

Element的子类介绍:

  • ExecutableElement:表示类或者接口中的方法,构造函数或者初始化器。
  • PackageElement :表示包程序元素
  • TypeELement:表示一个类或者接口元素
  • TypeParameterElement:表示类,接口,方法的泛型类型例如T。
  • VariableElement:表示字段,枚举常量,方法或者构造函数参数,局部变量,资源变量或者异常参数。

Element只在编译期可见,通过Element可以获取什么信息呢,如何获取呢。下面是jdk中对Element的说明:
在这里插入图片描述
在这里插入图片描述
asType() 返回TypeMirror,TypeMirror是元素的类型信息,包括包名,类(或方法,或参数)名/类型。TypeMirror的子类有ArrayType, DeclaredType, DisjunctiveType, ErrorType, ExecutableType, NoType, NullType, PrimitiveType, ReferenceType, TypeVariable, WildcardType ,getKind可以获取类型。

equals(Object obj) 比较两个Element利用equals方法。

getAnnotation(Class annotationType) 传入注解可以获取该元素上的所有注解。

getAnnotationMirrors() 获该元素上的注解类型。

getEnclosedElements() 获取该元素上的直接子元素,类似一个类中有VariableElement。

getEnclosingElement() 获取该元素的父元素,如果是PackageElement则返回null,如果是TypeElement则返回PackageElement,如果是TypeParameterElement则返回泛型Element

getKind() 返回值为ElementKind,通过ElementKind可以知道是那种element,具体就是Element的那些子类。

getModifiers() 获取修饰该元素的访问修饰符,public,private。

getSimpleName() 获取元素名,不带包名,如果是变量,获取的就是变量名,如果是定义了int age,获取到的name就是age。如果是TypeElement返回的就是类名。

getQualifiedName():获取类的全限定名,Element没有这个方法它的子类有,例如TypeElement,得到的就是类的全类名(包名)。

获取所在的包名:
Elements.getPackageOf(enclosingElement).asType().toString()

编译时注解学习一之 Element元素
编译时注解学习二之 注解处理器初探AbstractProcessor
编译时注解学习三之 注解处理器AbstractProcessor工具和Element属性简述
编译期注解学习四 简单的view注入框架
编译期注解学习五 - ElementKind,TypeKind,不同Element类型判断
编译期注解学习六- 生成java文件javapoet
编译期注解学习七-如何进行调试
编译时注解学习八 -模板文件读取

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Java 中,注解是在编译处理的,因此要在编译修改属性上的注解内容,需要使用 Java 的 annotation processing 工具(APT)。 APT 是一种在编译扫描和处理 Java 注解的工具,它可以在编译期间生成新的 Java 代码,并将其编译成可执行的程序。APT 工具提供了许多 API,可以用来读取和修改源代码上的注解信息。 下面是一个简单的例子,演示如何在编译修改属性上的注解内容: ```java @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface MyAnnotation { String value(); } public class MyClass { @MyAnnotation("old value") private String myField; } public class MyProcessor extends AbstractProcessor { @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { for (Element element : roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) { if (element.getKind() == ElementKind.FIELD) { VariableElement variableElement = (VariableElement) element; MyAnnotation annotation = variableElement.getAnnotation(MyAnnotation.class); String newValue = "new value"; MyAnnotation newAnnotation = new MyAnnotation() { @Override public String value() { return newValue; } @Override public Class<? extends Annotation> annotationType() { return MyAnnotation.class; } }; AnnotatedTypeMirror.AnnotatedDeclaredType fieldType = (AnnotatedTypeMirror.AnnotatedDeclaredType) variableElement.asType(); AnnotatedTypeMirror.AnnotatedDeclaredType annotatedFieldType = fieldType.replaceAnnotation(newAnnotation); variableElement.getEnclosingElement().getEnclosedElements().remove(variableElement); FieldSpec.Builder fieldBuilder = FieldSpec.builder(TypeName.get(annotatedFieldType.getUnderlyingType()), variableElement.getSimpleName().toString()); variableElement.getModifiers().forEach(modifier -> fieldBuilder.addModifiers(modifier)); fieldBuilder.addAnnotation(annotatedFieldType.getAnnotations().stream().map(AnnotationSpec::get).collect(Collectors.toList())); fieldBuilder.initializer("null"); FieldSpec fieldSpec = fieldBuilder.build(); JavaFile.builder(annotatedFieldType.getUnderlyingType().toString().replace('.', '/').replace('$', '/') + "Generated", fieldSpec) .build() .writeTo(processingEnv.getFiler()); } } return true; } } ``` 在这个例子中,`MyAnnotation` 是一个自定义的注解,`MyClass` 是一个包含注解属性的类。`MyProcessor` 是一个 APT 处理器,它会在编译扫描和处理带有 `@MyAnnotation` 注解元素。在 `process` 方法中,我们使用 `roundEnv.getElementsAnnotatedWith` 方法获取所有带有 `@MyAnnotation` 注解元素,然后判断元素类型是否为字段。如果是字段,我们就可以使用 `variableElement.getAnnotation` 方法获取字段上的注解对象,然后构造一个新的注解对象并使用 `replaceAnnotation` 方法替换原有的注解对象。最后,我们可以使用 `JavaFile.builder` 方法创建一个新的 Java 文件,并将修改后的字段写入该文件中。 需要注意的是,APT 处理器需要在编译自动运行,可以通过在 `build.gradle` 文件中配置以下内容来实现: ```groovy dependencies { compileOnly 'com.google.auto.service:auto-service:1.0-rc7' annotationProcessor 'your.package.MyProcessor' } sourceSets { main { java { srcDirs 'src/main/java', 'build/generated/source/apt/main' } } } compileJava.options.annotationProcessorPath = configurations.compileClasspath ``` 这个例子只是一个简单的示例,实际使用中可能需要更复杂的处理逻辑。但是,这个例子可以帮助你了解在编译修改注解内容的基本原理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值