背景
最近在設計和開發部門的基礎架構,需要利用反射技術找到classpath目錄下所有包含指定注解的類,然后根據注解配置完成指定的功能。
最初是想自己寫代碼來實現這些功能,邊查資料邊寫,整了大半天,寫出來的效果自己都不太滿意。一方面是代碼多,不好維護;另一方面是性能不太好。不過,在查資料的過程中,我發現了一個非常好用的反射框架:reflections。
reflections簡單好用,性能也不錯,很快就完成了我想要的功能,就是這么優秀!
簡介
Reflections通過掃描classpath,索引元數據,並且允許在運行時查詢這些元數據。
使用Reflections可以很輕松的獲取以下元數據信息:
- 獲取某個類型的全部子類
- 只要類型、構造器、方法,字段上帶有特定注解,便能獲取帶有這個注解的全部信息(類型、構造器、方法,字段)
- 獲取所有能匹配某個正則表達式的資源
- 獲取所有帶有特定簽名的方法,包括參數,參數注解,返回類型
- 獲取所有方法的名字
- 獲取代碼里所有字段、方法名、構造器的使用
Maven依賴
在pom.xml中添加reflections的依賴:
<dependency> <groupId>org.reflections</groupId> <artifactId>reflections</artifactId> <version>0.9.11</version> </dependency>
// 實例化Reflections,並指定要掃描的包名 Reflections reflections = new Reflections("my.project"); // 獲取某個類的所有子類 Set<Class<? extends SomeType>> subTypes = reflections.getSubTypesOf(SomeType.class); // 獲取包含某個注解的所有類 Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(SomeAnnotation.class);
使用
//scan urls that contain 'my.package', include inputs starting with 'my.package', use the default scanners Reflections reflections = new Reflections("my.package"); //or using ConfigurationBuilder new Reflections(new ConfigurationBuilder() .setUrls(ClasspathHelper.forPackage("my.project.prefix")) .setScanners(new SubTypesScanner(), new TypeAnnotationsScanner().filterResultsBy(optionalFilter), ...), .filterInputsBy(new FilterBuilder().includePackage("my.project.prefix")) ...);
掃描子類
Set<Class<? extends Module>> modules = reflections.getSubTypesOf(com.google.inject.Module.class);
掃描注解
//TypeAnnotationsScanner Set<Class<?>> singletons = reflections.getTypesAnnotatedWith(javax.inject.Singleton.class);
掃描資源
//ResourcesScanner Set<String> properties = reflections.getResources(Pattern.compile(".*\\.properties"));
掃描方法注解
//MethodAnnotationsScanner Set<Method> resources = reflections.getMethodsAnnotatedWith(javax.ws.rs.Path.class); Set<Constructor> injectables = reflections.getConstructorsAnnotatedWith(javax.inject.Inject.class);
掃描字段注解
//FieldAnnotationsScanner Set<Field> ids = reflections.getFieldsAnnotatedWith(javax.persistence.Id.class);
掃描方法參數
//MethodParameterScanner Set<Method> someMethods = reflections.getMethodsMatchParams(long.class, int.class); Set<Method> voidMethods = reflections.getMethodsReturn(void.class); Set<Method> pathParamMethods = reflections.getMethodsWithAnyParamAnnotated(PathParam.class);
掃描方法參數名
//MethodParameterNamesScanner List<String> parameterNames = reflections.getMethodParamNames(Method.class)
掃描方法調用情況
//MemberUsageScanner Set<Member> usages = reflections.getMethodUsages(Method.class)
參考資料
//TypeAnnotationsScanner
Set<Class<?>> singletons =
reflections.getTypesAnnotatedWith(javax.inject.Singleton.class);