利用反射實現Java類的動態加載
//首先定義一個接口來隔離類: public interface Operator { // public java.util.List act(java.util.List params); public java.util.List act(String content,String content2,java.util.List params); }
根據設計模式的原理,我們可以為不同的功能編寫不同的類,每個類都繼承Operator接口,客戶端只需要針對Operator接口編程就可以避免很多麻煩。比如這個類:
import java.util.*; public class Success implements Operator { public static void main(String[] args) { List list = new ArrayList(); list.add("Success3"); Operator op = new Success(); System.out.println("act===" + op.act("Success1", "Success2", list)); } // public java.util.List act(java.util.List params) public java.util.List act(String content, String content2, java.util.List params) { List result = new ArrayList(); result.add(content); result.add(content2); result.add(params); return result; } }
同樣,也可以寫另一個類:
import java.util.*; public class Load implements Operator { public static void main(String[] args) { List list = new ArrayList(); list.add("Load3"); Operator op = new Load(); System.out.println("act===" + op.act("Load1", "Load2", list)); } // public java.util.List act(java.util.List params) public java.util.List act(String content, String content2, java.util.List params) { List result = new ArrayList(); result.add(content); result.add(content2); result.add(params); return result; } }
我們還可以寫其他很多類,但是有個問題,接口是無法實例化的,我們必須手動控制具體實例化哪個類,這很不爽,如果能夠向應用程序傳遞一個參數,讓自己去選擇實例化一個類,執行它的act方法,那我們的工作就輕松多了。
很幸運,我使用的是Java,只有Java才提供這樣的反射機制,或者說內省機制,可以實現我們的無理要求。編寫一個配置文件emp.properties:
#成功響應
1000=Success
#向客戶發送普通文本消息
2000=Load
#客戶向服務器發送普通文本消息
3000=Store
文件中的鍵名是客戶將發給我的消息頭,客戶發送1000給我,那么我就執行Success類的act方法,類似的如果發送2000給我,那就執行Load類的act方法,這樣一來系統就完全符合開閉原則了,如果要添加新的功能,完全不需要修改已有代碼,只需要在配置文件中添加對應規則,然后編寫新的類,實現act方法就ok,即使我棄這個項目而去,它將來也可以很好的擴展。這樣的系統具備了非常良好的擴展性和可插入性。
下面這個例子體現了動態加載的功能,程序在執行過程中才知道應該實例化哪個類:
import java.lang.reflect.*; import java.util.Properties; import java.io.FileInputStream; import java.util.List; //這個程序是針對Operator編程的,所以無需做任何修改,直接提供Load和Store類,就可以支持2000、3000做參數的調用 //有了這樣的內省機制,可以把接口的作用發揮到極至,設計模式也更能體現出威力,而不僅僅供我們飯后閑聊。 public class TestReflect { //加載配置文件,查詢消息頭對應的類名 private String loadProtocal(String header) { String result=null; try { Properties prop=new Properties(); // FileInputStream fis=new FileInputStream("emp.properties"); // id = prop.getProperty(idString); // prop.load(fis); // fis.close(); prop.load(getTCL().getResourceAsStream("emp.properties")); result=prop.getProperty(header); }catch(Exception e) { System.out.println(e); } return result; } private static ClassLoader getTCL() throws IllegalAccessException, InvocationTargetException { Method method = null; try { method = Thread.class.getMethod("getContextClassLoader", null); } catch (NoSuchMethodException e) { return null; } return (ClassLoader)method.invoke(Thread.currentThread(), null); } //針對消息作出響應,利用反射導入對應的類 public String response(String header,String content,String content2,List list) { String result=null; String s=null; try { /* * 導入屬性文件emp.properties,查詢header所對應的類的名字 * 通過反射機制動態加載匹配的類,所有的類都被Operator接口隔離 * 可以通過修改屬性文件、添加新的類(繼承MsgOperator接口)來擴展協議 */ s="org.bromon.reflect."+this.loadProtocal(header).trim(); //加載類 System.out.println("s==="+s);//打印 s===org.bromon.reflect.Success Class c=Class.forName(s); //java.lang.reflect.Methods 是用來描述某個類中單個方法的一個類 // Method m[] = c.getDeclaredMethods();// // for (int i = 0; i < m.length; i++)// // System.out.println(m[i].toString()); // 打印 public java.util.List org.bromon.reflect.Success.act(java.util.List) //創建類的事例 Operator mo=(Operator)c.newInstance(); System.out.println("mo==="+mo); //構造參數列表 Class params[]=new Class[3]; // params[0]=Class.forName("java.util.List"); params[0]=Class.forName("java.lang.String"); params[1]=Class.forName("java.lang.String"); params[2]=Class.forName("java.util.List"); System.out.println("params[0]==="+params[0]); // //查詢act方法 Method m=c.getMethod("act",params); System.out.println("method=="+m.toString()); Object[] args=new Object[3]; args[0]=content; args[1]=content2; args[2]=list; // //調用方法并且獲得返回 Object returnObject=m.invoke(mo,args);//這個地方出問題了,拋異常~~~~ // System.out.println("returnObject==="+returnObject); List result2 = (List)returnObject; result = (String)result2.get(0); System.out.println("result2=="+result2); // }catch(Exception e) { System.out.println("Handler-response:"+e);//Handler-response:java.lang.IllegalArgumentException: argument type mismatch //IllegalArgumentException - 如果該方法是實例方法,且指定對象參數不是聲明基礎方法的類或接口(或其中的子類或實現程序)的實例; //如果實參和形參的數量不相同;如果基本參數的解包轉換失敗;或者如果在解包后,無法通過方法調用轉換將參數值轉換為相應的形參類型。 } return result; } public static void main(String args[]) { TestReflect tr=new TestReflect(); List list = new java.util.ArrayList(); list.add("測試List"); tr.response("2000","Load1","Load2",list);//1000是Success,2000是Load tr.response("1000","Success1","Success2",list);//1000是Success,2000是Load } }
測試一下,run一下TestReflect類,打印內容有,great!!
result2==[Load1, Load2, [測試List]]
result2==[Success1, Success2, [測試List]]
這個程序是針對Operator編程的,所以無需做任何修改,直接提供Load和Store類,就可以支持2000、3000做參數的調用。
有了這樣的內省機制,可以把接口的作用發揮到極至,設計模式也更能體現出威力,而不僅僅供我們飯后閑聊.
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!