首頁 Java java教程 取得指定包下所有自訂註解

取得指定包下所有自訂註解

Jun 23, 2017 pm 03:26 PM
指定 註解 自訂 獲取

Reflections 透過掃描 classpath,索引元數據,允許在運行時查詢這些元數據,也可以保存收集項目中多個模組的元數據資訊。

使用Reflections快速掃描指定包下自訂的Controller和RequestMapping兩個註解,先去掃描加了@Controller註解的類,接著獲取這些類下面加了@RequestMapping註解的方法,然後透過Java的反射invoke方法去呼叫加了RequestMapping註解的方法並輸出註解上的資訊。

Maven 專案導入

<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.9.10</version>
</dependency>
登入後複製

annotation套件下面自訂了兩個註解。

Controller.java:

package annotationTest.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.TYPE)// 注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Retention(RetentionPolicy.RUNTIME)//定义注解的作用目标**作用范围字段、枚举的常量/方法
@Documented//说明该注解将被包含在javadoc中
public @interface Controller {
    String value() default "";
}
登入後複製

RequestMapping.java

package annotationTest.annotation;

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

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
    String value() default "";

    /**
     * 是否为序列号
     *
     * @return
     */
    boolean id() default false;

    /**
     * 字段名称
     *
     * @return
     */
    String name() default "";

    /**
     * 字段描述
     *
     * @return
     */
    String description() default "";
}
登入後複製

在model套件下面定義了一個存放RequestMapping註解方法的物件

ExecutorBean.java

package annotationTest.model;

import java.lang.reflect.Method;

public class ExecutorBean {
    private Object object;

    private Method method;

    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }
}
登入後複製

service套件下面定義了幾個類,其中有兩個類別使用了自訂的Controller註解

SunService. java

package annotationTest.service;

import annotationTest.annotation.Controller;
import annotationTest.annotation.RequestMapping;

@Controller
public class SunService {
    @RequestMapping(id = true, name = "test1", description = "sun测试1", value = "/test1")
    public void test1() {
        System.out.println("SunService->test1()");
    }

    @RequestMapping(id = true, name = "test2", description = "sun测试2", value = "/test2")
    public void test2() {
        System.out.println("SunService->test2()");
    }
}
登入後複製

MoonService.java

package annotationTest.service;

import annotationTest.annotation.Controller;
import annotationTest.annotation.RequestMapping;

@Controller
public class MoonService {
    @RequestMapping(id = true, name = "moon测试3", description = "/test3", value = "/test3")
    public void test3() {
        System.out.println("MoonService->test3()");
    }

    @RequestMapping(id = true, name = "moon测试4", description = "/test4", value = "/test4")
    public void test4() {
        System.out.println("MoonService->test4()");
    }
}
登入後複製

Stars.java

package annotationTest.service;

import annotationTest.annotation.RequestMapping;

public class Stars {
    @RequestMapping(id = true, name = "test1", description = "stars测试1", value = "/test1")
    public void test1() {
        System.out.println("Stars->test1()");
    }
}
登入後複製

util套件下面定義了一個工具類,來對套件進行掃描獲取自定義註解的類別與方法

AnnoManageUtil.java

package annotationTest.util;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import annotationTest.annotation.Controller;
import annotationTest.annotation.RequestMapping;
import annotationTest.model.ExecutorBean;
import org.reflections.Reflections;

public final class AnnoManageUtil {

