当前位置: 首页 > news >正文

reflections:Java非常好用的反射工具包

文章目录

  • 一、写在前面
  • 二、使用

一、写在前面

开源地址:https://github.com/ronmamo/reflections

目前项目已经出于不活跃状态,JDK8还是支持的,但是JDK11以上就会有问题。

Reflections 会扫描并索引您项目类路径的元数据,允许在运行时反向传递查询类型系统。

核心功能
扫描预定义的URLs: Reflections可以扫描项目的类路径、特定的目录或者JAR文件,来查找特定的类型或者带有特定注解的元素。
查询元数据信息: 一旦扫描完成,Reflections允许你查询这些元数据信息,例如获取所有带有特定注解的类或者方法。
索引化视图: Reflections创建了一个索引化的视图,用于在运行时快速访问扫描结果。
支持多种扫描器: Reflections支持多种扫描器,包括类扫描器、字段扫描器、方法扫描器等,每种扫描器都可以用来查找特定的元素。

在使用 Java 的 Reflections 库扫描类时,默认情况下会加载类
这是因为 Reflections 库的工作原理是基于类路径扫描,它需要读取类的字节码信息来分析类的结构、继承关系、注解等元数据。当它找到符合条件的类时,会通过类加载器将类加载到 JVM 中,以便获取完整的类信息(如 Class 对象)。
类加载的过程会触发类的静态初始化块(static {})执行,这一点需要特别注意。
大量类被加载可能增加 JVM 内存占用,尤其在扫描范围过大时

性能考虑:避免在频繁执行的路径上使用Reflections,因为初始化可能比较耗时。
使用缓存:对于不变的查询结果,利用Reflections提供的缓存机制来提高性能。

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

二、使用


