技术小谈|反射和类加载的一个简单应用

        

        小明是一个刚入职不久的初级开发,虽然他掌握了很多Java的基础知识,但工作中一直没有机会用上,时常感到有些迷茫。某天,领导突然安排他编写一个系统的数据字典,由于项目代码风格良好,实体类中的字段都有中文名称,并且使用注解注释上了。面对这个任务,小明觉得如果手动维护太麻烦了,既费时间,又废精力,但他突然想起学习时提到的反射机制以及类加载,似乎可以用来动态获取类的信息。于是他深入研究,成功利用反射自动生成数据字典。

        好了,刚刚那个是需求背景,接下来我们简单聊一下这个小功能,说实话这个事情谁都可以做,无非就是做的快慢的事情,这里想用这个无非就是想说平常我们有些东西用起来代码写确实会时间更长一些,但是现在有了AI,我们有这个想法后在让AI来帮我们做这个事情确实会很容易。

        当然这里 作者只是抛砖引玉,这个东西实际上确实有这么个活,然后我把想法告诉了chatgpt,让他按照我说的写出了这段代码,加上调试,以及运行一共也就不到一个小时就搞定了,最后输出成了一个txt的文档,然后转换一下 直接复制到了excel,确实比纯手工维护方便很多,当然肯定会有其他问题,只不过在我这边跑通了而已,这个其实像网上的逆向原理也是差不多的。话不多说上代码:

