這篇文章主要介紹“如何改變jar包某個類的運行方式”,在日常操作中,相信很多人在如何改變jar包某個類的運行方式問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”如何改變jar包某個類的運行方式”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!
成都創(chuàng)新互聯(lián)公司是一家專注于成都網(wǎng)站制作、網(wǎng)站建設(shè)與策劃設(shè)計,湛江網(wǎng)站建設(shè)哪家好?成都創(chuàng)新互聯(lián)公司做網(wǎng)站,專注于網(wǎng)站建設(shè)10年,網(wǎng)設(shè)計領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:湛江等地區(qū)。湛江做網(wǎng)站價格咨詢:18982081108
例如:
有類 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,運行結(jié)果為 null . 而你想讓他輸出hello kitty
Java代碼
public class Test { /** * @param args */ public static void main(String[] args) { Function function = new Function(); function.show(); } }
***想到的方法是就是直接建一個同包同名類,在你的eclipse或者其它編譯環(huán)境下;然后把相關(guān)方法,改成自己想要的方法;如下:
Java代碼
public class Feature { private String content; public Feature(){ this.content = "hello kitty"; } public void show() { System.out.println(this.content); } }
然后,你會發(fā)現(xiàn),使用的是你的class吖,而不是jar包里的吖.
但是,如果你的程序也打成jar包,和原jar一起運跑,會是什么情況呢;
你可能發(fā)現(xiàn),會輸出 空,如果運氣好,也可能 輸出 hello kitty ;
為啥呢? 因為當(dāng)有同包同名類時,classLoader總會嘗試先加載到一個,而且加載到這個class文件后,后面就不會再加載;這個先加載到的類一般和classpath設(shè)置的先后有關(guān);
在eclipse環(huán)境下,會先加載編輯器下的類,然后優(yōu)先加載,先導(dǎo)入的類庫;
如果先加載到你的類,那么就會輸出 "hellokitty".
假如需要在生產(chǎn)環(huán)境指定加載你的類,
而且,
你無法預(yù)知客戶如何設(shè)置classPath的先后順序,那么,要怎么辦呢?
可否自己寫一個classLoader只加載目標(biāo)類,而讓你的調(diào)用程序在此classLoader環(huán)境下運行?
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 { // 根據(jù)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啟動我們的運行環(huán)境 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); }
運行結(jié)果:
Java代碼
hello kitty
用classLoader的方法,將建立一個小的運行機制,和業(yè)務(wù)代碼的相關(guān)性很低,冗余代碼多;
而且,新建的和原類相同的包名和類不便于維護(hù);
有什么更好的方法么?
對于(一)中描述的需求,其實,我們只需改變下Feature的私有屬性content,是否可以通過反射來實現(xiàn)呢?
嘗試以下代碼:
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的內(nèi)容 f_function.setAccessible(true); f_function.set(f_feature.get(function), "hello kitty"); function.show(); } }
執(zhí)行,得到結(jié)果
Java代碼
hello kitty
冗余代碼減少,目的更加明確了,但對于改變的業(yè)務(wù)代碼,任然不清晰;不容易維護(hù);
通常,如果我們要得到有我們的特性的類,通常用繼承的方法,但是有時候,會發(fā)現(xiàn),如果是你要調(diào)用的調(diào)用的調(diào)用的類,要改變一點動作,那你為了改調(diào)用的調(diào)用的調(diào)用,不得不繼承調(diào)用和調(diào)用的調(diào)用;
假如我們只改變目標(biāo)類,只繼承目標(biāo)類,結(jié)合反射的方式,改調(diào)用,是否可行呢?
例如,繼承Feature創(chuàng)建類MyFeature
Java代碼
public class MyFeature extends Feature { private String mycontent; public MyFeature(){ this.mycontent = "hello kitty"; } public void show() { System.out.println(this.mycontent); } }
這樣我們改變的邏輯清晰很多,容易維護(hù),我們再來修改下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的內(nèi)容 f_feature.setAccessible(true); f_feature.set(function, new MyFeature()); function.show(); } }
此時,Test的邏輯也清晰很多,我們可以清楚的看到,我們需要改變哪個類
運行一下,看下結(jié)果
Java代碼
hello kitty
到此,關(guān)于“如何改變jar包某個類的運行方式”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
網(wǎng)站題目:如何改變jar包某個類的運行方式
新聞來源:http://weahome.cn/article/pscdpp.html