Java Reflections

作者: 老鼠AI大米_Java全栈 | 来源:发表于2023-03-14 21:02 被阅读0次

    1. 简介

    reflections 是一个 Java 反射工具包,使用它可以非常方便的获取一下字段或者方法。

    2. maven

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

    3. 配置

    最简单的配置,就是直接指定扫描包:

    Reflections reflections = new Reflections("java.util");

    当然,也可以:

    @Test
    public void config(){
        ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
        //扫描vip.mycollege.jdk.reflect包
        Collection<URL> scannerPkg = ClasspathHelper.forPackage("vip.mycollege.jdk.reflect");
    
        SubTypesScanner subTypesScanner = new SubTypesScanner();
    
        //注解扫描
        TypeAnnotationsScanner typeAnnotationsScanner = new TypeAnnotationsScanner();
    
        FilterBuilder filter = new FilterBuilder()
                .includePackage("vip.mycollege.jdk.reflect")//注解扫描包
                .excludePackage("vip.mycollege.jdk.reflect.thirdpart");//注解扫描扫描排除包
        typeAnnotationsScanner.filterResultsBy(filter);
    
        ConfigurationBuilder configuration = configurationBuilder
                .setUrls(scannerPkg)
                .setScanners(subTypesScanner, typeAnnotationsScanner);
    
        Reflections reflections = new Reflections(configuration);
    }
    

    4. 通过类型扫描

    @Test
    public void newInstance(){
        Reflections reflections = new Reflections("java.util");
        //获取List及其子类
        Set<Class<? extends List>> listImpls = reflections.getSubTypesOf(List.class);
        listImpls.forEach(System.out::println);
    }
    

    5. 通过注解扫描

    @Test
    public void methodAnnotationsScanner(){
        Reflections reflections = new Reflections(SCAN_PKG);
        //方法上有Deprecated注解
        Set<Method> resources = reflections.getMethodsAnnotatedWith(Deprecated.class);
        //有PostConstruct注解的构造方法
        Set<Constructor> injectables = reflections.getConstructorsAnnotatedWith(PostConstruct.class);
    }
    
    @Test
    public void FieldAnnotationsScanner(){
        //指定包下有Nonnegative的字段
        Reflections reflections = new Reflections(SCAN_PKG);
        Set<Field> ids = reflections.getFieldsAnnotatedWith(Nonnegative.class);
    }
    

    6. 方法相关

    @Test
    public void methodParameterScanner(){
        Reflections reflections = new Reflections(SCAN_PKG);
        //参数类型是long和int
        Set<Method> someMethods = reflections.getMethodsMatchParams(long.class, int.class);
        //参数返回值是void
        Set<Method> voidMethods = reflections.getMethodsReturn(void.class);
        //任何参数上有注解Nullable
        Set<Method> pathParamMethods = reflections.getMethodsWithAnyParamAnnotated(Nullable.class);
    
        for(Method method : someMethods) {
            //获取方法参数的名称
            List<String> parameterNames = reflections.getMethodParamNames(method);
            parameterNames.forEach(System.out::println);
        }
    }
    

    7. 工具类

    @Test
    public void reflectionUtils(){
        //必须是public方法
        Predicate<Method> publicPredicate = ReflectionUtils.withModifier(Modifier.PUBLIC);
        //有get前缀
        Predicate<Method> getPredicate = ReflectionUtils.withPrefix("get");
        //参数个数为0
        Predicate<Member> paramPredicate = ReflectionUtils.withParametersCount(0);
        Set<Method> methods = ReflectionUtils.getAllMethods(LinkedList.class, publicPredicate, getPredicate, paramPredicate);
        methods.forEach(method -> System.out.println(method.getName()));
    
        System.out.println("---------------");
        //参数必须是Collection及其子类
        Predicate<Member> paramsPredicate = ReflectionUtils.withParametersAssignableTo(Collection.class);
        //返回类型是boolean
        Predicate<Method> returnPredicate = ReflectionUtils.withReturnType(boolean.class);
        methods = ReflectionUtils.getAllMethods(LinkedList.class, paramsPredicate, returnPredicate);
        methods.forEach(method -> System.out.println(method.getName()));
    
        System.out.println("---------------");
        //字段有注解Native
        Predicate<Field> annotationPredicate = ReflectionUtils.withAnnotation(Native.class);
        //字段类型是int及其子类
        Predicate<Field> typeAssignablePredicate = ReflectionUtils.withTypeAssignableTo(int.class);
        Set<Field> fields = ReflectionUtils.getAllFields(Integer.class, annotationPredicate, typeAssignablePredicate);
    //        Set<Field> fields = ReflectionUtils.getAllFields(Integer.class, annotationPredicate);
    //        Set<Field> fields = ReflectionUtils.getAllFields(Integer.class, typeAssignablePredicate);
        fields.forEach(field -> System.out.println(field.getName()));
    }
    

    Reflection框架还可以:

    • 获取某个类型的全部子类
    • 只要类型、构造器、方法,字段上带有特定注解,便能获取带有这个注解的全部信息(类型、构造器、方法,字段)
    • 获取所有能匹配某个正则表达式的资源
    • 获取所有带有特定签名的方法,包括参数,参数注解,返回类型
    • 获取所有方法的名字
    • 获取代码里所有字段、方法名、构造器的使用
    import com.coding.springboot.domain.Docker;
    import com.coding.springboot.domain.User;
    import com.google.common.base.Stopwatch;
    import org.junit.Test;
    import org.reflections.scanners.FieldAnnotationsScanner;
    import org.reflections.scanners.MethodAnnotationsScanner;
    import org.reflections.scanners.MethodParameterScanner;
    import org.reflections.scanners.ResourcesScanner;
    import org.reflections.util.ClasspathHelper;
    import org.reflections.util.ConfigurationBuilder;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.stereotype.Service;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import javax.persistence.Column;
    import javax.persistence.Id;
    import java.io.InputStream;
    import java.lang.reflect.*;
    import java.util.Collection;
    import java.util.List;
    import java.util.Set;
    import java.util.regex.Pattern;
    
    /**
     * @author micocube
     * projectName: utils4j
     * packageName: com.coding.reflect
     * email: ldscube@gmail.com
     * createTime: 2019-07-05 16:20
     * version: 0.1
     * description: reflection 框架
     *  Reflection依赖了谷歌的Guava包,出现此问题可能是因为缺少Guava或者包冲突。
     *  Reflections 0.9.11用的是Guava 20,Reflection 0.9.10用的是Guava 18,
     *  如果需要用Guava 18,则只能用Reflection 0.9.10版本。
     * <dependency>
     *     <groupId>org.reflections</groupId>
     *     <artifactId>reflections</artifactId>
     *     <version>0.9.11</version>
     * </dependency>
     *
     *
     * 1.获取某个类型的全部子类
     * 2.只要类型、构造器、方法,字段上带有特定注解,便能获取带有这个注解的全部信息(类型、构造器、方法,字段)
     * 3.获取所有能匹配某个正则表达式的资源
     * 4.获取所有带有特定签名的方法,包括参数,参数注解,返回类型
     * 5.获取所有方法的名字
     * 6.获取代码里所有字段、方法名、构造器的使用
     */
    public class Reflections {
    
        //获取所有Inputstream的子类,限定只扫包前缀为“java”的,也就是jdk自带的
        @Test
        public void testPackage(){
            org.reflections.Reflections  reflections = new org.reflections.Reflections("java.");
            Stopwatch stopwatch   = Stopwatch.createStarted();
            Set<Class<? extends InputStream>> allTypes    = reflections.getSubTypesOf(InputStream.class);
            System.out.println(stopwatch.toString());
            for (Class type : allTypes) {
                System.out.println("Found:"+type.getName());
            }
        }
    
    
        // com.coding 包下的所有带有service注解的类
        @Test
        public void testAnnotationType(){
            org.reflections.Reflections  reflections = new org.reflections.Reflections("com.coding");
            Stopwatch stopwatch   = Stopwatch.createStarted();
            Set<Class<?>> classes = reflections.getTypesAnnotatedWith(Service.class);
            System.out.println(stopwatch.toString());
            for (Class type : classes) {
                System.out.println("Found:"+type.getName());
            }
        }
    
    
        // 假如想扫描整个工程的类,直接new一个不带参数的Reflections就好。
        // 值得一提的是,这东西在扫描的时候,连依赖的jar包都不放过。以Spring框架的BeanFactory为例:
        @Test
        public void testSubType2(){
            org.reflections.Reflections reflections = new org.reflections.Reflections();
            Set<Class<? extends BeanFactory>> classes = reflections.getSubTypesOf(BeanFactory.class);
    
            for(Class clazz : classes) {
                //logger.info(clazz.getName());
                System.out.println("Found: " + clazz.getName());
            }
        }
    
    
        // 所有带RequestMapping注解的方法
        @Test
        public void testAnnotationMethod(){
            org.reflections.Reflections reflections = new org.reflections.Reflections(
                    new ConfigurationBuilder()
                            .setUrls(ClasspathHelper.forPackage("com.coding"))
                            .addScanners(new MethodAnnotationsScanner()));
    
            Set<Method> annotatedWith = reflections.getMethodsAnnotatedWith(RequestMapping.class);
    
            for(Method p : annotatedWith) {
                //logger.info(clazz.getName());
                System.out.println("Found: " + p.getName());
            }
        }
    
        // 所有properties文件
        @Test
        public void testResource(){
            org.reflections.Reflections reflections = new org.reflections.Reflections(
                    new ConfigurationBuilder()
                            .setUrls(ClasspathHelper.forPackage("com.coding"))
                            .addScanners(new ResourcesScanner()));
    
            Set<String> properties =
                    reflections.getResources(Pattern.compile(".*\\.properties"));
    
            for(String p : properties) {
                //logger.info(clazz.getName());
                System.out.println("Found: " + p);
            }
        }
    
        // 所有带Deprecated注解的构造方法
        @Test
        public void testAnnotationConstractor(){
            org.reflections.Reflections reflections = new org.reflections.Reflections(
                    new ConfigurationBuilder()
                            .setUrls(ClasspathHelper.forPackage("com.coding"))
                            .addScanners(new MethodAnnotationsScanner()));
    
            Set<Constructor> annotated = reflections.getConstructorsAnnotatedWith(Deprecated.class);
            for(Constructor p : annotated) {
                //logger.info(clazz.getName());
                System.out.println("Found: " + p.getName());
            }
        }
    
        // 所有带Id注解的构造方法
        @Test
        public void testAnnotationField(){
            org.reflections.Reflections reflections = new org.reflections.Reflections(
                    new ConfigurationBuilder()
                            .setUrls(ClasspathHelper.forPackage("com.coding"))
                            .addScanners(new FieldAnnotationsScanner()));
    
            Set<Field> annotated = reflections.getFieldsAnnotatedWith(Id.class);
            for(Field p : annotated) {
                //logger.info(clazz.getName());
                System.out.println("Found: " + p.getName());
            }
        }
    
        // MethodParameterScanner 方法参数扫描器
        @Test
        public void testMethodParameter(){
            org.reflections.Reflections reflections = new org.reflections.Reflections(
                    new ConfigurationBuilder()
                            .setUrls(ClasspathHelper.forPackage("com.coding"))
                            .addScanners(new MethodParameterScanner()));
    
            //MethodParameterScanner
            Set<Method> someMethods =
                    reflections.getMethodsMatchParams(String[].class);
            Set<Method> voidMethods =
                    reflections.getMethodsReturn(User.class);
            Set<Method> pathParamMethods =
                    reflections.getMethodsWithAnyParamAnnotated(PathVariable.class);
    
    
            for(Method p : someMethods) {
                //logger.info(clazz.getName());
                System.out.println("方法参数符合String[]的class:Found: " + p.getName());
            }
    
            for(Method p : voidMethods) {
                //logger.info(clazz.getName());
                System.out.println("返回值为User的方法:Found: " + p.getName());
            }
            for(Method p : pathParamMethods) {
                //logger.info(clazz.getName());
                System.out.println("参数带有PathVariable注解的方法:Found: " + p.getName());
            }
        }
    
    
        // 测试框架自带的工具类
        @Test
        public void testReflectionUtils(){
            // 所有get方法
            Set<Method> getters = org.reflections.ReflectionUtils.getAllMethods(User.class,
                    org.reflections.ReflectionUtils.withModifier(Modifier.PUBLIC),
                    org.reflections.ReflectionUtils.withPrefix("get"),
                    org.reflections.ReflectionUtils.withParametersCount(0));
    
            // 参数是Collection的子类,返回值是boolean
            Set<Method> listMethodsFromCollectionToBoolean =
                    org.reflections.ReflectionUtils.getAllMethods(List.class,
                            org.reflections.ReflectionUtils.withParametersAssignableTo(Collection.class),
                            org.reflections.ReflectionUtils.withReturnType(boolean.class));
    
            // field 带有Column注解,类型是String的子类
            Set<Field> fields = org.reflections.ReflectionUtils.getAllFields(Docker.class,
                    org.reflections.ReflectionUtils.withAnnotation(Column.class),
                    org.reflections.ReflectionUtils.withTypeAssignableTo(String.class));
    
            getters.forEach(get->System.out.println("getter:"+get));
            listMethodsFromCollectionToBoolean.forEach(get->System.out.println("listMethodsFromCollectionToBoolean:"+get));
            fields.forEach(get->System.out.println("fields:"+get));
        }
    }
    

    相关文章

      网友评论

        本文标题:Java Reflections

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