package com.demo;// todo  这个包这里的注解是作者公司封装的
import com.demo.Comment;import javax.persistence.Column;
import javax.persistence.Table;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;public class AnnotationProcessor {public static void main(String[] args) {// todo 只需要在这里定义路径即可,避免重复硬编码String basePackagePath = "/Users/xx/job/com/demo/xxx/data/dao";String entityPath = basePackagePath + "/target/classes/com/demo/xxx/data/dao/entity"; // 只需调整这里路径,其他地方动态引用   注意 这里读取的是编译后的文件File dir = new File(entityPath);List<String> result = new ArrayList<>();// 检查目录是否存在且为有效目录if (dir.exists() && dir.isDirectory()) {File[] files = dir.listFiles((file) -> file.getName().endsWith(".class"));if (files != null) {URL[] urls;try {// 将目录路径转换为URL,用于类加载器urls = new URL[]{dir.toURI().toURL()};} catch (MalformedURLException e) {throw new RuntimeException("URL转换失败: " + dir.getAbsolutePath(), e);}// 使用自定义类加载器加载类文件try (URLClassLoader classLoader = new URLClassLoader(urls)) {for (File file : files) {// 根据文件路径获取类名String className = getClassNameFromFile(file, entityPath, basePackagePath);try {// 处理类中的注解processClassAnnotations(className, classLoader, result);} catch (NoClassDefFoundError e) {System.err.println("加载类时出现NoClassDefFoundError: " + className);e.printStackTrace();} catch (Exception e) {System.err.println("处理类时出错: " + className);e.printStackTrace();}}} catch (Exception e) {System.err.println("类加载时出错: " + e.getMessage());e.printStackTrace();}}} else {System.err.println("目录 " + entityPath + " 不存在或不是有效目录。");}// 写入结果到文件writeToFile(result);}// 从文件名获取类的全限定名,避免硬编码package,动态构建类路径private static String getClassNameFromFile(File file, String basePath, String basePackagePath) {String absolutePath = file.getAbsolutePath();String classPath = absolutePath.replace(basePath + "/", "").replace("/", ".").replace(".class", "");return basePackagePath.replace("/", ".") + "." + classPath;   // 根据基础包路径动态拼接类名}// 处理类中的注解,提取表名、列名及注释信息private static void processClassAnnotations(String className, ClassLoader classLoader, List<String> result) {try {// 使用类加载器加载指定的类Class<?> clazz = Class.forName(className, true, classLoader);Table tableAnnotation = clazz.getAnnotation(Table.class);if (tableAnnotation != null) {String tableName = tableAnnotation.name();for (Field field : clazz.getDeclaredFields()) {Column columnAnnotation = field.getAnnotation(Column.class);if (columnAnnotation != null) {String columnName = columnAnnotation.name();Comment commentAnnotation = field.getAnnotation(Comment.class);String comment = commentAnnotation != null ? commentAnnotation.value() : "";// 构建结果行,格式:表名 | 列名 | 注释String line = tableName + " | " + columnName + " | " + comment;result.add(line);}}}} catch (NoClassDefFoundError e) {System.err.println("加载类时出现NoClassDefFoundError: " + className);e.printStackTrace();} catch (Exception e) {System.err.println("处理类时出错: " + className);e.printStackTrace();}}// 将结果写入到txt文件中private static void writeToFile(List<String> result) {System.out.println("开始写入文件……");System.out.println("当前工作目录: " + System.getProperty("user.dir"));try (FileWriter writer = new FileWriter("output.txt")) {for (String line : result) {writer.write(line + System.lineSeparator());}} catch (IOException e) {System.err.println("写入文件时出错: " + e.getMessage());e.printStackTrace();}}
}

        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/148948.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Invalid Executable The executable contains bitcode

Invalid Executable The executable contains bitcode xcode世界xcode16后&#xff0c;打包上传testflight时三方库报错&#xff1a;Invalid Executable - The executable ***.app/Frameworks/xxx.framework/xxx contains bitcode. 解决方案&#xff1a; 执行一下指令删除该f…

JavaScript中Windows对象下的属性和方法

1.Windows对象概念 所有的浏览器都支持Windows对象。它表示浏览器窗口 2.Boom概念 Boom&#xff1a;是指浏览器对象模型&#xff0c;它使javaScript有能力与浏览器进行对话 3.DOM概念 DOM&#xff1a;是指文档对象模型&#xff0c;通过它可以访问HTML文档中的所有元素 HT…

导入时,Excel模板不被下载

问题描述 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; 这是个SSM项目&#xff0c;以前经常遇到这个问题&#xff0c;今天有幸记录下来 [ERROR][o.a.s.r.StreamResult] Can not find a java.io.InputStream with the name [downLoadFile] in the invocation stack…

多数元素-简单

169. 多数元素 - 力扣&#xff08;LeetCode&#xff09; 【LeetCode 每日一题】169. 多数元素 | 手写图解版思路 代码讲解_哔哩哔哩_bilibili c为计数器&#xff0c;代表当前候选人的票数 v为当前候选人 x为遍历的各候选人得票 分三种情况&#xff1a; 第一种&#xff0c;c…

MFC - 复杂控件_1

前言 各位师傅大家好&#xff0c;我是qmx_07&#xff0c;今天给大家讲解复杂控件的相关知识点 复杂控件 进度条 绘图准备: 调整windows窗口大小、设置 Progress Control 进度条设置Button 按钮 添加进度条变量 m_Progress,通过按钮触发 void CMFCApplication2Dlg::OnBnCl…

C++ set 和 map学习

一、set(multiset)的基本知识和使用 set也是一种我们直接可以使用的容器&#xff0c;使用应该包含 #include <set> 这个头文件。此处暂且不讨论其底层&#xff0c;只探讨set如何使用即可。 我们看到&#xff0c;set 的模板参数有三个&#xff0c;第一个就是其存储的数据…

【操作系统强化】王道强化一轮笔记

第一章 计算机系统概述 考点1 操作系统的概念、特征和功能 1. 2. 考点2 内核态与用户态 1. 2.用户态和内核态之间的切换本质上就是应用程序和操作系统对CPU控制器的切换 考点3 中断和异常 1. 2. 考点4 系统调用 1. 2. 3.C 考点5 操作系统引导 1. 2. ①磁盘的物理格式化&…

ERNIESpeed-128K在线智能聊天机器人项目(附源码)

本项目是基于百度千帆的智能聊天模型ERNIESpeed-128K开发的 一、技术栈 后端&#xff1a;java8springboot2.6.13 数据库&#xff1a;MongoDB 前端&#xff1a;vue2element-uimarked&#xff08;md格式&#xff09; 二、MongoDB与对话存储的设计 使用MongoDB来储存对话&am…

戎易大数据 | 数据分析实操篇:基于MySQL和Tableau的淘宝用户购物行为数据分析

本文来源公众号“戎易大数据”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;数据分析实操篇&#xff1a;基于MySQL和Tableau的淘宝用户购物行为数据分析 1项目介绍 为提高平台GMV和实现精细化运营&#xff0c;本项目首先使用My…

领夹麦克风哪个品牌好,无线领夹麦克风品牌排名,麦克风品牌大全

无线领夹麦克风因其便携性和隐蔽性&#xff0c;越来越受到演讲者和表演者的青睐。但是&#xff0c;随着市场上品牌和型号的增多&#xff0c;质量也变得参差不齐。许多用户在选购时&#xff0c;会因为缺乏了解而选择到性能不佳的产品&#xff0c;影响声音的清晰度和稳定性。下面…

预计2030年全球半导体用超高纯氢气市场规模将达到2.5亿美元

超高纯度氢气是半导体制造行业使用的关键气体&#xff0c;其纯度通常为 99.999% (5N) 或更高。这种纯度水平对于避免引入可能损害半导体器件性能和可靠性的杂质至关重要。在半导体生产中&#xff0c;超高纯度氢气用于化学气相沉积 (CVD)、外延生长、退火和表面清洁等关键工艺。…

java基础(2)方法的使用

目录 1.前言 2.正文 2.1方法的定义 2.2方法的调用过程 2.3方法的实参与形参 2.3.1形参 2.3.2实参 2.3.3参数传递 2.4方法的重载 3.小结 1.前言 哈喽大家好啊&#xff0c;今天博主继续带领大家学习java的基本语法&#xff0c;java的基础语法部分打算用六到七篇博文完…

Undet for sketchup 2023.3注册机 支持草图大师sketchup2021-2022-2023

1.Undet for sketchup 2023.3支持草图大师sketchup2021-2022-2023。支持机载雷达扫描、车载扫描还是地面扫描&#xff0c;对AEC行业用户来说&#xff0c;真正需要的是如何将这些数据快速处理为三维模型&#xff0c;这样才能将这些信息延展到BIM领域发挥效用。因此面对这些海量的…

Facebook开发者篇 - API拉取广告投放数据对接流程

大家好&#xff0c;我是牢鹅&#xff01;相信大家做出海&#xff0c;很多人会考虑在Facebook这样的大平台买量&#xff0c;但是每次登入Facebook的广告后台看数据很麻烦&#xff0c;又要科学上网&#xff0c;又要拉数据下来作进一步的分析&#xff0c;赚刀乐总是慢人一步。所以…

PHP基础语法讲解

​ 大家好&#xff0c;我是程序员小羊&#xff01; 前言&#xff1a; PHP&#xff08;Hypertext Preprocessor&#xff09;是一种常用于网页开发的服务器端脚本语言&#xff0c;易于学习并且与 HTML 紧密结合。以下是 PHP 的基础语法详细讲解。 1. PHP 基础结构 1.1 PHP 脚本结…

kubernetes网络(二)之bird实现节点间BGP互联的实验

摘要 上一篇文章中我们学习了calico的原理&#xff0c;kubernetes中的node节点&#xff0c;利用 calico 的 bird 程序相互学习路由&#xff0c;为了加深对 bird 程序的认识&#xff0c;本文我们将使用bird进行实验&#xff0c;实验中实现了BGP FULL MESH模式让宿主相互学习到对…

Python练习宝典:Day 3 - 选择题 - 字符串与正则表达式、基础练习补充

目录 一、基础练习补充二、字符串与正则表达式 一、基础练习补充 1.下列能返回变量s的数据类型的是: A.print(type(s)) B.print(s) C.print(int(s)) D.print(str(s))2.如果想要换行,可以使用: A.\ B.\n C.\t D.\f3.合法的标识符是: A.M-N B.and C.Dior_Ysl D.6_friends4.在…

记一次:基于wmi软件的rpm包和deb包相互转换【附rpm和deb包】

1 背景 项目需要修改容器的基础镜像&#xff0c;从之前的CentOS 8 修改成 Ubuntu&#xff0c;项目中需要wmi包&#xff08;一个windows系统上管理和查询系统各种信息的工具&#xff0c;windows上自带&#xff09; 之前是使用rpm包进行安装的&#xff0c;现在使用的是deb的包管…

JBoss EJBInvokerServlet CVE-2013-4810 反序列化漏洞

开启环境 访问http://172.16.1.183:8080/invoker/EJBInvokerServlet下载下来了说明漏洞存在 利用生成的.ser文件&#xff0c;通过POST 二进制数据上去&#xff0c;反向连接shell curl http://192.168.10.154:8080/invoker/EJBInvokerServlet --data-binary ReverseShellCommon…

数据结构(Day19)

一、学习内容 单链表 头删 int front_dele(Plink L) {if(LNULL||L->len0){printf("头删失败\n");return -1;}Plink Q L->next;//保留要删除的1号节点L->next L->next->next;L->len--;free(Q);//释放空间QNULL;return 0; }尾删 int rear_dele(Pli…