文档章节

教你如何使用反射框架reflections

cjavaer
 cjavaer
发布于 2017/08/30 15:59
字数 1069
阅读 2324
收藏 0

笔者今天要推荐一款Java的第三方的反射工具,很多开源的软件都在使用。

pom依赖:

    <dependency>
      <groupId>org.reflections</groupId>
      <artifactId>reflections</artifactId>
      <version>0.9.9-RC1</version>
    </dependency>

一、常用的类

1、ClasspathHelper

通过上面的测试代码可以看出ClasspathHelper这个类提供的上面的三个方法是获取资源的路径。

 

2、Reflections

public class Test01 {

    private static String packNameList = "com.jeff.reflection.bean,"+

                                                                  +"com.jeff.reflection.test,com.jeff.anotation";
    
    public static void main(String[] args) {
        FilterBuilder filterBuilder = new FilterBuilder();

        for (String packName : packNameList.split(",")) {
            filterBuilder = filterBuilder.includePackage(packName);//定义要扫描的包
        }
        Predicate<String> filter = filterBuilder;//过滤器

        //里面放的是这些包所在的资源路径
        Collection<URL> urlTotals = new ArrayList<URL>();
        for (String packName : packNameList.split(",")) {
            Set<URL> urls = ClasspathHelper.forPackage(packName);
            urlTotals.addAll(urls);
        }

        /**
         * 定义Reflections对象,指明"包过滤器",以及扫描器的类型,主要把是扫描器的类型
         * 细分之后,得到对应的数据
         */
        Reflections reflections = new Reflections(new ConfigurationBuilder()

                .filterInputsBy(filter)
                .setScanners(

                        new SubTypesScanner().filterResultsBy(filter),
                        new TypeAnnotationsScanner().filterResultsBy(filter),
                        new FieldAnnotationsScanner().filterResultsBy(filter),
                        new MethodAnnotationsScanner().filterResultsBy(filter),
                        new MethodParameterScanner().filterResultsBy(filter)

                ).setUrls(urlTotals));
        
        //获取方法上待MyAnotation注解的所有的方法
        Set<Method> methods = reflections.getMethodsAnnotatedWith(MyAnotation.class);
        for(Method m : methods){
            System.out.println(m.getName());
        }
    }
}

注意:从上面的代码可以看出,我们在使用的时候要先定义过滤器,把你要扫描的包加入。然后获取这个资源路径。最后定义reflections对象,然后拿reflections获取对应的Method、Field等等对象。

二、封装工具

1、在配置中定义扫描类包

2、SacnUtils类

public class ScanUtils {

    private static final String  SPLIT_STR = ",";//通过","切割包
    
    private static Properties pro = null;
    
    private static Reflections reflections = null;
    
