最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java冷知識:javac AbstractProcessor詳解

 更新時間:2021年11月09日 09:34:21   作者:布道  
這篇文章主要介紹了java冷知識:javac AbstractProcessor詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

它可以做什么?

它做的事情當然是生成新類或修改原始的類,比如你遇到這樣的情況下就可以使用:

  • 反射好慢,曾見過一個大廠大量是Gson,由于Gson序列化時大量使用了反射,每一個field,每一個get、set都需要用反射,由此帶來了性能問題。解決方法就是使用它盡量減少反射(替換成JSONObject)
  • 生成代碼,只要是有注解的地方都可以讀取,總之很多(有些android orm框架)

Processor

javax.annotation.processing.Processor 這個接口將提供注解處理,它遵循SPI規(guī)約進行拓展,jdk默認就有很多處理器的實現(xiàn)。

AbstractProcessor

注解處理器是最重要的拓展處理類了。

注意:請確認JAVA的環(huán)境變量已經配置成功,并且把tools.jar(它源于此包)加入到自己電腦的環(huán)境變量中

ProcessingEnvironment 是一個注解處理工具的集合
Element 是一個接口,表示一個程序元素,它可以是包、類、方法或者一個變量。Element已知的子接口有:

PackageElement 表示一個包程序元素。提供對有關包及其成員的信息的訪問。
ExecutableElement 表示某個類或接口的方法、構造方法或初始化程序(靜態(tài)或實例),包括注釋類型元素。
TypeElement 表示一個類或接口程序元素。提供對有關類型及其成員的信息的訪問。注意,枚舉類型是一種類,而注解類型是一種接口。
VariableElement 表示一個字段、enum 常量、方法或構造方法參數(shù)、局部變量或異常參數(shù)。

源碼

重點關注process方法

// 源于javax.annotation.processing;
public abstract class AbstractProcessor implements Processor {
    // 集合中指定支持的注解類型的名稱(這里必須時完整的包名+類名)
    public Set<String> getSupportedAnnotationTypes() {
            SupportedAnnotationTypes sat = this.getClass().getAnnotation(SupportedAnnotationTypes.class);
            if  (sat == null) {
                if (isInitialized())
                    processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
                                                             "No SupportedAnnotationTypes annotation " +
                                                             "found on " + this.getClass().getName() +
                                                             ", returning an empty set.");
                return Collections.emptySet();
            }
            else
                return arrayToSet(sat.value());
        }
    // 指定當前正在使用的Java版本
    public SourceVersion getSupportedSourceVersion() {
        SupportedSourceVersion ssv = this.getClass().getAnnotation(SupportedSourceVersion.class);
        SourceVersion sv = null;
        if (ssv == null) {
            sv = SourceVersion.RELEASE_6;
            if (isInitialized())
                processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
                                                         "No SupportedSourceVersion annotation " +
                                                         "found on " + this.getClass().getName() +
                                                         ", returning " + sv + ".");
        } else
            sv = ssv.value();
        return sv;
    }
    // 初始化處理器
    public synchronized void init(ProcessingEnvironment processingEnv) {
        if (initialized)
            throw new IllegalStateException("Cannot call init more than once.");
        Objects.requireNonNull(processingEnv, "Tool provided null ProcessingEnvironment");
 
        this.processingEnv = processingEnv;
        initialized = true;
    }
    /**
     * 這些注解是否由此 Processor 處理,該方法返回ture表示該注解已經被處理, 后續(xù)不會再有其他處理器處理; 返回false表示仍可被其他處理器處理
     */
    public abstract boolean process(Set<? extends TypeElement> annotations,
                                    RoundEnvironment roundEnv);
}

實現(xiàn)一個打印可以API的功能

由于本人是maven環(huán)境,以此展開講

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <!--Disable annotation processing for ourselves-->
                <!--<compilerArgument>-proc:none</compilerArgument>-->
            </configuration>
        </plugin>
    </plugins>
</build>

步驟1:實現(xiàn)一個注解處理器

