成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

誰動了你的jar包

開發(fā) 后端
哈,你想改變jar包某個類的運行方式?或是因為業(yè)務(wù)需要,或是因為這個jar暫時不能滿足你你欲望...或者只是for Fun!但是你無法改變這個jar包,可能因為是公用的,可能因為產(chǎn)品的生成依賴于標準倉庫,或者僅僅是你不想用 "編譯一下你的java類,然后把你的.class替換進去" 這么...這么..這么...的方法,那你要怎么做?

哈,你想改變jar包某個類的運行方式?

或是因為業(yè)務(wù)需要,或是因為這個jar暫時不能滿足你你欲望...

或者只是for Fun!

但是你無法改變這個jar包,可能因為是公用的,可能因為產(chǎn)品的生成依賴于標準倉庫,或者僅僅是你不想用 "編譯一下你的java類,然后把你的.class替換進去" 這么...這么..這么...的方法,那你要怎么做?

例如:

有類 Feature

Java代碼

  1. public class Feature {     
  2.     
  3.     private String content;     
  4.     
  5.     public void show() {     
  6.         System.out.println(this.content);     
  7.     }     
  8. }    

 

及類 Function

Java代碼

  1. public class Function {     
  2.     
  3.     private Feature f;     
  4.     
  5.     public void show() {     
  6.         this.f.show();     
  7.     }     
  8.          
  9. }   

 

測試類 Test,運行結(jié)果為 null . 而你想讓他輸出hello kitty

Java代碼

  1. public class Test {     
  2.     
  3.     /**    
  4.      * @param args    
  5.      */    
  6.     public static void main(String[] args) {     
  7.         Function function = new Function();     
  8.         function.show();     
  9.     }     
  10.     
  11. }  

 

***想到的方法是就是直接建一個同包同名類,在你的eclipse或者其它編譯環(huán)境下;然后把相關(guān)方法,改成自己想要的方法;如下:

Java代碼

  1. public class Feature {     
  2.     
  3.     private String content;     
  4.     
  5.     public Feature(){     
  6.         this.content = "hello kitty";     
  7.     }     
  8.     
  9.     public void show() {     
  10.         System.out.println(this.content);     
  11.     }     
  12. }   

 

然后,你會發(fā)現(xiàn),使用的是你的class吖,而不是jar包里的吖.

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

你可能發(fā)現(xiàn),會輸出 空,如果運氣好,也可能 輸出 hello kitty ;

為啥呢? 因為當有同包同名類時,classLoader總會嘗試先加載到一個,而且加載到這個class文件后,后面就不會再加載;這個先加載到的類一般和classpath設(shè)置的先后有關(guān);

在eclipse環(huán)境下,會先加載編輯器下的類,然后優(yōu)先加載,先導(dǎo)入的類庫;

如果先加載到你的類,那么就會輸出 "hellokitty".

假如需要在生產(chǎn)環(huán)境指定加載你的類,

而且,

你無法預(yù)知客戶如何設(shè)置classPath的先后順序,那么,要怎么辦呢?

可否自己寫一個classLoader只加載目標類,而讓你的調(diào)用程序在此classLoader環(huán)境下運行?

Let us try try : 先寫出這個特別的classLoader

Java代碼

  1. public class HoneyLoader extends URLClassLoader {     
  2.     
  3.     public HoneyLoader(URL[] urls, ClassLoader parent){     
  4.         super(urls, parent);     
  5.     }     
  6.     
  7.     public synchronized Class loadClass(String name) throws ClassNotFoundException {     
  8.         Class c = findLoadedClass(name);     
  9.         if (c != null) {     
  10.             return c;     
  11.         }     
  12. //先自己在指定位置(通過urls指定)找,找不到交給父類     
  13.         try {     
  14.             c = this.findClass(name);     
  15.         } catch (Exception e) {     
  16.             c = super.loadClass(name);     
  17.         }     
  18.         return c;     
  19.     }     
  20. }   

 

回到我們的測試類,修改如下

