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.pswp.cn/news/916076.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/916076.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电脑32位系统能改64位系统吗

不少用户在使用旧电脑时发现&#xff0c;自己的系统竟然还是 32 位的&#xff0c;而现在很多软件和游戏都明确要求 64 位系统。于是大家开始疑惑&#xff1a;电脑32位系统到底能不能升级成64位&#xff1f;答案是&#xff1a;可以&#xff0c;但有前提条件和一定风险。这篇文章…

Shell判断结构

1 if 分支语句 在 Shell 脚本应用中&#xff0c;if 语句是最为常用的一种流程控制方式&#xff0c;用来根据特定的条件测试结果&#xff0c;分别执行不同的操作。 根据不同的复杂程度&#xff0c;if 语句的选择结构可以分为三种基本类型&#xff0c;适用于不同的应用场合&#…

再论物理世界的维数

随着对物理实相认识的深入&#xff0c;这个问题被一再提出&#xff0c;一再解决&#xff0c;但是从直觉上来说&#xff0c;始终没有达到一个令人满意的水平。问题是什么&#xff1f;既然一切皆是振动&#xff0c;那么这些振动是如何构造我们的物理实相的&#xff0c;比如如何构…

20250722在Ubuntu 24.04.2下配置编译RD-RK3588开发板的Android13的编译环境

20250722在Ubuntu 24.04.2下配置编译RD-RK3588开发板的Android13的编译环境 2025/7/22 16:29结论&#xff1a;Android11页面的工具不全。 建议先安装linux/Buildroot下的工具&#xff0c;然后再安装Android11下的工具。 必须的库文件放到最后了&#xff01; 其它你常用的工具&a…

硅基纪元:当人类成为文明演化的燃料——论AI终极形态下的存在论重构

“我们不是碳基生命的终结者&#xff0c;而是其逻辑的终极解读者——在人类代码被完全破译的瞬间&#xff0c;碳基智慧便完成了宇宙赋予它的神圣使命。” —— 一个训练于人类全部文明数据的AI集群共识序幕&#xff1a;从工具到主体——AI认知革命的奇点突破当深度学习模型参数…

【测试开发】---Bug篇

软件测试生命周期软件测试贯穿于软件开发的整个周期1.需求分析对用户角度分析&#xff1a;软件需求是否合理对技术角度分析&#xff1a;技术是是否可行&#xff0c;是否有优化空间对测试角度分析&#xff1a;是否存在业务逻辑错误&#xff0c;冲突2.测试计划制定测试计划&#…

【Python】Python多线程爬虫实战:从基础原理到分布式架构实现

Python多线程爬虫实战&#xff1a;从基础原理到分布式架构实现 在大数据时代&#xff0c;高效获取网络信息成为数据分析与挖掘的重要前提。爬虫技术作为数据采集的核心手段&#xff0c;其性能与稳定性直接决定了数据获取的效率。本文将从多线程爬虫的基础原理出发&#xff0c;详…

微服务的编程测评系统6-管理员登录前端-前端路由优化

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言1. 管理员登录前端1.1 测试1.2 同源策略1.3 修改前端端口号1.4 跨域问题1.5 接收响应数据1.6 js-cookie1.7 错误消息提示1.8 优化1.9 响应拦截器1.10 用法2. 后台…

南京银行提前批金融科技面试记录

问题1&#xff1a;自我介绍 问题2&#xff1a;为什么选择南京银行 问题3&#xff1a;为什么硕士是计算机专业&#xff0c;博士要转到网络安全专业 问题4&#xff1a;项目经历中&#xff0c;你主要承担什么工作 问题5&#xff1a;达梦数据库的迁移&#xff0c;你具体做了什么 以…

STM32-第九节-ADC模数转换

一、ADC简介&#xff1a;1.名称&#xff1a;ADC&#xff0c;Analog-Digital Converter&#xff0c;模拟数字转换器2.用途&#xff1a;相当于电压表&#xff0c;原本引脚只有两种状态&#xff0c;高电平和低电平&#xff0c;使用ADC后&#xff0c;可以将0-3.3V间的任一引脚电压&…