    /**
     * 获取指定文件下面的RequestMapping方法保存在mapp中
     *
     * @param packageName
     * @return
     */
    public static Map<String, ExecutorBean> getRequestMappingMethod(String packageName) {
        Reflections reflections = new Reflections(packageName);
        Set<Class<?>> classesList = reflections.getTypesAnnotatedWith(Controller.class);

        // 存放url和ExecutorBean的对应关系
        Map<String, ExecutorBean> mapp = new HashMap<String, ExecutorBean>();
        for (Class classes : classesList) {
            //得到该类下面的所有方法
            Method[] methods = classes.getDeclaredMethods();

            for (Method method : methods) {
                //得到该类下面的RequestMapping注解
                RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
                if (null != requestMapping) {
                    ExecutorBean executorBean = new ExecutorBean();
                    try {
                        executorBean.setObject(classes.newInstance());
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    executorBean.setMethod(method);
                    mapp.put(requestMapping.value(), executorBean);

                }
            }
        }
        return mapp;
    }

}
登入後複製

#test套件下面是一個測試的類別

package annotationTest.test;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import annotationTest.annotation.Controller;
import annotationTest.annotation.RequestMapping;
import annotationTest.model.ExecutorBean;
import annotationTest.util.AnnoManageUtil;

public class Test {
    public static void main(String[] args) {
        List<Class<?>> classesList = null;
        classesList = AnnoManageUtil.getPackageController("annotationTest.service", Controller.class);
        Map<String, ExecutorBean> mmap = new HashMap<String, ExecutorBean>();
        AnnoManageUtil.getRequestMappingMethod(classesList, mmap);
        ExecutorBean bean = mmap.get("/test1");

        try {
            bean.getMethod().invoke(bean.getObject());
            RequestMapping annotation = bean.getMethod().getAnnotation(RequestMapping.class);
            System.out.println("注解名称:" + annotation.name() + "\t注解描述:" + annotation.description());
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
登入後複製

運行得到:

取得指定包下所有自訂註解

其他

  1. 使用Reflections 可以查詢以下元資料資訊:

    Reflections 依賴Google 的Guava函式庫和Javassist 函式庫。

  • 得到某個類型的所有子類型

  • #獲得標記了某個註解的所有類型/成員變量,支援註解參數匹配。

  • 使用正規表示式獲得所有符合的資源檔案

  • #獲得所有特定簽章(包括參數,參數註解,傳回值)的方法

  • 使用註解修飾了類別/方法/成員變數等之後,這些註解不會自己生效,必須由這些註解的開發者提供相應的工具來提取並處理註解資訊(當然​​,只有當定義註解時使用了@Retention(RetentionPolicy.RUNTIME)修飾,JVM才會在裝載class檔案時提取保存在class檔案中的註解,該註解才會在運行時可見,這樣我們才能夠解析).

  • Java使用Annotation介面來代表程式元素前面的註解,該介面是所有註解的父介面。

  • java5在java.lang.reflect套件下新增了用AnnotatedElement介面代表程式中可以接受註解的程式元素.

  • AnnotatedElement介面的實作類別有:Class(類別元素)、Field(類別的成員變數元素)、Method(類別的方法元素)、Package(套件元素),每一個實作類別代表了一個可以接受註解的程式元素類型。

  • 這樣, 我們只需要獲取到Class、 Method、 Filed等這些實作了AnnotatedElement介面的類別的實例,透過該實例物件呼叫該類別中的方法(AnnotatedElement介面中抽象方法的重寫) 就可以獲得我們想要的註解資訊了。

  • 得到Class類別的實例有三種方法:

    • #利用物件呼叫getClass()方法來取得Class實例

    • 利用Class類別的靜態的forName()方法,使用類別名稱取得Class實例

    • #運用.class的方式取得Class實例,如:類別名.class

  • AnnotatedElement介面提供的抽象方法(在該介面的實作類別中重寫了這些方法):

    • T getAnnotation(Class< T> annotationClass)< T extends Annotation>為泛型參數聲明,表明A的類型只能是Annotation類型或是Annotation的子類別。
      功能:傳回該程式元素上存在的、指定類型的註解,如果該類型的註解不存在,則傳回null

    • Annotation[] getAnnotations()
      功能:傳回此元素上存在的所有註解,包括沒有顯示定義在該元素上的註解(繼承得到的)。 (如果此元素沒有註釋,則傳回長度為零的陣列。)

    • < T extends Annotation> T getDeclaredAnnotation(Class < T> annotationClass)
      功能:這是Java8新增的方法,此方法傳回直接修飾該程式元素、指定類型的註解(忽略繼承的註解)。如果該類型的註解不存在,則傳回null.

    • Annotation[] getDeclaredAnnotations()
      功能:傳回直接存在於此元素上的所有註解,該方法將忽略繼承的註釋。 (如果沒有註解直接存在於此元素上,則傳回長度為零的一個陣列。)

    • boolean isAnnotationPresent(ClassannotationClass)
      功能:判斷判斷該程式元素上是否存在指定類型的註解,如果存在則傳回true,否則回傳false。

    • <T extends Annotation> T[] getAnnotationsByTpye(Class annotationClass)
      功能: 因為java8增加了重複註解功能,因此需要使用該方法獲得修飾該程式元素、指定類型的多個註解。

    • T[] getDeclaredAnnotationsByTpye(ClassannotationClass)
      功能: 因為java8增加了重複註解功能,因此需要使用此方法獲得直接修飾該程式元素、指定類型的多個註解。

    Class提供了getMethod()、getField()以及getConstructor()方法(還有其他方法),這些方法分別取得與方法、領域變數以及建構子相關的信息,這些方法傳回Method、Field 以及Constructor型別的物件。

    以上是取得指定包下所有自訂註解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    本網站聲明
    本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

    熱AI工具

    Undresser.AI Undress

    Undresser.AI Undress

    人工智慧驅動的應用程序,用於創建逼真的裸體照片

    AI Clothes Remover

    AI Clothes Remover

    用於從照片中去除衣服的線上人工智慧工具。

    Undress AI Tool

    Undress AI Tool

    免費脫衣圖片

    Clothoff.io

    Clothoff.io

    AI脫衣器

    AI Hentai Generator

    AI Hentai Generator

    免費產生 AI 無盡。

    熱門文章

    R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
    1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.最佳圖形設置
    1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
    威爾R.E.P.O.有交叉遊戲嗎?
    1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

    熱工具

    記事本++7.3.1

    記事本++7.3.1

    好用且免費的程式碼編輯器

    SublimeText3漢化版

    SublimeText3漢化版

    中文版,非常好用

    禪工作室 13.0.1

    禪工作室 13.0.1

    強大的PHP整合開發環境

    Dreamweaver CS6

    Dreamweaver CS6

    視覺化網頁開發工具

    SublimeText3 Mac版

    SublimeText3 Mac版

    神級程式碼編輯軟體(SublimeText3)

    如何在Netflix中快速設定自訂頭像 如何在Netflix中快速設定自訂頭像 Feb 19, 2024 pm 06:33 PM

    Netflix上的頭像是你串流媒體身分的視覺化代表。使用者可以超越預設的頭像來展現自己的個性。繼續閱讀這篇文章,了解如何在Netflix應用程式中設定自訂個人資料圖片。如何在Netflix中快速設定自訂頭像在Netflix中,沒有內建功能來設定個人資料圖片。不過,您可以透過在瀏覽器上安裝Netflix擴充功能來實現此目的。首先,在瀏覽器上安裝Netflix擴充功能的自訂個人資料圖片。你可以在Chrome商店買到它。安裝擴充功能後,在瀏覽器上開啟Netflix並登入您的帳戶。導航至右上角的個人資料,然後點擊

    Eclipse中自訂快捷鍵設定的方法 Eclipse中自訂快捷鍵設定的方法 Jan 28, 2024 am 10:01 AM

    如何在Eclipse中自訂快捷鍵設定?身為開發人員,在使用Eclipse進行編碼時,熟練快捷鍵是提高效率的關鍵之一。 Eclipse作為一個強大的整合開發環境,不僅提供了許多預設的快捷鍵,還允許使用者根據自己的偏好進行個人化的客製化。本文將介紹如何在Eclipse中自訂快捷鍵設置,並給出具體的程式碼範例。打開Eclipse首先,打開Eclipse,並進入

    谷歌安全碼在哪裡獲取 谷歌安全碼在哪裡獲取 Mar 30, 2024 am 11:11 AM

    谷歌驗證器是一種用於保護使用者帳戶安全的工具,其金鑰是用於產生動態驗證碼的重要資訊。如果忘記了谷歌驗證器的金鑰,只能透過安全碼進行驗證,那麼下文站小編就會為大家帶來谷歌安全碼在哪裡取得的詳細內容介紹,希望能幫助到大家,想要了解的用戶們就請跟著下文繼閱讀吧!首先開啟手機設置,進入設定頁面。下拉頁面,找到Google。進入Google頁面,點選Google帳號。進入帳號頁面,點選驗證碼下方的檢視。輸入密碼或使用指紋驗證身分。取得Google安全碼,利用安全碼驗證Google身分。

    JUnit框架中註解如何用於測試方法? JUnit框架中註解如何用於測試方法? May 06, 2024 pm 05:33 PM

    JUnit框架中的註解用於聲明和配置測試方法,主要註解包括:@Test(聲明測試方法)、@Before(測試方法執行前運行的方法)、@After(測試方法執行後運行的方法)、@ BeforeClass(所有測試方法執行前運行的方法)、@AfterClass(所有測試方法執行後運行的方法),這些註解有助於組織和簡化測試程式碼,並透過提供明確的意圖和配置來提高測試程式碼的可讀性和可維護性。

    PHP 程式碼文檔化之王:PHPDoc 的進階指南 PHP 程式碼文檔化之王:PHPDoc 的進階指南 Mar 02, 2024 am 08:43 AM

    引言:PHPDoc是一種用於php程式碼的註解標準,可產生易於理解且資訊豐富的文件。透過使用特定的註釋標籤,PHPDoc允許開發人員提供有關函數、類別、方法和其他程式碼元素的重要詳細資訊。這篇進階指南將深入探討PHPDoc,展示其功能並提供有效的文檔化策略。語法與標籤:PHPDoc註解以雙斜線(//)或多行註解(/**/)開頭。以下是一些常見的註解標籤:@param:定義函數或方法的參數。 @return:指定函數或方法的回傳值。 @throws:說明函數或方法可能引發的異常。 @var:定義類別的屬性或實例

    edius自訂螢幕佈局的操作流程 edius自訂螢幕佈局的操作流程 Mar 27, 2024 pm 06:50 PM

    1.下圖是edius預設的螢幕佈局,預設的EDIUS視窗佈局是橫向版式,因此在單一顯示器環境中,許多視窗是重疊在一起的,且預覽視窗為單一視窗模式。 2、您可以透過【檢視】選單列啟用【雙視窗模式】,使預覽視窗同時顯示播放視窗和錄製視窗。 3.您可以透過【檢視功能表列>視窗佈局>常規】來恢復預設螢幕佈局。另外您也可以自訂適合您的佈局方式,並儲存為常用螢幕佈局:將視窗拖曳成適合自己的佈局,然後點擊【檢視>視窗佈局>儲存目前佈局>新建】,在彈出的【儲存目前佈局】小視窗中輸入佈局名稱,按確定

    Jackson庫中註解如何控制JSON序列化和反序列化? Jackson庫中註解如何控制JSON序列化和反序列化? May 06, 2024 pm 10:09 PM

    Jackson庫中的註解可控制JSON序列化和反序列化:序列化:@JsonIgnore:忽略屬性@JsonProperty:指定名稱@JsonGetter:使用獲取方法@JsonSetter:使用設定方法反序列化:@JsonIgnoreProperties:忽略屬性@ JsonProperty:指定名稱@JsonCreator:使用建構子@JsonDeserialize:自訂邏輯

    詳解MyBatis註解與動態SQL的操作步驟 詳解MyBatis註解與動態SQL的操作步驟 Feb 18, 2024 pm 03:29 PM

    MyBatis註解動態SQL的使用方法詳解IntroductiontotheusageofMyBatisannotationdynamicSQLMyBatis是一個持久層框架,為我們提供了便利的持久化操作。在實際開發中,通常需要根據業務需求來動態產生SQL語句,以實現靈活的資料操作。 MyBatis註解動態SQL正是為了滿足這項需求而設計的,本

    See all articles