美文网首页
reflections:Java runtime metadat

reflections:Java runtime metadat

作者: hemiao3000 | 来源:发表于2022-10-20 07:13 被阅读0次

关于 reflections 及其版本

Reflections 通过扫描 classpath ,索引元数据,并且允许在运行时查询这些元数据。

使用 Reflections 可以很轻松的获取以下元数据信息:

  • 获取某个类型的全部子类;
  • 只要类型、构造器、方法,字段上带有特定注解,便能获取带有这个注解的全部信息<small>( 类型、构造器、方法,字段 )</small>;
  • 获取所有能匹配某个正则表达式的资源;
  • 获取所有带有特定签名的方法,包括参数,参数注解,返回类型;
  • 获取所有方法的名字;
  • 获取代码里所有字段、方法名、构造器的使用。

官方 github

当前,reflections 有 3 个"特色鲜明"的版本:

  • 0.9.11 是最后一个依赖 guava 的版本;
  • 0.9.12 从这个版本开始移除了 guava 依赖;
  • 0.10.2 相较于 0.9.x 版本,0.10 版本采用了新的函数式的编程风格。<small>学习曲线变陡峭了,对初级程序员来说不太友好。</small>

综合考虑,对于初学者而言,推荐使用 0.9.12 版本。

<!-- https://mvnrepository.com/artifact/org.reflections/reflections -->
<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.9.12</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);

扫描字段注解

// 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)

public class Store extends HashMap<String, Map<String, Set<String>>> ;
import static org.reflections.ReflectionUtils.*;


// 查找 C3 的祖先,看谁的"脑袋"上有 AI1 注解。
getAllSuperTypes(TestModel.C3.class, withAnnotation(TestModel.AI1.class);

// 查找 C4 的方法,要求要是 public 的,且返回值为 void 。
getAllMethods(TestModel.C4.class, withModifier(Modifier.PUBLIC), withReturnType(void.class));
// 同上
getAllMethods(TestModel.C4.class, withPattern("public.*.void .*"));
            
// 查找 C4 的方法,要求方法中至少有个参数用到了 AM1 注解。
getAllMethods(TestModel.C4.class, withAnyParameterAnnotation(TestModel.AM1.class))
            
// 查找 C4 的域,要求被标注了 AF1 注解。 
getAllFields(TestModel.C4.class, withAnnotation(TestModel.AF1.class))
            
// 查找 C4 的域,要求被标准娱乐 AF1 注解,且注解的 value 属性值为 "2"
getAllFields(TestModel.C4.class, withAnnotation(new TestModel.AF1() {
        public String value() {return "2";}
        public Class<? extends Annotation> annotationType() {return TestModel.AF1.class;}}))
               
// 查找 C4 的域,要求能够被 String 类型赋值的。
getAllFields(TestModel.C4.class, withTypeAssignableTo(String.class))

// 查找 C4 的构造器,无参的那个
getAllConstructors(TestModel.C4.class, withParametersCount(0))

// 查找 C3 脑袋上的注解,包括从祖先那里继承来的。
getAllAnnotations(TestModel.C3.class).size()

// 查找 C4 中叫 m4 的方法。
getMethods(TestModel.C4.class, withName("m4")).iterator().next();

/****************
* withParameter *
****************/
                 



assertTrue(getAnnotations(m4).isEmpty());

    @Test public void () throws Exception {
        Class target = Collections.class;
        Object arg1 = Arrays.asList(1, 2, 3);

        Set<Method> allMethods = new HashSet<>();
        for (Class<?> type : getAllSuperTypes(arg1.getClass())) {
            allMethods.addAll(getAllMethods(target, withModifier(Modifier.STATIC), withParameters(type)));
        }

        Set<Method> allMethods1 = getAllMethods(target, withModifier(Modifier.STATIC), withParametersAssignableTo(arg1.getClass()));

        assertEquals(allMethods, allMethods1);

        for (Method method : allMethods) { //effectively invokable
            //noinspection UnusedDeclaration
            Object invoke = method.invoke(null, arg1);
        }
    }

    @Test
    public void withParametersAssignableFromTest() throws Exception {
        //Check for null safe
        getAllMethods(Collections.class, withModifier(Modifier.STATIC), withParametersAssignableFrom());

        Class target = Collections.class;
        Object arg1 = Arrays.asList(1, 2, 3);

        Set<Method> allMethods = new HashSet<>();
        for (Class<?> type : getAllSuperTypes(arg1.getClass())) {
            allMethods.addAll(getAllMethods(target, withModifier(Modifier.STATIC), withParameters(type)));
        }

        Set<Method> allMethods1 = getAllMethods(target, withModifier(Modifier.STATIC), withParametersAssignableFrom(Iterable.class), withParametersAssignableTo(arg1.getClass()));

        assertEquals(allMethods, allMethods1);

        for (Method method : allMethods) { //effectively invokable
            //noinspection UnusedDeclaration
            Object invoke = method.invoke(null, arg1);
        }
    }

    @Test public void withReturn() {
        Set<Method> returnMember = getAllMethods(Class.class, withReturnTypeAssignableTo(Member.class));
        Set<Method> returnsAssignableToMember = getAllMethods(Class.class, withReturnType(Method.class));

        assertTrue(returnMember.containsAll(returnsAssignableToMember));
        assertFalse(returnsAssignableToMember.containsAll(returnMember));

        returnsAssignableToMember = getAllMethods(Class.class, withReturnType(Field.class));
        assertTrue(returnMember.containsAll(returnsAssignableToMember));
        assertFalse(returnsAssignableToMember.containsAll(returnMember));
    }

    @Test
    public void getAllAndReflections() {
        Reflections reflections = new Reflections(TestModel.class, new FieldAnnotationsScanner());

        Set<Field> af1 = reflections.getFieldsAnnotatedWith(TestModel.AF1.class);
        Set<? extends Field> allFields = ReflectionUtils.getAll(af1, withModifier(Modifier.PROTECTED));
        assertEquals(1, allFields.size());
        assertThat(allFields, names("f2"));
    }

}

相关文章

网友评论

      本文标题:reflections:Java runtime metadat

      本文链接:https://www.haomeiwen.com/subject/jqvpzrtx.html