java获取包下所有的类
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; } }