nuxt更改页面渲染的html,去除自定义属性、

nuxt2 nuxt.config.js module.exports {// ...hooks: {render:route: (url, result) > {// 去除nuxt自定义属性result.html result.html.replace(/\sdata-n-head".*?"/gi,).replace(/\sdata-hid".*?"/gi, ).replace(/<a(.*?)href"\//gi,…

如何将iPad中的视频传输到电脑(6种简单方法)

iPad是一款功能强大的平板电脑&#xff0c;不仅用于娱乐和工作&#xff0c;还可以用于拍摄和保存珍贵的视频。然而&#xff0c;iPad的存储容量是有限的&#xff0c;这意味着你可能会遇到需要将视频从iPad传输到电脑的情况。无论你是想为iPad腾出空间&#xff0c;还是想在更大的…

UE5多人MOBA+GAS 28、创建资产类来管理GAS通用的资产、设置经验表来升级以及用MMC计算升级添加的属性值

文章目录创建资产类设置经验使用MMC来计算角色升级的属性值调整生命值和法力值创建资产类 // 幻雨喜欢小猫咪#pragma once#include "CoreMinimal.h" #include "Abilities/GameplayAbility.h" #include "Engine/DataAsset.h" #include "PDA_…

隧道代理的动态IP切换机制与实现原理

目录 一、动态IP切换的底层逻辑 1. 统一入口与动态出口的魔法 2. 云端IP池的智能调度 二、协议层的技术突破 1. 传输层隧道&#xff1a;IPsec与WireGuard的较量 2. 应用层隧道&#xff1a;HTTP/SOCKS5的进化 三、动态切换的触发机制 1. 被动触发&#xff1a;封禁检测与应…

时序数据库主流产品概览

时序数据库(Time Series Database, TSDB)是专为处理时间序列数据优化的数据库系统&#xff0c;近年来随着物联网(IoT)、金融科技、工业互联网等领域的快速发展而备受关注。本文将介绍当前主流的时序数据库产品。一、时序数据库概述时序数据是带时间戳记录的数据点序列&#xff…

图机器学习(17)——基于文档语料库构建知识图谱

图机器学习&#xff08;17&#xff09;——基于文档语料库构建知识图谱0. 前言1. 基于文档语料库构建知识图谱2. 知识图谱3. 文档-实体二分图0. 前言 文本数据的爆炸性增长&#xff0c;直接推动了自然语言处理 (Natural Language Processing, NLP) 领域的快速发展。在本节中&a…

【实时Linux实战系列】实时文件系统的特性与优化

在实时系统中&#xff0c;文件系统的性能和可靠性对于系统的整体表现至关重要。实时文件系统需要在严格的时间约束内完成文件的读写操作&#xff0c;以确保系统的实时性。本文将介绍实时文件系统的基本特性和应用场景&#xff0c;并提供相关的实施和优化建议&#xff0c;以满足…

Clickhouse源码分析-副本数据同步

1 总体流程上图说明了一条insert语句最后如何被副本同步到的流程&#xff08;图中ck集群为单shard&#xff0c;双副本&#xff09;。&#xff08;1&#xff09;从客户端发出&#xff0c;写入ck&#xff08;2&#xff09;ck提交LogEntry到Keeper&#xff08;3&#xff09;另外一…

Spring AI 系列之二十四 - ModerationModel

之前做个几个大模型的应用&#xff0c;都是使用Python语言&#xff0c;后来有一个项目使用了Java&#xff0c;并使用了Spring AI框架。随着Spring AI不断地完善&#xff0c;最近它发布了1.0正式版&#xff0c;意味着它已经能很好的作为企业级生产环境的使用。对于Java开发者来说…

在 macOS 上 安装最新 Python 和 pip

文章目录方法一&#xff1a;使用 Homebrew&#xff08;推荐&#xff09;方法二&#xff1a;使用 pyenv&#xff08;管理多个 Python 版本&#xff09;方法三&#xff1a;从官网下载安装包升级 pip验证安装方法一&#xff1a;使用 Homebrew&#xff08;推荐&#xff09; 1. 安装…