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> getRequestMappingMethod(String packageName) { Reflections reflections = new Reflections(packageName); Set<class>> classesList = reflections.getTypesAnnotatedWith(Controller.class); // 存放url和ExecutorBean的对应关系 Map<string> mapp = new HashMap<string>(); 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; } }</string></string></class></string>
#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> mmap = new HashMap<string>(); 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(); } } }</string></string></class>
運行得到:
其他
-
使用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 annotationClass)< T extends Annotation>為泛型參數聲明,表明A的類型只能是Annotation類型或是Annotation的子類別。
功能:傳回該程式元素上存在的、指定類型的註解,如果該類型的註解不存在,則傳回null Annotation[] getAnnotations()
功能:傳回此元素上存在的所有註解,包括沒有顯示定義在該元素上的註解(繼承得到的)。 (如果此元素沒有註釋,則傳回長度為零的陣列。)T getDeclaredAnnotation(Class annotationClass)
功能:這是Java8新增的方法,此方法傳回直接修飾該程式元素、指定類型的註解(忽略繼承的註解)。如果該類型的註解不存在,則傳回null.Annotation[] getDeclaredAnnotations()
功能:傳回直接存在於此元素上的所有註解,該方法將忽略繼承的註釋。 (如果沒有註解直接存在於此元素上,則傳回長度為零的一個陣列。)boolean isAnnotationPresent(Class extends Annotation>annotationClass)
功能:判斷判斷該程式元素上是否存在指定類型的註解,如果存在則傳回true,否則回傳false。<T extends Annotation> T[] getAnnotationsByTpye(Class
annotationClass)
功能: 因為java8增加了重複註解功能,因此需要使用該方法獲得修飾該程式元素、指定類型的多個註解。T[] getDeclaredAnnotationsByTpye(Class annotationClass)
功能: 因為java8增加了重複註解功能,因此需要使用此方法獲得直接修飾該程式元素、指定類型的多個註解。
Class提供了getMethod()、getField()以及getConstructor()方法(還有其他方法),這些方法分別取得與方法、領域變數以及建構子相關的信息,這些方法傳回Method、Field 以及Constructor型別的物件。
以上是取得指定包下所有自訂註解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Atom編輯器mac版下載
最受歡迎的的開源編輯器

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

SublimeText3漢化版
中文版,非常好用

WebStorm Mac版
好用的JavaScript開發工具

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器