1. 程式人生 > >java註解與APT技術

java註解與APT技術

1,基本概念

什麼是註解?

註解(Annotation),也叫元資料。一種程式碼級別的說明。它是JDK1.5及以後版本引入的一個特性,與類、介面、列舉是在同一個層次。它可以宣告在包、類、欄位、方法、區域性變數、方法引數等的前面,用來對這些元素進行說明,註釋。

什麼是元註解?

簡單來說,就是註解的註解,元註解的作用就是負責註解其他註解。Java5.0定義了4個標準的meta-annotation型別,它們被用來提供對其它 annotation型別作說明:
 

[email protected],
[email protected],
[email protected]

,
4.[email protected]

下面我們看一下每個元註解的作用和相應分引數的使用說明。

  • @Target:
    該標識用於描述註解的使用範圍(即:被描述的註解可以用在什麼地方): packages、types(類、介面、列舉、Annotation型別)、型別成員(方法、構造方法、成員變數、列舉值)、方法引數和本地變數(如迴圈變數、catch引數)。在Annotation型別的宣告中使用了target可更加明晰其修飾的目標。

取值(ElementType)有:
  1.CONSTRUCTOR:用於描述構造器
  2.FIELD:用於描述域
  3.LOCAL_VARIABLE:用於描述區域性變數
  4.METHOD:用於描述方法
  5.PACKAGE:用於描述包
  6.PARAMETER:用於描述引數
  7.TYPE:用於描述類、介面(包括註解型別) 或enum宣告

  • @Retention:
    該標示定義了該Annotation被保留的時間長短:某些Annotation僅出現在原始碼中,而被編譯器丟棄;而另一些卻被編譯在class檔案中;編譯在class檔案中的Annotation可能會被虛擬機器忽略,而另一些在class被裝載時將被讀取(請注意並不影響class的執行,因為Annotation與class在使用上是被分離的)。

取值(ElementType)有:
  1.SOURCE:在原始檔中有效(即原始檔保留)
  2.CLASS:在class檔案中有效(即class保留)
  3.RUNTIME:在執行時有效(即執行時保留)

  • @Documented:
    Documented用於描述其它型別的annotation應該被作為被標註的程式成員的公共API,因此可以被例如javadoc此類的工具文件化。Documented是一個標記註解,沒有成員

  • @Inherited:
    @Inherited 元註解是一個標記註解,@Inherited闡述了某個被標註的型別是被繼承的。如果一個使用了@Inherited修飾的annotation型別被用於一個class,則這個annotation將被用於該class的子類。

      注意:@Inherited annotation型別是被標註過的class的子類所繼承。類並不從它所實現的介面繼承annotation,方法並不從它所過載的方法繼承annotation。

      當@Inherited annotation型別標註的annotation的Retention是RetentionPolicy.RUNTIME,則反射API增強了這種繼承性。如果我們使用java.lang.reflect去查詢一個@Inherited annotation型別的annotation時,反射程式碼檢查將展開工作:檢查class和其父類,直到發現指定的annotation型別被發現,或者到達類繼承結構的頂層。

自定義註解

定義註解格式:
  public @interface 註解名 {定義體}

使用@interface自定義註解時,自動繼承了java.lang.annotation.Annotation介面,由編譯程式自動完成其他細節。在定義註解時,不能繼承其他的註解或介面。@interface用來宣告一個註解,其中的每一個方法實際上是聲明瞭一個配置引數。方法的名稱就是引數的名稱,返回值型別就是引數的型別(返回值型別只能是基本型別、Class、String、enum)。可以通過default來宣告引數的預設值。

註解引數的可支援資料型別:

1.所有基本資料型別(int,float,boolean,byte,double,char,long,short)
2.String型別
3.Class型別
4.enum型別
5.Annotation型別
6.以上所有型別的陣列

  Annotation型別裡面的引數設定:
   第一,只能用public或預設(default)這兩個訪問權修飾.例如,String value();這裡把方法設為defaul預設型別;   
第二,引數成員只能用基本型別byte,short,char,int,long,float,double,boolean八種基本資料型別和 String,Enum,Class,annotations等資料型別,以及這一些型別的陣列.例如,String value();這裡的引數成員就為String;  
  第三,如果只有一個引數成員,最好把引數名稱設為”value”,後加小括號.例:下面的例子FruitName註解就只有一個引數成員。
  