import org.reflections.ReflectionUtils;
import org.reflections.Reflections;
import org.reflections.scanners.FieldAnnotationsScanner;
import org.reflections.scanners.MethodAnnotationsScanner;
import org.reflections.scanners.MethodParameterScanner;
import org.reflections.scanners.TypeAnnotationsScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.FilterBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RestController;import javax.websocket.server.PathParam;
import java.lang.annotation.Native;
import java.lang.reflect.*;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.regex.Pattern;public class Test {public static void main(String[] args) throws Exception {// 指定包名Reflections reflections = new Reflections("com.demo");//  1、获取所有被 @RestController 注解的类Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(RestController.class);// 如果是嵌套注解,是无法获取的Set<Class<?>> annotated2 = reflections.getTypesAnnotatedWith(Controller.class);System.out.println(annotated);System.out.println(annotated2);/*** 2、创建Reflections实例: Reflections类的实例化是通过一个配置对象ConfigurationBuilder进行的。** 配置输入过滤器:* .filterInputsBy(new FilterBuilder().includePackage(INIT_PATH))* 这行设置了输入过滤器,它决定了哪些类会被扫描。这里使用了FilterBuilder来包含一个特定的包路径INIT_PATH。** 设置URLs:* .setUrls(ClasspathHelper.forPackage(INIT_PATH))* 这行代码设置了Reflections扫描的URLs。ClasspathHelper.forPackage是通过包路径查找类路径URLs的实用方法。它会搜索与INIT_PATH包相关的所有URLs,并将它们提供给Reflections库,以便扫描。** 添加扫描器:* new TypeAnnotationsScanner():扫描所有带注解的类型(类、接口等)。* new MethodParameterScanner():扫描所有方法的参数。* new MethodAnnotationsScanner():扫描所有带注解的方法。* new FieldAnnotationsScanner():扫描所有带注解的字段。* 这些扫描器指定了Reflections需要收集哪些元数据。** 整个代码块的目的是配置Reflections实例以搜索和索引特定包"com.demo"中的类、方法、参数和字段的注解信息,* 以便可以快速访问这些元数据而不必逐个类地使用Java反射API。*/final Reflections reflections2 = new Reflections(new ConfigurationBuilder().filterInputsBy(new FilterBuilder().includePackage("com.demo")).setUrls(ClasspathHelper.forPackage("com.demo")).addScanners(new TypeAnnotationsScanner(),new MethodParameterScanner(),new MethodAnnotationsScanner(),new FieldAnnotationsScanner()));// 3、得到某接口下的所有实现类,子类Set<Class<? extends BeanPostProcessor>> implClassSet=reflections.getSubTypesOf(BeanPostProcessor.class);for (Class<? extends BeanPostProcessor> aClass : implClassSet) {BeanPostProcessor beanPostProcessor = aClass.newInstance();// 。。。}// 4、ResourcesScanner 扫描资源Set<String> properties =reflections.getResources(Pattern.compile(".*\\.properties"));// 5、 扫描方法、构造注解//MethodAnnotationsScannerSet<Method> resources =reflections.getMethodsAnnotatedWith(Value.class);Set<Constructor> injectables =reflections.getConstructorsAnnotatedWith(Autowired.class);// 字段注解Set<Field> ids =reflections.getFieldsAnnotatedWith(Autowired.class);// 6、扫描方法参数//MethodParameterScannerSet<Method> someMethods =reflections.getMethodsWithSignature(long.class, int.class);Set<Method> voidMethods =reflections.getMethodsReturn(void.class);Set<Method> pathParamMethods =reflections.getMethodsAnnotatedWith(PathParam.class);List<String> parameterNames =reflections.getMemberParameterNames(method);//MemberUsageScanner 方法调用情况Set<Member> usages =reflections.getMemberUsage(class);}/*** 工具类的使用*/public void reflectionUtils(){//必须是public方法Predicate<Method> publicPredicate = ReflectionUtils.withModifier(Modifier.PUBLIC);//有get前缀Predicate<Method> getPredicate = ReflectionUtils.withPrefix("get");//参数个数为0Predicate<Member> paramPredicate = ReflectionUtils.withParametersCount(0);Set<Method> methods = ReflectionUtils.getAllMethods(LinkedList.class, publicPredicate, getPredicate, paramPredicate);methods.forEach(method -> System.out.println(method.getName()));// 根据方法的可见性,前缀名,入参个数,获取某个类的对应方法Set<Method> getters = ReflectionUtils.getAllMethods(User.class,ReflectionUtils.withModifier(Modifier.PUBLIC), ReflectionUtils.withPrefix("set"), ReflectionUtils.withParametersCount(1));//获取List的方法:入参为Collection,返回值为booleanSet<Method> methods2 = ReflectionUtils.getAllMethods(List.class,ReflectionUtils.withParametersAssignableTo(Collection.class),ReflectionUtils.withReturnType(boolean.class));//该方法可以传入一些参数,比如过滤出带注解的参数:withAnnotation(NonNull.class)Set<Field> fields2 = ReflectionUtils.getAllFields(Animal.class, ReflectionUtils.withTypeAssignableTo(String.class));System.out.println("---------------");//参数必须是Collection及其子类Predicate<Member> paramsPredicate = ReflectionUtils.withParametersAssignableTo(Collection.class);//返回类型是booleanPredicate<Method> returnPredicate = ReflectionUtils.withReturnType(boolean.class);methods = ReflectionUtils.getAllMethods(LinkedList.class, paramsPredicate, returnPredicate);methods.forEach(method -> System.out.println(method.getName()));System.out.println("---------------");//字段有注解NativePredicate<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()));}
}

http://www.lryc.cn/news/599944.html

相关文章:

  • 【linux】Haproxy七层代理
  • 如何理解泊松分布
  • 在 IntelliJ IDEA 中打开这个用于设置 Git 用户名(Name)和邮箱(Email)的特定弹窗
  • JAVA知识点(三):Spring与ORM框架
  • 【RDMA】Adapters PRM Mellanox Adapters Programmer’s Reference mellanox网卡编程手册0.52
  • Linux库——库的制作和原理(1)_回顾动静态库、制作使用库
  • 上位机程序开发基础介绍
  • OpenCV结合深度学习进行图像分类
  • 练习实践-基础设施-文件共享-windows和linux之间的文件共享-smb服务搭建
  • 解决angular与jetty websocket 每30s自动断连的问题
  • 从kHz到GHz:晶振频率范围如何决定其应用场景
  • streamyfin(世博会)android 编译
  • 告别虚函数性能焦虑:深入剖析C++多态的现代设计模式
  • 萤石云替代产品摄像头方案萤石云不支持TCP本地连接-东方仙盟
  • 蓝光中的愧疚
  • Nacos-服务注册,服务发现(一)
  • 中级统计师-经济学基础知识-第七章 失业与通货膨胀理论
  • 怎么放大单片机输出电流
  • linux C — udp,tcp通信
  • 【硬件】LT3763中文手册
  • 51 单片机单文件多文件结构工程模板的创建教程
  • Nginx 安全加固:如何阻止 IP 直接访问,只允许域名访问
  • Linux网络配置全攻略:IP、路由与双机通信
  • freqtrade关于获取k线数量,以及显示时间的问题
  • JAVA知识点(六):性能调优与线上问题排查
  • Day 3: 机器学习进阶算法与集成学习
  • 【13】C# 窗体应用WinForm——.NET Framework、WinForm、工程创建、工具箱简介、窗体属性及创建
  • [ComfyUI] -入门2- 小白零基础搭建ComfyUI图像生成环境教程
  • 语义分割-FCN-听课记录
  • vue使用xlsx库导出excel