Java代碼

  1. public class Test {     
  2.     
  3.     public static void main(String[] args) throws Exception {     
  4.         // 根據(jù)jar包名稱,獲取我們需要的jar包的名稱的url     
  5.         String jarName = "feature2.jar";     
  6.         URL url = null;     
  7.     
  8.         ClassLoader loader = Thread.currentThread().getContextClassLoader();     
  9.         Enumeration urls = loader.getResources("Feature.class");     
  10.         int i = 0;     
  11.         while (urls.hasMoreElements()) {     
  12.             url = urls.nextElement();     
  13.             i = url.getPath().indexOf(jarName);     
  14.             if (i > -1) {     
  15.                 break;     
  16.             }     
  17.         }     
  18.     
  19.         // 用honeyLoader啟動我們的運行環(huán)境     
  20.         ClassLoader myLoader = new HoneyLoader(new URL[] { new URL(url.getPath().substring(0, i) + jarName) }, loader);     
  21.         Object object = myLoader.loadClass("Feature").newInstance();     
  22.         object.getClass().getMethod("show").invoke(object);     
  23.     
  24.     }    

 

運行結(jié)果:

Java代碼

  1. hello kitty  

 

#p#

用classLoader的方法,將建立一個小的運行機制,和業(yè)務(wù)代碼的相關(guān)性很低,冗余代碼多;

而且,新建的和原類相同的包名和類不便于維護;

有什么更好的方法么?

對于(一)中描述的需求,其實,我們只需改變下Feature的私有屬性content,是否可以通過反射來實現(xiàn)呢?

嘗試以下代碼:

Java代碼

  1. public class Test {     
  2.     
  3.     // 獲取object 的屬性 fieldName     
  4.     public static Field getField(Object object, String fieldName) throws Exception {     
  5.         Field field = object.getClass().getDeclaredField(fieldName);     
  6.         return field;     
  7.     }     
  8.     
  9.     public static void main(String[] args) throws Exception {     
  10.         Function function = new Function();     
  11.         // 獲取function的feature     
  12.         Field f_feature = getField(function, "f");     
  13.     
  14.         // 通過feature 獲取 其屬性 content     
  15.         f_feature.setAccessible(true);     
  16.         Field f_function = getField(f_feature.get(function), "content");     
  17.     
  18.         // 改變content的內(nèi)容     
  19.         f_function.setAccessible(true);     
  20.         f_function.set(f_feature.get(function), "hello kitty");     
  21.     
  22.         function.show();     
  23.     }     
  24. }    

 

執(zhí)行,得到結(jié)果

Java代碼

  1. hello kitty   

 

冗余代碼減少,目的更加明確了,但對于改變的業(yè)務(wù)代碼,任然不清晰;不容易維護;

通常,如果我們要得到有我們的特性的類,通常用繼承的方法,但是有時候,會發(fā)現(xiàn),如果是你要調(diào)用的調(diào)用的調(diào)用的類,要改變一點動作,那你為了改調(diào)用的調(diào)用的調(diào)用,不得不繼承調(diào)用和調(diào)用的調(diào)用;

假如我們只改變目標類,只繼承目標類,結(jié)合反射的方式,改調(diào)用,是否可行呢?

例如,繼承Feature創(chuàng)建類MyFeature

Java代碼

  1. public class MyFeature extends Feature {     
  2.     
  3.     private String mycontent;     
  4.     
  5.     public MyFeature(){     
  6.         this.mycontent = "hello kitty";     
  7.     }     
  8.     
  9.     public void show() {     
  10.         System.out.println(this.mycontent);     
  11.     }     
  12. }  

 

這樣我們改變的邏輯清晰很多,容易維護,我們再來修改下Test類

Java代碼

  1. public class Test {     
  2.     
  3.     // 獲取object 的屬性 fieldName     
  4.     public static Field getField(Object object, String fieldName) throws Exception {     
  5.         Field field = object.getClass().getDeclaredField(fieldName);     
  6.         return field;     
  7.     }     
  8.     
  9.     public static void main(String[] args) throws Exception {     
  10.         Function function = new Function();     
  11.         // 獲取function的feature     
  12.         Field f_feature = getField(function, "f");     
  13.     
  14.         // 改變feature的內(nèi)容     
  15.         f_feature.setAccessible(true);     
  16.         f_feature.set(function, new MyFeature());     
  17.     
  18.         function.show();     
  19.     }     
  20. }    

 

此時,Test的邏輯也清晰很多,我們可以清楚的看到,我們需要改變哪個類

運行一下,看下結(jié)果

 

Java代碼

  1. hello kitty 

原文鏈接:http://ilab.iteye.com/blog/1002629

【編輯推薦】

  1. 高手Java核心技術(shù)學(xué)習筆記
  2. 如何使用 JavaScript XSLT 處理 XML 文件
  3. JSP結(jié)合XML+XSLT將輸出轉(zhuǎn)換HTML
  4. Java通過JNI調(diào)用C語言的方法
  5. JAVA環(huán)境變量的設(shè)置
責任編輯:金賀 來源: ITEYE博客
相關(guān)推薦

2017-02-14 14:23:52

大數(shù)據(jù)春晚

2017-07-14 09:13:53

2014-06-30 16:19:43

eHR管理軟件

2015-06-05 15:47:47

2010-05-20 09:29:14

谷歌微軟云計算

2020-01-10 09:06:10

Activity系統(tǒng) 通信

2012-12-12 09:56:40

EC2AWSAmazon

2015-10-09 11:02:02

2016-10-19 11:00:26

2010-08-26 15:34:12

2020-03-24 14:57:05

戴爾

2015-04-17 10:30:13

2015-09-25 11:35:56

2023-12-13 10:36:38

Long算法代碼

2012-03-28 13:02:40

2021-09-01 20:27:34

數(shù)據(jù)安全法數(shù)據(jù)安全信息安全

2021-01-08 09:35:41

LinuxHistory命令

2021-04-19 07:35:01

Linuxhistory命令

2021-04-26 10:24:52

Linux 開發(fā)操作系統(tǒng)

2011-01-06 13:14:40

Android短信誤發(fā)
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 特级生活片| 成人免费一区二区三区牛牛 | 高清成人av | 国产乱码精品一区二区三区五月婷 | 精品欧美乱码久久久久久1区2区 | 国产一区二区三区在线 | 九色在线视频 | 国内精品伊人久久久久网站 | 亚洲综合精品 | 国产乱码久久久 | 久久精品免费一区二区 | 日本电影免费完整观看 | 午夜影院毛片 | 亚洲伊人a| 天天久久 | 久久久91 | 色爱综合网 | 日韩在线观看一区 | 国产视频中文字幕在线观看 | 国产91精品网站 | 狠狠久 | 精品国产综合 | 91一区二区 | 欧美一区二区三区视频 | 欧洲一区在线观看 | 正在播放国产精品 | 久久亚洲欧美日韩精品专区 | 91美女在线 | 99re在线视频免费观看 | 亚洲 欧美 日韩在线 | 日韩三极 | 欧美中文在线 | 毛片免费观看 | 欧美日韩久久 | 亚洲成人一区二区三区 | 国产高清精品在线 | 久久久久久久久综合 | 欧美日韩一区二区视频在线观看 | 特级黄一级播放 | 久草99| 精品亚洲一区二区 |