    static{
        InputStream in = ScanUtils.class.getClassLoader()

                                    .getResourceAsStream("reflection.properties");
        pro = new Properties();
        try {
            pro.load(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 初始化
     * @return
     */
    public static Reflections init(){
        //定义过滤器集合
        FilterBuilder filterBuilder = new FilterBuilder();
        Collection<URL> urlTotals = new ArrayList<URL>();
        //初始化过滤器集合
        initPackage(filterBuilder,urlTotals);
        Predicate<String> filter = filterBuilder;
        
        reflections = new Reflections(new ConfigurationBuilder().filterInputsBy(filter)
                .setScanners(new SubTypesScanner().filterResultsBy(filter),
                        new TypeAnnotationsScanner()
                                .filterResultsBy(filter),
                        new FieldAnnotationsScanner()
                                .filterResultsBy(filter),
                        new MethodAnnotationsScanner()
                                .filterResultsBy(filter),
                        new MethodParameterScanner().filterResultsBy(filter)).setUrls(urlTotals));
        
        return reflections;
    }
    
    /**
     * 获取Reflections对象
     * @return
     */
    public static Reflections getReflections() {
        return reflections;
    }
    
    /**
     * 初始化配置文件的包 reflection.properties
     * @param filterBuilder
     */
    private static void initPackage(FilterBuilder filterBuilder,Collection<URL> urlTotals){
        
        String includePackage = pro.getProperty("includePackage");
        if(StringUtils.isNotEmpty(includePackage)){
            for (String packName : includePackage.split(SPLIT_STR)) {
                filterBuilder = filterBuilder.includePackage(packName);
                
                /**
                 * 通过ClasspathHelper(ClassLoader)类加载去去加载该包路径下的所有资源(URL),
                 * 最终通过URL资源(类、方法,注解,修饰符等等), 结合Filter可以得到Reflections
                 * 对象。
                 */
                Set<URL> urls = ClasspathHelper.forPackage(packName);
                urlTotals.addAll(urls);
            }
        }
        String includeRegex = pro.getProperty("includeRegex");
        if(StringUtils.isNotEmpty(includeRegex)){
            for (String packName : includeRegex.split(SPLIT_STR)) {
                filterBuilder = filterBuilder.include(packName);
                
                Set<URL> urls = ClasspathHelper.forPackage(packName);
                urlTotals.addAll(urls);
            }
        }
        
        String excludePackage = pro.getProperty("excludePackage");
        if(StringUtils.isNotEmpty(excludePackage)){
            for (String packName : excludePackage.split(SPLIT_STR)) {
                filterBuilder = filterBuilder.excludePackage(packName);
                
                Set<URL> urls = ClasspathHelper.forPackage(packName);
                urlTotals.addAll(urls);
            }
        }
        
        String excludeRegex = pro.getProperty("excludeRegex");
        if(StringUtils.isNotEmpty(excludeRegex)){
            for (String packName : excludeRegex.split(SPLIT_STR)) {
                filterBuilder = filterBuilder.includePackage(packName);
                
                Set<URL> urls = ClasspathHelper.forPackage(packName);
                urlTotals.addAll(urls);
            }
        }
    }
}

3、测试类路径的资源

public class Test02 {

    @SuppressWarnings("rawtypes")
    public static void main(String[] args) {
        Reflections reflections = ScanUtils.init();
        /**
         * 注意要获取拥有某个注解的方法,注意这个注解所在的包一定要配置到我们的includePackage
         * 或者includeRegex下,否则获取不到对应的方法
         */
        Set<Method> methods = reflections.getMethodsAnnotatedWith(MyAnotation.class);
        for(Method m : methods){
               System.out.println(m.getName());
        }
        /**
         *获取Object的子类,注意:Object这个类或者它的包,要配置在includePackage下,
         *另外得到的结果也一定是在“配置包”路径下面的类:includePackage=com.jeff.reflection.bean,
         *com.jeff.reflection.test,com.jeff.anotation,java.lang.Object
         */
        Set sub = reflections.getSubTypesOf(Object.class);
        System.out.println(sub);
        
        /**
         * 得到String为返回值的所有方法
         */
        methods = reflections.getMethodsReturn(String.class);
        for(Method m : methods){
               System.out.println(m.getName());
        }
        
        /**
         * 获取构造方法中参数带ParamAnotation.class注解的所有构造方法
         */
        Set<Constructor> cons = reflections.

                            getConstructorsWithAnyParamAnnotated(ParamAnotation.class);
        for(Constructor c : cons){
            System.out.println(c.getModifiers() + "," + c.getName());//1,com.jeff.reflection.bean.User
        }
        
        /**
         * 获取该注解上面的修饰的注解类型(该注解一定是在我们配置的包路径下)
         * 由于@Documented注解不在我们配置的包路径下,下面的方法获取不了它的
         * 注解
         * @Documented
         * @ParamAnotation(name="")
         * public @interface MyAnotation {
         * }
         */
        Set anot = reflections.getTypesAnnotatedWith(ParamAnotation.class,true);
        System.out.println(anot);//[interface com.jeff.anotation.MyAnotation]
        
        /**
         * 获取资源:从reflections晒选出符合条件(正则)的资源,所以在includePackage
         * 配置这个下面资源的路径,要不筛选不出来。(查看Test03.java)
         */
        Set<String> res = reflections.getResources(Pattern.compile(".*\\.properties"));
        for(Iterator<String> ite = res.iterator();ite.hasNext();){
            String str = ite.next();
            System.out.println(str);
        }
    }
}

 

4、获取资源

     /**
     * 首先要通过过滤器指定包/类/文件资源,因为ClassLoader要依靠指定的过滤器去找出
     * 符合条件的资源。然后通过api:reflections.getResources(regex)找出符合条件
     * 的资源。
     */
    public static void main(String[] args) {
        Predicate<String> filter = new FilterBuilder().include(".*\\.properties")

                                                                    .exclude(".*testModel-reflections\\.xml");
        Reflections reflections = new Reflections(new ConfigurationBuilder()
                .filterInputsBy(filter)
                .setScanners(new ResourcesScanner())
                .setUrls(ClasspathHelper.forPackage("com.jeff.")));
        
        Set<String> str = reflections.getResources(Pattern.compile(".*\\.properties"));
        for(String s : str){
            System.out.println(s);
        }
    }

© 著作权归作者所有

cjavaer
粉丝 0
博文 38
码字总数 15232
作品 0
朝阳
程序员
私信 提问
前期知识准备

由于现在大多数已经不使用xml配置,基本是基于注解实现,因此,此处不考虑xml文件的相关操作(读取,校验等) 1.spring的自动扫描注册功能, 可采用类库 org.reflections,可大大降低反射的操...

chenbaojun
2018/02/26
1
0
java 非常好用的反射框架Reflections

Reflections通过扫描classpath,索引元数据,并且允许在运行时查询这些元数据。 使用Reflections可以很轻松的获取以下元数据信息: 1)获取某个类型的所有子类;比如,有一个父类是TestInter...

孟飞阳
02/21
54
0
【Unity3D技术文档翻译】第3.6.7.3篇 反射探针高级特性

上一章:【Unity3D技术文档翻译】第3.6.7.2篇 使用反射探针 本章原文所在章节:【Unity Manual】→【Graphics】→【Graphics Overview】→【Lighting】→【Global Illumination】→【Reflect...

何三思
2018/08/31
0
0
Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (上)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lmj623565791/article/details/39269193 转载请标明出处:http://blog.csdn.net/lmj623565791/article/detai...

鸿洋_
2014/09/18
0
0
SpringBoot27 JDK动态代理详解、获取指定的类类型、动态注册Bean、接口调用框架

1 JDK动态代理详解   静态代理、JDK动态代理、Cglib动态代理的简单实现方式和区别请参见我的另外一篇博文。   1.1 JDK代理的基本步骤     》通过实现InvocationHandler接口来自定义自...

CRUD_Architect
2018/08/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

java通过ServerSocket与Socket实现通信

首先说一下ServerSocket与Socket. 1.ServerSocket ServerSocket是用来监听客户端Socket连接的类,如果没有连接会一直处于等待状态. ServetSocket有三个构造方法: (1) ServerSocket(int port);...

Blueeeeeee
今天
6
0
用 Sphinx 搭建博客时,如何自定义插件?

之前有不少同学看过我的个人博客(http://python-online.cn),也根据我写的教程完成了自己个人站点的搭建。 点此:使用 Python 30分钟 教你快速搭建一个博客 为防有的同学不清楚 Sphinx ,这...

王炳明
昨天
5
0
黑客之道-40本书籍助你快速入门黑客技术免费下载

场景 黑客是一个中文词语,皆源自英文hacker,随着灰鸽子的出现,灰鸽子成为了很多假借黑客名义控制他人电脑的黑客技术,于是出现了“骇客”与"黑客"分家。2012年电影频道节目中心出品的电影...

badaoliumang
昨天
15
0
很遗憾,没有一篇文章能讲清楚线程的生命周期!

(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本。 简介 大家都知道线程是有生命周期,但是彤哥可以认真负责地告诉你网上几乎没有一篇文章讲得是完全正确的。 ...

彤哥读源码
昨天
15
0
jquery--DOM操作基础

本文转载于:专业的前端网站➭jquery--DOM操作基础 元素的访问 元素属性操作 获取:attr(name);$("#my").attr("src"); 设置:attr(name,value);$("#myImg").attr("src","images/1.jpg"); ......

前端老手
昨天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部