1.背景

给一个Java的包名,获取包名下的所有类..

根据类上的注解,可以展开很多统一操作的业务

2.直接看代码-spring环境下

package com.qxnw.digit.scm.common.config.mq.supplier;

import com.qxnw.digit.scm.common.config.mq.MqRegister;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils; import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set; /**
* @Copyright (C) XXXXX技有限公司
* @Author: ldp
* @Date: 2023/4/19 10:41
* @Description:
*/
@Slf4j
public class MqSupplierConstHelp {
private final static String RESOURCE_PATTERN = "/**/*.class"; /**
* 获取当前包路径下的供应商队列
*
* @return
* @throws Exception
*/
public Set<String> getSupplierQueueList() throws Exception {
String basePackageName = this.getClass().getPackage().getName();
log.info("basePackageName=" + basePackageName);
// 获取到class字节码集合
List<Class<?>> classList = getClassList(basePackageName);
// 获取到带有注解的字段值
Set<String> fieldQueueNameList = getFieldQueueName(classList);
return fieldQueueNameList;
} /**
* 通过包名获取项目包下所有类
*
* @param BASE_PACKAGE 包名
* @return
*/
public static List<Class<?>> getClassList(String BASE_PACKAGE) {
List<Class<?>> classes = new ArrayList<>();
//spring工具类,可以获取指定路径下的全部类
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
try {
String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
ClassUtils.convertClassNameToResourcePath(BASE_PACKAGE) + RESOURCE_PATTERN;
Resource[] resources = resourcePatternResolver.getResources(pattern);
//MetadataReader 的工厂类
MetadataReaderFactory readerfactory = new CachingMetadataReaderFactory(resourcePatternResolver);
for (Resource resource : resources) {
//用于读取类信息
MetadataReader reader = readerfactory.getMetadataReader(resource);
//扫描到的class
String classname = reader.getClassMetadata().getClassName();
log.info("classname={}", classname);
Class<?> clazz = Class.forName(classname);
classes.add(clazz);
}
} catch (Exception e) {
log.error("获取class异常:", e);
}
return classes;
} /**
* 根据字节码,获取带有注解的常量对象的字段值
*
* @param classList
* @return
* @throws Exception
*/
private Set<String> getFieldQueueName(List<Class<?>> classList) throws Exception {
Set<String> set = new HashSet();
for (Class<?> aClass : classList) {
MqRegister mqRegister = aClass.getAnnotation(MqRegister.class);
if (mqRegister == null) {
continue;
}
log.info("可以注册的常量对象:{}", aClass.getName());
Object mqConst = aClass.newInstance();
// 可以注册
Field[] fields = aClass.getFields();
for (Field field : fields) {
String fieldName = field.getName();
String queueName = field.get(mqConst).toString();
log.info("可以注册的字段名称:" + fieldName + ",字段值:" + queueName);
set.add(queueName);
}
}
return set;
}
}

3.直接看代码-非sping环境

package com.common.config.mq.supplier;

