Github地址:https://github.com/ronmamo/reflections

简介

Reflections会扫描classpath,索引元数据(indexes),允许您在运行时查询它,为项目中的许多模块保存和收集信息。

使用Reflections,您可以查询:

  • get all subtypes of some type 获取子类
  • get all types/members annotated with some annotation 根据注解获取类型和成员变量
  • get all resources matching a regular expression 根据正则匹配资源
  • get all methods with specific signature including parameters, parameter annotations and return type 获取方法的获取参数、参数注解返回值

集成

Add Reflections to your project. for maven projects just add this dependency:

<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.9.11</version>
</dependency>

A typical use of Reflections would be:

Reflections reflections = new Reflections("my.project");
Set<Class<? extends SomeType>> subTypes = reflections.getSubTypesOf(SomeType.class);
Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(SomeAnnotation.class);

注意,可能与其他库有冲突,如google-collections。类似见issue: https://github.com/ronmamo/reflections/issues/194

使用

1). 使用Reflections首先通过urlsscaner进行初始化

  • 方式1: 直接接包名,此时使用默认的scaner
  • 方式2: 使用ConfigurationBuilder构建
//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"))
     ...);

2). 直接调用查询方法(取决于配置的scanner配置)

//SubTypesScanner
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)
  • 如果scanners没有配置,默认将会使用SubTypesScannerTypeAnnotationsScanner
  • 还可以配置Classloader,它将根据名称中解析运行时类。
  • Reflection默认情况下会扩展超类。这解决了传输URL不被扫描的一些问题

Checkout the javadoc for more info.

Also, browse the tests directory to see some more examples.

ReflectionUtils

ReflectionsUtils包含一些方便的Java反射辅助方法,用于获取匹配types/constructors/methods/fields/annotations,通常采用谓词,如* getAllXXX(type,withYYY)的格式。

举例:

import static org.reflections.ReflectionUtils.*;

Set<Method> getters = getAllMethods(someClass,
  withModifier(Modifier.PUBLIC), withPrefix("get"), withParametersCount(0));

//or
Set<Method> listMethodsFromCollectionToBoolean = 
  getAllMethods(List.class,
    withParametersAssignableTo(Collection.class), withReturnType(boolean.class));

Set<Field> fields = getAllFields(SomeClass.class, withAnnotation(annotation), withTypeAssignableTo(type));

See more in the ReflectionUtils javadoc

例子

//根据包名初始化
Reflections reflections = new Reflections("cc.tyrad.smartservice");
//获取子类
Set<Class<? extends com.baomidou.mybatisplus.extension.activerecord.Model>> subTypes = reflections.getSubTypesOf(com.baomidou.mybatisplus.extension.activerecord.Model.class);
for (Class<? extends com.baomidou.mybatisplus.extension.activerecord.Model> class1 : subTypes) {
    log.info("获取Model的子类=:{}", class1.toString());
}
//获取注解修饰的类
Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(RestController.class);
for (Class<?> class1 : annotated) {
    log.info("获取包含RestController注解的类=:{}", class1.toString());
}