注解(3):插件化注解处理API(Pluggable Annotation Processing API)

    插件化注解处理(Pluggable Annotation Processing)APIJSR 269提供一套标准API来处理AnnotationsJSR 175,实际上JSR 269不仅仅用来处理Annotation,我觉得更强大的功能是它建立了Java 语言本身的一个模型,它把method、package、constructor、type、variable、enum、annotation等Java语言元素映射为Types和Elements,从而将Java语言的语义映射成为对象,我们可以在javax.lang.model包下面可以看到这些类。所以我们可以利用JSR 269提供的API来构建一个功能丰富的元编程(metaprogramming)环境。JSR 269用Annotation Processor在编译期间而不是运行期间处理Annotation, Annotation Processor相当于编译器的一个插件,所以称为插入式注解处理.如果Annotation Processor处理Annotation时(执行process方法)产生了新的Java代码,编译器会再调用一次Annotation Processor,如果第二次处理还有新代码产生,就会接着调用Annotation Processor,直到没有新代码产生为止。每执行一次process()方法被称为一个"round",这样整个Annotation processing过程可以看作是一个round的序列。JSR 269主要被设计成为针对Tools或者容器的API。这个特性虽然在JavaSE 6已经存在,但是很少人知道它的存在。

    Pluggable Annotation Processing API的核心是Annotation Processor即注解处理器,一般需要继承抽象类javax.annotation.processing.AbstractProcessor。注意,与运行时注解RetentionPolicy.RUNTIME不同,注解处理器只会处理编译期注解,也就是RetentionPolicy.SOURCE的注解类型,处理的阶段位于Java代码编译期间。

插件化注解处理API的使用步骤大概如下:

  1. 自定义一个Annotation Processor,需要继承javax.annotation.processing.AbstractProcessor,并覆写process方法。
  2. 自定义一个注解,注解的元注解需要指定@Retention(RetentionPolicy.SOURCE)
  3. 需要在声明的自定义Annotation Processor中使用javax.annotation.processing.SupportedAnnotationTypes指定在第2步创建的注解类型的名称(注意需要全类名,"包名.注解类型名称",否则会不生效)。
  4. 需要在声明的自定义Annotation Processor中使用javax.annotation.processing.SupportedSourceVersion指定编译版本。
  5. 可选操作,可以通在声明的自定义Annotation Processor中使用javax.annotation.processing.SupportedOptions指定编译参数。

    下面是一个自定义的注解:

package annotations;

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.SOURCE)
public @interface Test {

	String value();
}

定义一个注解处理器:

package annotations;

import java.util.Set;

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.TypeElement;

//指定该注解处理器可以解决的类型,需要完整的包名+类命
@SupportedAnnotationTypes("annotations.Test")
//指定编译的JDK版本
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class AnnotationProcessor extends AbstractProcessor {

	// 这里就是处理注解的process函数
	@Override
	public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
		System.out.println("Log in AnnotationProcessor.process");
		for (TypeElement typeElement : annotations) {
			System.out.println(typeElement);
		}
		System.out.println(roundEnv);
		return true;
	}
}

编写一个主类:

package annotations;

public class AnnotationTest {
	public static void main(String[] args) {
		test();
	}

	@Test("test1")
	public static void test() {

	}
}

可以通过下面几种方式指定指定Processor。

  • 直接使用编译参数指定,例如:javac -processor club.throwable.processor.AnnotationProcessor Main.java。
  • 通过服务注册指定,就是META-INF/services/javax.annotation.processing.Processor文件中添加club.throwable.processor.AnnotationProcessor。
  • 通过Maven的编译插件的配置指定如下:
<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
					<encoding>UTF-8</encoding>
					<annotationProcessors>
						<annotationProcessor>
							annotations.AnnotationProcessor
						</annotationProcessor>
					</annotationProcessors>
				</configuration>
			</plugin>
		</plugins>
	</build>

    最后,使用Maven命令compile进行编译。可见编译期间AnnotationProcessor生效了。

如果本文对您有很大的帮助,还请点赞关注一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

游王子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值