import com.common.config.mq.MqRegister;
import lombok.extern.slf4j.Slf4j; import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLDecoder;
import java.util.*; /**
* @Copyright (C) XXXXX技有限公司
* @Author: ldp
* @Date: 2023/4/19 10:41
* @Description:
*/
@Slf4j
public class MqSupplierConstHelp { /**
* 获取当前包路径下的队列
*
* @return
* @throws Exception
*/
public Set<String> getSupplierQueueList() throws Exception {
String basePackageName = this.getClass().getPackage().getName();
log.info("basePackageName=" + basePackageName);
// 获取包的磁盘路径
String dirPath = getDirPath(basePackageName);
// 获取磁盘路径下的Java对象
List<String> classNameList = getClassNameList(dirPath);
log.info("classNameList" + classNameList);
// 获取到class字节码集合
List<Class<?>> classList = getClassList(classNameList, basePackageName);
// 获取到带有注解的字段值
Set<String> fieldQueueNameList = getFieldQueueName(classList);
return fieldQueueNameList;
} /**
* 根据包名获取磁盘路径
*
* @param basePackageName
* @return
* @throws Exception
*/
private String getDirPath(String basePackageName) throws Exception {
String path = basePackageName.replace(".", "\\");
ClassLoader loader = ClassLoader.getSystemClassLoader();
//获取编译后的class文件夹路径dirPath
Enumeration<URL> enums = loader.getResources(path);
String dirPath = "";
while (enums.hasMoreElements()) {
URL url = enums.nextElement();
if (url != null) {
String protool = url.getProtocol();
if ("file".equals(protool)) {
dirPath = url.getPath();
dirPath = URLDecoder.decode(dirPath, "utf-8");
log.info("dirPath=" + dirPath);
}
}
}
return dirPath;
} /**
* 获取磁盘路径下的Java对象
*
* @param dirPath
* @return
*/
private List<String> getClassNameList(String dirPath) {
List<String> classNameList = new ArrayList<>();
//根据传入文件夹路径创建File对象
File dir = new File(dirPath);
//检查是否为文件夹
if (dir.isDirectory()) {
//遍历文件夹内的文件
for (File f : dir.listFiles()) {
//获取文件名,并删除后缀 xxx.class
String fileName = f.getName();
String[] split = fileName.split("\\.");
if (split.length != 2) {
continue;
}
if (!split[1].equals("class")) {
continue;
}
fileName = fileName.substring(0, fileName.lastIndexOf("."));
//添加到结果中
classNameList.add(fileName);
}
}
return classNameList;
} /**
* 拼接class全路径
*
* @param classNames
* @param basePackageName
* @return
*/
private List<Class<?>> getClassList(List<String> classNames, String basePackageName) {
//将获取到的包内文件名转换为反射对象
List<Class<?>> classes = new ArrayList<>();
for (String className : classNames) {
try {
classes.add(Class.forName(basePackageName + "." + className));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return classes;
} /**
* 根据字节码,获取带有注解的常量对象的字段值
*
* @param classList
* @return
* @throws Exception
*/
private Set<String> getFieldQueueName(List<Class<?>> classList) throws Exception {
Set<String> set = new HashSet();
for (Class<?> aClass : classList) {
MqRegister mqRegister = aClass.getAnnotation(MqRegister.class);
if (mqRegister == null) {
continue;
}
log.info("可以注册的常量对象:{}", aClass.getName());
Object mqConst = aClass.newInstance();
// 可以注册
Field[] fields = aClass.getFields();
for (Field field : fields) {
String fieldName = field.getName();
String queueName = field.get(mqConst).toString();
log.info("可以注册的字段名称:" + fieldName + ",字段值:" + queueName);
set.add(queueName);
}
}
return set;
}
}

完美!

java获取包下所有的类的更多相关文章

  1. 【第二周】关于java.util包下的Random类

    1.功能:此类的实例用于生成伪随机数流 2.方法(Random的方法有很多,在此只解释说明我认为比较常用的几个方法) (1)next(int bits):生成下一个伪随机数 (2)nextDouble ...

  2. java.io 包下的类有哪些 + 面试题

    java.io 包下的类有哪些 + 面试题 IO 介绍 IO 是 Input/Output 的缩写,它是基于流模型实现的,比如操作文件时使用输入流和输出流来写入和读取文件等. IO 分类 传统的 IO ...

  3. java工具类 获取包下所有类

    extends:http://blog.csdn.net/jdzms23/article/details/17550119 package com.threeti.util; import java. ...

  4. Java 获取指定包下的所有类

    package com.s.rest.util; import java.io.File; import java.io.FileFilter; import java.io.IOException; ...

  5. Java反射1——扫描某个包下的所有类

    1.从包package中获取所有的Class /** * 从包package中获取所有的Class * * @param pack * @return */ public static Set< ...

  6. Java 扫描包下所有类(包括jar包)

    package com.MyUtils.file; [java] view plain copy import java.io.File; import java.io.FileFilter; imp ...

  7. java.util.regex包下的Pattern类和Matcher类的使用总结

    一.介绍 Java正则表达式通过java.util.regex包下的Pattern类与Matcher类实现1.Pattern类用于创建一个正则表达式,也可以说创建一个匹配模式,它的构造方法是私有的,不 ...

  8. List,Set,Map在java.util包下都是接口 List有两个实现类:ArrayList和LinkedList Set有两个实现类:HashSet和LinkedHashSet AbstractSet实现了Set

    List,Set,Map在java.util包下都是接口 List有两个实现类:ArrayList和LinkedListSet有两个实现类:HashSet和LinkedHashSetAbstractS ...

  9. java 获取classpath下文件多种方式

    java 获取classpath下文件多种方式 一:properties下配置 在resources下定义server.properties register.jks.path=classpath\: ...

  10. spring java 获取webapp下文件路径

    spring java 获取webapp下文件路径 @RequestMapping("/act/worldcup_schedule_time/imgdownload") @Resp ...

随机推荐

  1. sql去重常用的基本方法

    1.存在两条完全相同的纪录 select distinct * from table(表名) where (条件)   2.存在部分字段相同的纪录(有主键id即唯一键) 如果是这种情况的话用disti ...

  2. Future集合会等线程池执行完才开始遍历吗?

    先说结论:Future集合并不是等线程池执行完才开始遍历,而是线程池内的线程执行完一条Future集合就立即遍历一条 在使用线程池的业务场景下,我们经常需要获取线程执行的返回值,此时我们需要Calla ...

  3. 查看es结构,es _search查询基础语法

    查看es结构,es _search查询基础语法 http://xx.xx.xx.xx:9200/ ES地址 car_info/_search POST {} POST { "query&qu ...

  4. 有点儿神奇,原来vue3的setup语法糖中组件无需注册因为这个

    前言 众所周知,在vue2的时候使用一个vue组件要么全局注册,要么局部注册.但是在setup语法糖中直接将组件import导入无需注册就可以使用,你知道这是为什么呢?注:本文中使用的vue版本为3. ...

  5. 关于c指针的理解

    1 #include<stdio.h> 2 { 3 int a= 100,b=10; 4 int *p1=&a,*p2=&b; 5 *p1=b; 6 *p2=a; 7 pr ...

  6. Prometheus监控系统(二)Prometheus部署与使用

    1. Prometheus安装 官网:https://prometheus.io/ 下载地址:https://prometheus.io/download/ Prometheus基于Golang编写, ...

  7. 下载 Linux 内核的脚本

    介绍 在 类UNIX 环境下运行比较好(基于wget) 包括了 2.6 ~ 4.x 内核的地址. 5.x 因为 还在更新因此不做记录. 脚本下载地址: https://files.cnblogs.co ...

  8. 设备树DTS 学习:3-驱动开发中常用的 DTS api

    背景 本章的内容是为了实现在驱动中的开发,通过调用有关的api来寻找设备树节点熟悉,从而达到使用设备树进行驱动开发的目的. 参考:Linux内核 设备树操作常用API Linux设备树语法详解一文中介 ...

  9. Gitlab的安装和使用

    安装和配置必要的依赖项 yum install dnf sudo dnf install -y curl policycoreutils openssh-server #将SSH服务设置成开机自启动 ...

  10. 【深度学习 有效炼丹】多GPU使用教程, DP与DDP对比, ray多线程并行处理等 [GPU利用率低的分析]

    ️ 前言 更新日志: 20220404:新增一个DDP 加载模型时显存分布不均问题,见目录遇到的问题及解决处 主要是上次server12 被自己一个train 直接线程全部拉满了(没错 ... ser ...