註解引數的可支援資料型別:

  1.所有基本資料型別(int,float,boolean,byte,double,char,long,short)
  2.String型別
  3.Class型別
  4.enum型別
  5.Annotation型別
  6.以上所有型別的陣列

  Annotation型別裡面的引數該怎麼設定: 
  
  第一,只能用public或預設(default)這兩個訪問權修飾.例如,String value();這裡把方法設為defaul預設型別;   
  第二,引數成員只能用基本型別byte,short,char,int,long,float,double,boolean八種基本資料型別和 String,Enum,Class,annotations等資料型別,以及這一些型別的陣列.例如,String value();這裡的引數成員就為String;  
  第三,如果只有一個引數成員,最好把引數名稱設為"value",後加小括號.

下面是一個簡單的自定義註解的栗子:

package annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 動物名稱註解
 *
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AnimalName {
    String value() default "";
}

定義了註解,並在需要的時候給相關類,類屬性加上註解資訊,如果沒有響應的註解資訊處理流程,註解可以說是沒有實用價值,接下來要介紹的是java的APT(Annotation Process Tool)技術,用於處理自定義註解。

2,APT技術

APT(Annotation Process Tool),是一種在程式碼編譯時處理註解,按照一定的規則,生成相應的java檔案,多用於對自定義註解的處理,目前比較流行的Dagger2, ButterKnife, EventBus3都是採用APT技術,對執行時的效能影響很小。我們通過自定義註解的方式,來了解一下如何使用APT:

1,自定義註解:

@Target({ElementType.TYPE})   ---作用範圍 Class

@Retention(RetentionPolicy.CLASS)  ---生命週期:僅保留到.class檔案

public @interface Route {
    /** Path of route*/
    String value();  ---類似於成員變數
}

2,使用方式

@Route(path = "/test/activity2")
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test2);
    }
}

JVM預設只會處理@override等語言自帶的註解,對於自定義的註解,需要我們自己處理,java提供了一個名為AbstractProcessor.java的抽象類,我們只要繼承該類,就實現自己的註解處理器,來處理自定義的@Route註解

public class RouteProcessor extends AbstractProcessor {

    @Override
    public synchronized void init(ProcessingEnvironment env){ 
        // 主要做一些初始化操作
    }

    @Override
        public boolean process(Set<? extends TypeElement> annoations, RoundEnvironment env) { 
        //具體處理註解的邏輯,控制程式碼的生成
        processAnnotations();
    }

    @Override
    public Set<String> getSupportedAnnotationTypes() { 
       // 支援處理的註解型別, 在這裡就是@Route

    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
      //java版本 如:jdk1.6or jdk1.7
   }

}

3,自定義Processor

@AutoService(Processor.class)
public class HelloProcessor extends AbstractProcessor {

    /** 檔案相關的輔助類 用於生成新的原始檔、class等 */
    private Filer mFiler;

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

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

        // 構建方法 此處使用到了square公司的javapoet庫,用來輔助生成 類的程式碼
        MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("show")
                .addModifiers(Modifier.PUBLIC);
        methodBuilder.addStatement("String test = \"$N\" ","hello annotation world!");