@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface ApiAnnotation {
    String author() default "alex.chen";
    String date();
    int version() default 1;
}
@SupportedAnnotationTypes({"com.kxtx.annotation.ApiAnnotation"})
@SupportedSourceVersion(SourceVersion.RELEASE_8)
//@AutoService(Processor.class)
public class MyProcessor extends AbstractProcessor {
    //類名的前綴、后綴
    public static final String SUFFIX = "AutoGenerate";
    public static final String PREFIX = "My_";
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
        Messager messager = processingEnv.getMessager();
        for (TypeElement typeElement : annotations) {
            for (Element e : env.getElementsAnnotatedWith(typeElement)) {
                //打印
                messager.printMessage(Diagnostic.Kind.WARNING, "Printing:" + e.toString());
                messager.printMessage(Diagnostic.Kind.WARNING, "Printing:" + e.getSimpleName());
                messager.printMessage(Diagnostic.Kind.WARNING, "Printing:" + e.getEnclosedElements().toString());
 
                //獲取注解
                ApiAnnotation annotation = e.getAnnotation(ApiAnnotation.class);
                //獲取元素名并將其首字母大寫
                String name = e.getSimpleName().toString();
                char c = Character.toUpperCase(name.charAt(0));
                name = String.valueOf(c + name.substring(1));
                //包裹注解元素的元素, 也就是其父元素, 比如注解了成員變量或者成員函數(shù), 其上層就是該類
                Element enclosingElement = e.getEnclosingElement();
                //獲取父元素的全類名,用來生成報名
                String enclosingQualifiedname;
                if (enclosingElement instanceof PackageElement) {
                    enclosingQualifiedname = ((PackageElement) enclosingElement).getQualifiedName().toString();
                } else {
                    enclosingQualifiedname = ((TypeElement) enclosingElement).getQualifiedName().toString();
                }
                try {
                    //生成包名
                    String generatePackageName = enclosingQualifiedname.substring(0, enclosingQualifiedname.lastIndexOf("."));
                    // 生成的類名
                    String genarateClassName = PREFIX + enclosingElement.getSimpleName() + SUFFIX;
                    //創(chuàng)建Java 文件
                    JavaFileObject f = processingEnv.getFiler().createSourceFile(genarateClassName);
                    // 在控制臺輸出文件路徑
                    messager.printMessage(Diagnostic.Kind.WARNING, "Printing: " + f.toUri());
                    Writer w = f.openWriter();
                    try {
                        PrintWriter pw = new PrintWriter(w);
                        pw.println("package " + generatePackageName + ";");
                        pw.println("\npublic class " + genarateClassName + " { ");
                        pw.println("\n    /** 打印值 */");
                        pw.println("    public static void print" + name + "() {");
                        pw.println("        // 注解的父元素: " + enclosingElement.toString());
                        pw.println("        System.out.println(\"代碼生成的路徑: " + f.toUri() + "\");");
                        pw.println("        System.out.println(\"注解的元素: " + e.toString() + "\");");
                        pw.println("        System.out.println(\"注解的版本: " + annotation.version() + "\");");
                        pw.println("        System.out.println(\"注解的作者: " + annotation.author() + "\");");
                        pw.println("        System.out.println(\"注解的日期: " + annotation.date() + "\");");
 
                        pw.println("    }");
                        pw.println("}");
                        pw.flush();
                    } finally {
                        w.close();
                    }
                } catch (IOException e1) {
                    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
                            e1.toString());
                }
            }
        }
        return true;
    }
}

步驟2:配置一個spi,在resources目錄新建META-INF/services/javax.annotation.processing.Processor,內容為MyProcessor類全名。

步驟3:在另一個項目中使用@ApiAnnotation就會發(fā)現(xiàn)生成了一個新My_feignAutoGenerate.class文件:

public class My_feignAutoGenerate {
    public My_feignAutoGenerate() {
    }
    public static void printStartUp() {
        System.out.println("代碼生成的路徑: file:/C:/Users/Administrator/Desktop/feign-async-master/target/generated-sources/annotations/My_feignAutoGenerate.java");
        System.out.println("注解的元素: com.github.feign.StartUp");
        System.out.println("注解的版本: 1");
        System.out.println("注解的作者: alex");
        System.out.println("注解的日期: 2019-03-6");
    }
}

到這里基本上已經演示完了。

google的 auto-service

<dependency>
    <groupId>com.google.auto.service</groupId>
    <artifactId>auto-service</artifactId>
    <version>1.0-rc2</version>
</dependency>

這個類庫非常有用,它非常簡單,使用@AutoService(Processor.class)會基于該接口和注解的類上自動幫我們生成META-INF/services下對應spi文件。它實現(xiàn)的原理就是通過注解處理器。

