千家信息网

如何改变jar包某个类的运行方式

发表于:2025-01-25 作者:千家信息网编辑
千家信息网最后更新 2025年01月25日,这篇文章主要介绍"如何改变jar包某个类的运行方式",在日常操作中,相信很多人在如何改变jar包某个类的运行方式问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"如何改变j
千家信息网最后更新 2025年01月25日如何改变jar包某个类的运行方式

这篇文章主要介绍"如何改变jar包某个类的运行方式",在日常操作中,相信很多人在如何改变jar包某个类的运行方式问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"如何改变jar包某个类的运行方式"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

例如:

有类 Feature

Java代码

public class Feature {             private String content;             public void show() {             System.out.println(this.content);         }     }

及类 Function

Java代码

public class Function {             private Feature f;             public void show() {             this.f.show();         }              }

测试类 Test,运行结果为 null . 而你想让他输出hello kitty

Java代码

public class Test {             /**         * @param args         */        public static void main(String[] args) {             Function function = new Function();             function.show();         }         }

***想到的方法是就是直接建一个同包同名类,在你的eclipse或者其它编译环境下;然后把相关方法,改成自己想要的方法;如下:

Java代码

public class Feature {             private String content;             public Feature(){             this.content = "hello kitty";         }             public void show() {             System.out.println(this.content);         }     }

然后,你会发现,使用的是你的class吖,而不是jar包里的吖.

但是,如果你的程序也打成jar包,和原jar一起运跑,会是什么情况呢;

你可能发现,会输出 空,如果运气好,也可能 输出 hello kitty ;

为啥呢? 因为当有同包同名类时,classLoader总会尝试先加载到一个,而且加载到这个class文件后,后面就不会再加载;这个先加载到的类一般和classpath设置的先后有关;

在eclipse环境下,会先加载编辑器下的类,然后优先加载,先导入的类库;

如果先加载到你的类,那么就会输出 "hellokitty".

假如需要在生产环境指定加载你的类,

而且,

你无法预知客户如何设置classPath的先后顺序,那么,要怎么办呢?

可否自己写一个classLoader只加载目标类,而让你的调用程序在此classLoader环境下运行?

Let us try try : 先写出这个特别的classLoader

Java代码

public class HoneyLoader extends URLClassLoader {             public HoneyLoader(URL[] urls, ClassLoader parent){             super(urls, parent);         }             public synchronized Class loadClass(String name) throws ClassNotFoundException {             Class c = findLoadedClass(name);             if (c != null) {                 return c;             }     //先自己在指定位置(通过urls指定)找,找不到交给父类             try {                 c = this.findClass(name);             } catch (Exception e) {                 c = super.loadClass(name);             }             return c;         }     }

回到我们的测试类,修改如下

Java代码

public class Test {             public static void main(String[] args) throws Exception {             // 根据jar包名称,获取我们需要的jar包的名称的url             String jarName = "feature2.jar";             URL url = null;                 ClassLoader loader = Thread.currentThread().getContextClassLoader();             Enumeration urls = loader.getResources("Feature.class");             int i = 0;             while (urls.hasMoreElements()) {                 url = urls.nextElement();                 i = url.getPath().indexOf(jarName);                 if (i > -1) {                     break;                 }             }                 // 用honeyLoader启动我们的运行环境             ClassLoader myLoader = new HoneyLoader(new URL[] { new URL(url.getPath().substring(0, i) + jarName) }, loader);             Object object = myLoader.loadClass("Feature").newInstance();             object.getClass().getMethod("show").invoke(object);             }

运行结果:

Java代码

hello kitty

用classLoader的方法,将建立一个小的运行机制,和业务代码的相关性很低,冗余代码多;

而且,新建的和原类相同的包名和类不便于维护;

有什么更好的方法么?

对于(一)中描述的需求,其实,我们只需改变下Feature的私有属性content,是否可以通过反射来实现呢?

尝试以下代码:

Java代码

public class Test {             // 获取object 的属性 fieldName         public static Field getField(Object object, String fieldName) throws Exception {             Field field = object.getClass().getDeclaredField(fieldName);             return field;         }             public static void main(String[] args) throws Exception {             Function function = new Function();             // 获取function的feature             Field f_feature = getField(function, "f");                 // 通过feature 获取 其属性 content             f_feature.setAccessible(true);             Field f_function = getField(f_feature.get(function), "content");                 // 改变content的内容             f_function.setAccessible(true);             f_function.set(f_feature.get(function), "hello kitty");                 function.show();         }     }

执行,得到结果

Java代码

hello kitty

冗余代码减少,目的更加明确了,但对于改变的业务代码,任然不清晰;不容易维护;

通常,如果我们要得到有我们的特性的类,通常用继承的方法,但是有时候,会发现,如果是你要调用的调用的调用的类,要改变一点动作,那你为了改调用的调用的调用,不得不继承调用和调用的调用;

假如我们只改变目标类,只继承目标类,结合反射的方式,改调用,是否可行呢?

例如,继承Feature创建类MyFeature

Java代码

public class MyFeature extends Feature {             private String mycontent;             public MyFeature(){             this.mycontent = "hello kitty";         }             public void show() {             System.out.println(this.mycontent);         }     }

这样我们改变的逻辑清晰很多,容易维护,我们再来修改下Test类

Java代码

public class Test {             // 获取object 的属性 fieldName         public static Field getField(Object object, String fieldName) throws Exception {             Field field = object.getClass().getDeclaredField(fieldName);             return field;         }             public static void main(String[] args) throws Exception {             Function function = new Function();             // 获取function的feature             Field f_feature = getField(function, "f");                 // 改变feature的内容             f_feature.setAccessible(true);             f_feature.set(function, new MyFeature());                 function.show();         }     }

此时,Test的逻辑也清晰很多,我们可以清楚的看到,我们需要改变哪个类

运行一下,看下结果

Java代码

hello kitty

到此,关于"如何改变jar包某个类的运行方式"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

代码 运行 方法 方式 环境 属性 结果 学习 输出 目标 业务 先后 内容 冗余 名称 更多 程序 逻辑 反射 尝试 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 仪表检定数据库 部队保密网络安全图片 软件开发实施公司 传统工业里面搞软件开发 网络安全宣传日相关视频 电子商务有哪些网络安全问题 多媒体的软件开发工具包括哪些 吉林运营网络安全工程联系人 数据库中职称代码 目前存在哪些网络安全问题 网络技术部门的职责是什么 易语言稳定服务器 mc服务器怎么删除封禁信息 网络安全等级保护行业分析 教育软件开发的上市公司 服务器怎么解决文章的存储 浙江软件开发设计招生电话 艾克斯软件开发有限公司 本科有计算机网络技术 数据库的两种查询方式到底是什么 数据库常见的网络模型 金蝶记账王数据库 梅州无线软件开发维修电话 最新的网络技术案例 全球恐怖主义数据库怎么查 进入网络安全模式要多久 聊天内容会留在服务器上吗 外包开发好后服务器数据安全 网络安全等级考试通过率 ajax 服务器时间
0