        /** 構建類 */
        TypeSpec finderClass = TypeSpec.classBuilder("Hello$$Inject")
                .addModifiers(Modifier.PUBLIC)
                .addMethod(methodBuilder.build())
                .build();
        try {
            JavaFile.builder("com.win.test",finderClass).build().writeTo(mFiler);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

    // 支援的註解型別
    @Override
    public Set<String> getSupportedAnnotationTypes() {
        Set<String> types = new LinkedHashSet<>();
        types.add(Hello.class.getCanonicalName());
        return types;
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return super.getSupportedSourceVersion();
    }
}

在AS工程中使用

@Hello("MainTest")   //自定義的Hello註解
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

在專案App module的build目錄下,便會生成對應的java類檔案:

這裡寫圖片描述

這個只是簡單的栗子,我們可以在process()方法中,加入更多的業務邏輯,以實現特定功能。

相關推薦

[轉]java註解APT技術

pretty runt src ons data exception clas -m animal 下面是一個簡單的自定義註解的栗子: package annotation; import java.lang.annotation.Docume

java註解APT技術

1,基本概念 什麼是註解? 註解(Annotation),也叫元資料。一種程式碼級別的說明。它是JDK1.5及以後版本引入的一個特性,與類、介面、列舉是在同一個層次。它可以宣告在包、類、欄位、方法、區域性變數、方法引數等的前面,用來對這些元素進行說

Java註解反射應用的小例子

1.功能介紹    小例子主要完成以下功能,通過Java反射獲取SQL語句,使用MyBatis傳入SQL語句,將資料插入到資料庫中2.程式碼講解2.1 自定義註解    首先看一個自定義註解,在此例子中我自定義了兩個註解,一個叫DBTable,另一個是DBColumn。   

[java][annotation][@Aspect]Java註解切面使用

import org.springframework.kafka.annotation.KafkaListener; impor

Spring註解Java註解小結

spa package param style 值範圍 描述 tro ret 類型 註解 Annotation 基於註解的開發,使得代碼簡潔,可讀性高,簡化的配置的同時也提高了開發的效率,尤其是SpringBoot的興起,隨著起步依賴和自動配置的完善,更是將基於註解的開發推

Java併發程式設計高階技術-高效能併發框架原始碼解析實戰(資源同步)

第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級資料進行壓力測試。讓大

6. Spring:Java註解技術詳解

6. Spring:Java註解技術詳解 自定義註解示例:https://blog.csdn.net/wangpengzhi19891223/article/details/78131137/ Java註解技術基本概念 Annotation是Java5開始引入的新特徵。中文

Java併發程式設計高階技術-高效能併發框架原始碼解析實戰(無密連結)

第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級資料進行壓力測試。讓大

Java併發程式設計高階技術-高效能併發框架原始碼解析實戰

Java併發程式設計高階技術-高效能併發框架原始碼解析與實戰 第1章 課程介紹 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後

#Java怎麼學?2018最新Java學習路線,技術要求專案推薦詳解!

一 基礎篇 很多人認為,java的基礎應該是C語言,這個不可否認,但是也不能說完全正確,因為兩個語言技術的內涵是不一樣的,C語言是面向語言程式設計而java語言是面向物件程式設計,打個比喻,C語言大多數是做系統應用,而java是做企業級應用的。所以,學Java不一定要學C,Java簡化了C,而在

Python自動生成10000個java類使用APT註解後引發的問題!

前言 前面寫了一篇關於自己開發的一個 基於APT註解的用於RecyclerView複雜樓層的開源框架 ,框架的原理比較簡單,通過註解,在編譯期會生成一個ComponentRule.java的檔案,然後建立一個對映關係。使用方式簡單介紹一下: 1.繫結佈局檔案 @ComponentType

某課最新Java併發程式設計高階技術-高效能併發框架原始碼解析實戰

第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級

某課最全Java併發程式設計高階技術-高效能併發框架原始碼解析實戰

第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級

阿里專家你分享:你必須瞭解的Java多執行緒技術

摘要: 本文介紹了Lambda表示式的起源以及基本語法,並提供程式碼例項幫助大家理解Lambda表示式的使用。另外,本文介紹了Java開發中常用的多執行緒技術,詳細介紹多執行緒涉及到的概念以及使用方法。 數十款阿里雲產品限時折扣中,趕緊點選這裡,領劵開始雲上實踐吧! 演講

2018最新Java併發程式設計高階技術-高效能併發框架原始碼解析實戰(已完結)

第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級資料進行壓力測試。讓大

閒談java中的程式編譯優化技術

java中的程式編譯和優化技術同其他語言一樣基本都發生在編譯期。java的編譯期可根據不同的編譯器分為三個部分,一個是前端編譯器,比如javac;它的工作就是把.java檔案轉化為.class檔案。另一個是即時編譯器,比如JIT編譯器;它的工作是把.class檔案中的某些

某課無加密Java併發程式設計高階技術-高效能併發框架原始碼解析實戰

第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級

Java併發程式設計高階技術-高效能併發框架原始碼解析實戰(雲盤分享)

第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級

某網Java併發程式設計高階技術-高效能併發框架原始碼解析實戰(雲盤下載)

第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級

Android進階——Java註解實戰之APT構建模組化的第一步

前言 APT的學習要花點時間去掌握和實踐的,短時間內只能掌握知識點,更多的是在實戰中去實踐。其實,APT就是一種工具而已,只要用多了,自然就會熟練了,不過要想實踐之前,還是必須把基礎知識學好才能實戰進入開發。文章會從基礎用例講解知識點,然後再通過實戰進行實踐 APT簡介 AP