javapoet

有沒有覺得上面pw.println("package " + generatePackageName + ";");這樣的代碼很痛苦啊?

JavaPoet is a Java API for generating .java source files.

package com.example.helloworld; 
public final class HelloWorld {
  public static void main(String[] args) {
    System.out.println("Hello, JavaPoet!");
  }
}
MethodSpec main = MethodSpec.methodBuilder("main")
    .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
    .returns(void.class)
    .addParameter(String[].class, "args")
    .addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!")
    .build();
 
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
    .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
    .addMethod(main)
    .build();
 
JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)
    .build();
 
javaFile.writeTo(System.out);

你喜歡的lombok實現(xiàn)原理是怎樣的呢?

lombok(用來幫助開發(fā)人員消除 Java 對象 的冗長),非常好用

里面源碼就不再介紹了??!

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • SpringMvc3+extjs4實現(xiàn)上傳與下載功能

    SpringMvc3+extjs4實現(xiàn)上傳與下載功能

    這篇文章主要為大家詳細介紹了SpringMvc3+extjs4實現(xiàn)上傳與下載功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • java如何將實體類轉換成json并在控制臺輸出

    java如何將實體類轉換成json并在控制臺輸出

    這篇文章主要介紹了java如何將實體類轉換成json并在控制臺輸出問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • java 使用poi 導入Excel數(shù)據(jù)到數(shù)據(jù)庫的步驟

    java 使用poi 導入Excel數(shù)據(jù)到數(shù)據(jù)庫的步驟

    這篇文章主要介紹了java 使用poi 導入Excel 數(shù)據(jù)到數(shù)據(jù)庫的步驟,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-12-12
  • Java實題演練二叉搜索樹與雙向鏈表分析

    Java實題演練二叉搜索樹與雙向鏈表分析

    這篇文章主要介紹了Java二叉搜索樹與雙向鏈表,總的來說這并不是一道難題,那為什么要拿出這道題介紹?拿出這道題真正想要傳達的是解題的思路,以及不斷優(yōu)化探尋最優(yōu)解的過程。希望通過這道題能給你帶來一種解題優(yōu)化的思路
    2022-12-12
  • java-SSH2實現(xiàn)數(shù)據(jù)庫和界面的分頁

    java-SSH2實現(xiàn)數(shù)據(jù)庫和界面的分頁

    本文主要是介紹SSH2實現(xiàn)數(shù)據(jù)庫和界面的分頁的代碼,分頁在web應用中是經常要做的事情,實用性比較大,有需要的朋友可以來了解一下。
    2016-10-10
  • IDEA添加Java類注釋模版的方法

    IDEA添加Java類注釋模版的方法

    本篇文章主要介紹了IDEA添加Java類注釋模版的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12
  • Java LocalCache 本地緩存的實現(xiàn)實例

    Java LocalCache 本地緩存的實現(xiàn)實例

    本篇文章主要介紹了Java LocalCache 本地緩存的實現(xiàn)實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-05-05
  • Java并發(fā)線程之線程池的知識總結

    Java并發(fā)線程之線程池的知識總結

    這篇文章主要介紹了Java并發(fā)線程之線程池的知識總結,幫助大家更好的理解和學習Java并發(fā)線程的相關內容,感興趣的朋友可以了解下
    2021-01-01
  • 基于Rest的API解決方案(jersey與swagger集成)

    基于Rest的API解決方案(jersey與swagger集成)

    下面小編就為大家?guī)硪黄赗est的API解決方案(jersey與swagger集成)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • 快速排序和分治排序介紹

    快速排序和分治排序介紹

    這篇文章主要介紹了快速排序和分治排序,需要的朋友可以參考下
    2015-04-04

最新評論

扎赉特旗| 张家口市| 定远县| 辽中县| 怀安县| 盐津县| 永康市| 富川| 东乡族自治县| 改则县| 济阳县| 崇明县| 沙田区| 浦江县| 兰考县| 阿拉善盟| 莒南县| 临江市| 镇平县| 威远县| 巴里| 台州市| 长泰县| 仪陇县| 临桂县| 万荣县| 海丰县| 理塘县| 峨眉山市| 屯门区| 正宁县| 宁安市| 集安市| 湖州市| 阿巴嘎旗| 乌拉特中旗| 肥西县| 中阳县| 毕节市| 苗栗市| 牟定县|