apt编译java_Java中的APT的工作过程

Java中的APT的工作过程

APT即Annotatino Processing Tool, 他的作用是处理代码中的注解, 用来生成代码, 换句话说, 这是用代码生成代码的工具, 减少boilerplate代码.

我们通过一个简单的例子来简单APT的工作过程, 因为本文demo不设计ide及gradle等, 请注意包名及import问题.

根据上一篇博客Java中的自定义注解, 首先设计一个自定义注解MyAnnotation.

package com.example;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Retention(RetentionPolicy.SOURCE) // 只保留到编译阶段

@Target(ElementType.TYPE) // 可用于类, 接口..

public @interface MyAnnotation {

}

下面来看一下我们的主角, Processor:

package com.example;

import javax.annotation.processing.AbstractProcessor;

import javax.annotation.processing.ProcessingEnvironment;

import javax.annotation.processing.RoundEnvironment;

import javax.lang.model.SourceVersion;

import javax.lang.model.element.TypeElement;

import java.util.HashSet;

import java.util.Set;

public class MyProcessor extends AbstractProcessor {

// Processor初始化回调

@Override

public synchronized void init(ProcessingEnvironment processingEnv) {

super.init(processingEnv);

System.out.println("MyProcessor init");

}

// processor处理过程的回调, 如果需要生成代码, 就在这个方法中写. 这个demo暂时不演示代码生成.

@Override

public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {

System.out.println("process");

return false;

}

@Override

public Set getSupportedAnnotationTypes() {

// 在此处声明该processor支持的注解类型

Set set = new HashSet<>();

set.add(MyAnnotation.class.getCanonicalName());

return set;

}

@Override

public SourceVersion getSupportedSourceVersion() {

return SourceVersion.latestSupported();

}

}

那么我们如何把这个apt注册给javac呢? 我们将项目以常规的模式打包, 但是在META-INF目录中加入一个services文件夹, 在其中创建一个名为javax.annotation.processing.Processor的文件, 以文本将processor的完整名字写进去, 如果有多个processor, 换行即可.

javax.annotation.processing.Processor的内容:

com.example.MyProcessor

最终jar包的结构:

mp.jar // jar包名字随意起

com

example

MyProcess.class

MyAnnotation.class

META-INF

services

javax.annotation.processing.Processor

MANIFEST.MF

测试

测试的例子很简单:

@MyAnnotation

public class Sample {

public static void main(String[] args) {

System.out.printf("Hello, World!");

}

}

我们用javac编译这个文件

$ javac -cp mp.jar Sample.java

MyProcessor init

process

process

可以看到, 我们的Process已经生成了, 但是process过程输出了两次, 原因可以参考下图:

a3b4a5e24b5c711ca4147a096992c7a6.png

process的过程会进行两边, 我们代码生成的过程应该在第一遍, 因为第二次processor的过程应当负责做一些清理的工作, 某些打包工具可能不会编译在第二阶段生成的.java源文件.

if (!roundEnv.processingOver()) { ... }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值