Java中的APT的工做過程

Java中的APT的工做過程

APT即Annotatino Processing Tool, 他的做用是處理代碼中的註解, 用來生成代碼, 換句話說, 這是用代碼生成代碼的工具, 減小boilerplate代碼.html

咱們經過一個簡單的例子來簡單APT的工做過程, 由於本文demo不設計ide及gradle等, 請注意包名及import問題.java

根據上一篇博客Java中的自定義註解, 首先設計一個自定義註解MyAnnotation.ide

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<String> getSupportedAnnotationTypes() {
        // 在此處聲明該processor支持的註解類型
        Set<String> 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的內容:gradle

com.example.MyProcessor

最終jar包的結構:設計

mp.jar // jar包名字隨意起
    com
        example
            MyProcess.class
            MyAnnotation.class
    META-INF
        services
            javax.annotation.processing.Processor
        MANIFEST.MF

測試

測試的例子很簡單:code

@MyAnnotation
public class Sample {
    public static void main(String[] args) {
        System.out.printf("Hello, World!");
    }
}

咱們用javac編譯這個文件htm

$ javac -cp mp.jar Sample.java
MyProcessor init
process
process

能夠看到, 咱們的Process已經生成了, 可是process過程輸出了兩次, 緣由能夠參考下圖:blog

process的過程會進行兩邊, 咱們代碼生成的過程應該在第一遍, 由於第二次processor的過程應當負責作一些清理的工做, 某些打包工具可能不會編譯在第二階段生成的.java源文件.

if (!roundEnv.processingOver()) { ... }
相關文章
相關標籤/搜索