如何使用java获取包下被指定注解的类
发表于:2025-01-24 作者:千家信息网编辑
千家信息网最后更新 2025年01月24日,这篇文章主要介绍如何使用java获取包下被指定注解的类,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!方案一: 采用reflections 框架(此框架依赖com.google.
千家信息网最后更新 2025年01月24日如何使用java获取包下被指定注解的类
这篇文章主要介绍如何使用java获取包下被指定注解的类,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!
方案一: 采用reflections 框架(此框架依赖com.google.guava)
1、reflections框架地址:https://github.com/ronmamo/reflections
2、项目依赖
org.reflections reflections 0.9.11 com.google.guava guava 21.0
3、实现代码
//入参 要扫描的包名Reflections f = new Reflections("com.ggband.netty.execute.command");//入参 目标注解类Set
方案二: 采用ClassLoader扫描
1、实现代码
package com.ggband.netty;import java.io.File;import java.io.IOException;import java.lang.annotation.Annotation;import java.net.JarURLConnection;import java.net.URL;import java.net.URLDecoder;import java.util.Enumeration;import java.util.HashSet;import java.util.Set;import java.util.jar.JarEntry;import java.util.jar.JarFile;public class Scanner { /** * 从包package中获取所有的Class * * @param packageName * @return */ public Set> getClasses(String packageName) throws Exception { // 第一个class类的集合 //List > classes = new ArrayList >(); Set > classes = new HashSet<>(); // 是否循环迭代 boolean recursive = true; // 获取包的名字 并进行替换 String packageDirName = packageName.replace('.', '/'); // 定义一个枚举的集合 并进行循环来处理这个目录下的things Enumeration dirs; try { dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName); // 循环迭代下去 while (dirs.hasMoreElements()) { // 获取下一个元素 URL url = dirs.nextElement(); // 得到协议的名称 String protocol = url.getProtocol(); // 如果是以文件的形式保存在服务器上 if ("file".equals(protocol)) { // 获取包的物理路径 String filePath = URLDecoder.decode(url.getFile(), "UTF-8"); // 以文件的方式扫描整个包下的文件 并添加到集合中 addClass(classes, filePath, packageName); } else if ("jar".equals(protocol)) { // 如果是jar包文件 // 定义一个JarFile JarFile jar; try { // 获取jar jar = ((JarURLConnection) url.openConnection()).getJarFile(); // 从此jar包 得到一个枚举类 Enumeration entries = jar.entries(); // 同样的进行循环迭代 while (entries.hasMoreElements()) { // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件 JarEntry entry = entries.nextElement(); String name = entry.getName(); // 如果是以/开头的 if (name.charAt(0) == '/') { // 获取后面的字符串 name = name.substring(1); } // 如果前半部分和定义的包名相同 if (name.startsWith(packageDirName)) { int idx = name.lastIndexOf('/'); // 如果以"/"结尾 是一个包 if (idx != -1) { // 获取包名 把"/"替换成"." packageName = name.substring(0, idx).replace('/', '.'); } // 如果可以迭代下去 并且是一个包 if ((idx != -1) || recursive) { // 如果是一个.class文件 而且不是目录 if (name.endsWith(".class") && !entry.isDirectory()) { // 去掉后面的".class" 获取真正的类名 String className = name.substring(packageName.length() + 1, name.length() - 6); try { // 添加到classes classes.add(Class.forName(packageName + '.' + className)); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } } } } catch (IOException e) { e.printStackTrace(); } } } } catch (IOException e) { e.printStackTrace(); } return classes; } public void addClass(Set > classes, String filePath, String packageName) throws Exception { File[] files = new File(filePath).listFiles(file -> (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory()); assert files != null; for (File file : files) { String fileName = file.getName(); if (file.isFile()) { String classsName = fileName.substring(0, fileName.lastIndexOf(".")); if (!packageName.isEmpty()) { classsName = packageName + "." + classsName; } doAddClass(classes, classsName); } } } public void doAddClass(Set > classes, final String classsName) throws Exception { ClassLoader classLoader = new ClassLoader() { @Override public Class> loadClass(String name) throws ClassNotFoundException { return super.loadClass(name); } }; classes.add(classLoader.loadClass(classsName)); } public Set > getAnnotationClasses(String packageName, Class annotationClass) throws Exception { //找用了annotationClass注解的类 Set > controllers = new HashSet<>(); Set > clsList = getClasses(packageName); if (clsList != null && clsList.size() > 0) { for (Class> cls : clsList) { if (cls.getAnnotation(annotationClass) != null) { controllers.add(cls); } } } return controllers; }}
2、使用:
Set
扩充:现在就可以实现自己的业务了,比如 扫描com.ggband.netty.execute.command包下被Cmd注解的类 得到Cmd注解value和被注解类的实例
MapbeanContainer = new HashMap<>(); try { //@1 采用reflections 框架(此框架依赖com.google.guava)// Reflections f = new Reflections("com.ggband.netty.execute.command");// Set > set = f.getTypesAnnotatedWith(Cmd.class); //@2 采用ClassLoader扫描 Set > set = new Scanner().getAnnotationClasses("com.ggband.netty.execute.command", Cmd.class); for (Class> c : set) { Object bean = c.newInstance(); Cmd annotation = c.getAnnotation(Cmd.class); beanContainer.put(Arrays.toString(annotation.value()), (Command) bean); } } catch (Exception e) { e.printStackTrace(); }
以上是"如何使用java获取包下被指定注解的类"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!
注解
文件
框架
循环
迭代
目录
代码
内容
方案
篇文章
相同
业务
价值
元素
兴趣
前半部
名字
名称
地址
字符
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
广电网络技术KPI考核
xp电脑无线服务器
大数据软件开发费用
以管理员登录服务器
中国知名的al服务器厂家
网络安全中的科学计算
提升 网络安全意识
压强思维导图软件开发
烈焰网络技术有限公司
高中生学软件开发好吗
原始传奇4月10日是哪个服务器
中小学同步教育软件开发
app定制软件开发丽水
数据库批量替换字
母鸡云服务器
wind数据库辅助
神华软件开发
欧标和国标服务器插头的区别
洛阳软件开发学校
网络安全校园日课件
018年国家网络安全周
如何建立一个数据库
数据库什么称为实例
两千字软件开发总结
服务器怎么设置不登录
神舟网络安全评估中心
中国的互联网科技成就
sql本机数据库密码
谈谈看待网络安全的做法
杭州定制软件开发流程