日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務,提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

什么是APT

APT(Annotation Processing Tool)它是JAVA編譯期注解處理器,它可以讓開發(fā)人員在編譯期對注解進行處理,通過APT可以獲取到注解和被注解對象的相關信息,并根據(jù)這些信息在編譯期按我們的需求生成java代碼模板或者配置文件(比如SPI文件或者spring.fatories)等。APT獲取注解及生成代碼都是在代碼編譯時候完成的,相比反射在運行時處理注解大大提高了程序性能

APT的工作流程

 

什么是注解

:因為APT = 注解+ 注解處理器(AbstractProcessor)。因此需要了解什么是注解,不過對于java開發(fā)人員來說,注解應該是耳熟能詳了,這邊就不再論述。如果不了解啥是注解的小伙伴,可以查看如下文章科普一下

https://baike.baidu.com/item/%E6%B3%A8%E8%A7%A3/22344968

這邊得特別說下元注解@Retention

 

因為APT是在java編譯器使用,因此@Retention的value通常指定為source或者class,這樣可以提高一點性能。就我個人而言,我傾向指定為source

APT之Element常用元素以及Element元素常用變量

1、常用元素

 

這些元素映射到java,我通過一個例子大家應該就可以了解這些元素是指什么

 

2、Element元素常用變量

更多element詳細內(nèi)容可以查看如下鏈接

https://www.jianshu.com/p/899063e8452e

創(chuàng)建注解處理器步驟

  • 創(chuàng)建注解類
  • 創(chuàng)建一個繼承自 AbstractProcessor 的類,這就是 APT 的核心類
  • 注冊處理器

創(chuàng)建注解處理器示例

注: 示例要實現(xiàn)的功能,通過一個自定義注解AutoComponent,通過注解處理器掃描解析AutoComponent注解,并生成lybgeek.components,spring通過解析lybgeek.components,實現(xiàn)bean注冊

1、創(chuàng)建注解類

@Documented
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface AutoComponent {

}

2、創(chuàng)建一個繼承自 AbstractProcessor 的類

這邊需介紹這個類里面幾個核心的方法

 public synchronized void init(ProcessingEnvironment processingEnv)

init方法可以讓我們處理器的初始化階段,通過ProcessingEnvironment來獲取一些幫助我們來處理注解的工具類

// Element操作類,用來處理Element的工具
Elements elementUtils = processingEnv.getElementUtils();

// 類信息工具類,用來處理TypeMirror的工具
Types typeUtils = processingEnv.getTypeUtils();

// 日志工具類,因為在process()中不能拋出一個異常,那會使運行注解處理器的JVM崩潰。所以Messager提供給注解處理器一個報告錯誤、警告以及提示信息的途徑,用來寫一些信息給使用此注解器的第三方開發(fā)者看
Messager messager = processingEnv.getMessager();

// 文件工具類,常用來讀取或者寫資源文件
Filer filer = environment.getFiler();

public Set<String> getSupportedAnnotationTypes()


getSupportedAnnotationTypes方法用來指定需要處理的注解集合,返回的集合元素需要是注解全路徑(包名+類名)

public SourceVersion getSupportedSourceVersion()

getSupportedSourceVersion方法用來指定當前正在使用的Java版本,一般返回
SourceVersion.latestSupported()表示最新的java版本即可

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

process是注解處理器核心方法,注解的處理和生成代碼或者配置資源都是在這個方法中完成。

Java官方文檔給出的注解處理過程的定義:注解處理過程是一個有序的循環(huán)過程。在每次循環(huán)中,一個處理器可能被要求去處理那些在上一次循環(huán)中產(chǎn)生的源文件和類文件中的注解。

每次循環(huán)都會調(diào)用process方法,process方法提供了兩個參數(shù),第一個是我們請求處理注解類型的集合(也就是我們通過重寫
getSupportedAnnotationTypes方法所指定的注解類型),第二個是有關當前和上一次循環(huán)的信息的環(huán)境。返回值表示這些注解是否由此 Processor 聲明,如果返回 true,則這些注解已聲明并且不要求后續(xù) Processor 處理它們;如果返回 false,則這些注解未聲明并且可能要求后續(xù) Processor 處理它們。

核心方法介紹完后,我們通過示例來自定義一個注解處理器

@AutoService(Processor.class)
@SupportedOptions("debug")
public class AutoComponentProcessor extends AbstractComponentProcessor {
    
    /**
     * 元素輔助類
     */
    private Elements elementUtils;

    private Set<String> componentClassNames = new ConcurrentSkipListSet<>();

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        elementUtils = processingEnv.getElementUtils();
    }


    @Override
    public Set<String> getSupportedAnnotationTypes() {
        return Collections.singleton(AutoComponent.class.getName());
    }


    @Override
    protected boolean processImpl(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
       // 注解處理完成,創(chuàng)建配置文件
        if (roundEnv.processingOver()) {
            generateConfigFiles();
        } else {
            processAnnotations(annotations, roundEnv);
        }
        return false;
    }

3、注冊處理器

因為處理器是通過SPI機制實現(xiàn),因此它的注冊,其實就是在META-INF/services底下創(chuàng)建
javax.annotation.processing.Processor文件,文件內(nèi)容為自定義的處理器類

com.Github.lybgeek.apt.process.AutoComponentProcessor

不過我們可以在項目的POM中引入GAV

 <dependency>
            <groupId>com.google.auto.service</groupId>
            <artifactId>auto-service</artifactId>
            <version>1.0.1</version>
            <scope>provided</scope>
        </dependency>

或者

<dependency>
            <groupId>.NET.dreamlu</groupId>
            <artifactId>mica-auto</artifactId>
            <version>2.3.0</version>
            <scope>provided</scope>
        </dependency>

在process的處理器上,加上注解

@AutoService(Processor.class)

就會在編譯期自動生成spi配置文件,它實現(xiàn)機制也是采用APT

4、當我們制作好處理器后,我們可以將處理器打成jar,提供給項目用

示例

<dependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>springboot-apt-framework</artifactId>
            <version>${project.version}</version>
        </dependency>

在項目編譯后,就會在target的MATA-INF底下看到lybgeek.components文件

 

文件內(nèi)容如下

# Generated by LYB-GEEK AT TIME : 2023-01-12T17:14:24.982
com.github.lybgeek.test.service.EchoService
com.github.lybgeek.test.service.HelloService

接下來就是解析lybgeek.components,并通過spring提供的擴展點和API進行bean注冊,因為這塊內(nèi)容不屬于APT的內(nèi)容,本文就不再論述,對這部分感興趣的朋友,可以通過文末提供的demo鏈接查看

總結(jié)

在未接觸APT之前,我們可能會通過反射去解析注解并實現(xiàn)功能,接觸APT之后,我們又多了額外一種比反射更能提升性能的實現(xiàn)實現(xiàn)。不過任何東西都有其適用場景,APT主要還是用在編譯期幫我們生成代碼或者配置等,如果我們項目要使用APT生成的代碼,有可能還是需要通過反射處理。

我們耳熟能詳?shù)膌ombok、mapstruct、包括spring5.0之后提供的@Index都是通過APT來實現(xiàn),文中的示例其實就是仿造spring index來實現(xiàn),可以看成是spring index的簡單版本

demo鏈接

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-apt

分享到:
標簽:JAVA
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定