利用Java的反射與代理實(shí)現(xiàn)IOC模式_第1頁
利用Java的反射與代理實(shí)現(xiàn)IOC模式_第2頁
利用Java的反射與代理實(shí)現(xiàn)IOC模式_第3頁
利用Java的反射與代理實(shí)現(xiàn)IOC模式_第4頁
利用Java的反射與代理實(shí)現(xiàn)IOC模式_第5頁
已閱讀5頁,還剩8頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、在 Java 中, 其反射和動態(tài)代理機(jī)制極其強(qiáng)大,我們可以通過其反射機(jī)制在運(yùn)行時獲取信息。而代理是一種基本的設(shè)計(jì)模式,它是一種為了提供額外的或不同的操作而插入到真實(shí)對象中的某個對象。而Java 的動態(tài)代理在代理上更進(jìn)一步,既能動態(tài)的創(chuàng)建代理對象,又能動態(tài)的調(diào)用代理 方法。 Java 的反射和動態(tài)代理機(jī)制,使Java 變得更加強(qiáng)大。Spring 框架這幾年風(fēng)頭正勁,雖然使用者眾多,但真正了解其內(nèi)部實(shí)現(xiàn)原理的朋友卻并不是很多。其實(shí),了解它的內(nèi)部實(shí)現(xiàn)機(jī)制和設(shè)計(jì)思想是很有必要的大家都知道,Spring 框架的IOC和AOP部分功能強(qiáng)大,很值得我們學(xué)習(xí)。那么讓我們在這兩篇文章中分別詳細(xì)的學(xué)習(xí)IOC和AO

2、P的實(shí)現(xiàn)吧。在本文中,主要講述的是用Java的反射機(jī)制實(shí)現(xiàn)IOCo下 面,讓我們開始IOC之旅吧!Java 反射機(jī)制概述與初探Java 的反射機(jī)制是Java 語言的一個重要特性,Java 具有的 比較突出的動態(tài)機(jī)制就是反射( reflection 。通過它,我們可以獲取如下信息:1 在運(yùn)行時判斷任意一個對象所屬的類;2 在運(yùn)行時獲取類的對象;3 在運(yùn)行時獲得類所具有的成員變量和方法等。下面讓我們通過調(diào)用一個Java Reflection API 的演示實(shí)例來見識一下反射機(jī)制的強(qiáng)大。首先在 IDE 中建立名為reflection_proxy 的 Java 工程,并建立存放源文件的目錄src ,并

3、在 src 目錄下分別建立org.amigo. reflection 目錄和 xy 目錄來分別存放代理和反射的實(shí)例。我們在reflection 目錄下建立ReflectionTest.java 文件,在該文件中編寫代碼來 演示 Java Reflection API 的使用。該類的代碼如下所示:package org.amigo.reflection;import java.awt.Button;import java.lang.reflect.Method;import java.util.Hashtable;/* 初探 Java 的反射機(jī)制.*author <

4、;a href="mailto:xiexingxing1121">AmigoXie </a>*Creationdate:2007 - 10-2-上午 10:13:48*/publicclass ReflectionTest /* paramargs* /publicstaticvoid main(String args) throws Exception ReflectionTest reflection =new ReflectionTest();reflection.getNameTest();System. out .println( "&

5、quot; );reflection.getMethodTest();/* Class 的 getName() 方法測試.* throwsException* /publicvoidgetNameTest() throws Exception System.out .println("=begin getNameTest=" );String name =" 阿蜜果 " ;Class cls = name.getClass();System. out .println( "String 類名 : " + cls.getName();B

6、utton btn =new Button();Class btnClass = btn.getClass();System. out .println( "Button 類名 : " + btnClass.getName();Class superBtnClass = btnClass.getSuperclass();System. out .println( "Button 的父類名: " + superBtnClass.getName();Class clsTest = Class.System.System.out .println(out .p

7、rintln(forName( "java.awt.Button");"clsTest name: "+ clsTest.getName();"=end getNameTest=);/* *ClassgetMethod()方法測試.System. out .println(begin getMethodTest);Class cls = Class. Class ptypes = ptypes0 = Class. ptypes1 = Class.);forName( "org.amigo.reflection.ReflectionTe

8、st new Class2;forName( "java.lang.String");forName( "java.util.Hashtable");Method method = cls.getMethod("testMethod" , ptypes);Object args =new Object2;args0 = "hello, my dear!" ;Hashtable<String, String> ht = ht.put( "name" , " 阿蜜果 "

9、; ); args1 = ht;new Hashtable<String, String>();String returnStr = (String) method.invoke(newReflectionTest(), args);System. out .println( "returnStr= "+ returnStr);System. out .println( "=end getMethodTest=" );throws Exception public String testMethod(String str, Hashtable

10、 ht)String returnStr =System.out.println(System.out.println(System.out.println(System.out.println(return returnStr;" 返回值" ;" 測試testMethod() 方法調(diào)用" );"str= "+ str);" 名字 = " + (String) ht.get("name");" 結(jié)束testMethod() 方法調(diào)用" );運(yùn)行該例,可在控制臺看到如下內(nèi)容:=

11、begin getNameTest=String 類名: java.lang.StringButton 類名: java.awt.ButtonButton 的父類名: java.awt.ComponentclsTest name: java.awt.Button=end getNameTest= =begin getMethodTest=測試 testMethod() 方法調(diào)用 str= hello, my dear! 名字 = 阿蜜果結(jié)束 testMethod() 方法調(diào)用returnStr= 返回值=end getMethodTest=分析運(yùn)行結(jié)果,我們可以發(fā)現(xiàn),Java 的反射機(jī)制使得我

12、們在運(yùn)行時能夠判斷一個對象所屬的類,獲取對象的方法并得其進(jìn)行調(diào)用,并獲取方法的返回結(jié)果等功能。IOC 使用的背景在我們?nèi)粘5脑O(shè)計(jì)中,類與類之間存在著千絲萬縷的關(guān)系,如果兩個類存在著強(qiáng)耦合關(guān)系,那么在維護(hù)時,一個類的修改很可能會牽動另一個類的關(guān)聯(lián)修改,從而使得我們的維護(hù)工作步履維艱。下面讓我們來看這樣的一個強(qiáng)耦合反面例子。首先我們建立一個Chinese.java 類,該類的 sayHelloWorld(Stringname)方法,用中文對名為name的人問好,其內(nèi)容如下:package org.amigo.reflection;/* 中國人類.*author <a href="m

13、ailto:xiexingxing1121">AmigoXie </a>*Creationdate:2007 - 10-2-上午 10:37:17*/publicclass Chinese /* 用中文對某人問好.* paranname 姓名*/publicvoid sayHelloWorld(String name) String helloWorld ="你好,"+ name;System. out .println(helloWorld); I 下面我們接著建立一個American.java 類,該類的 sayHelloWorld(Stri

14、ng name) 方法,用英文對名為name的人問好,其內(nèi)容如下:package org.amigo.reflection;/*美國人類.*author <a href="mailto:xiexingxing1121">AmigoXie </a>*version 1.0*Creationdate:2007 - 10-2-上午 10:41:27*/publicclass American /* 用英文對某人問好.* paranname 姓名* / publicvoid sayHelloWorld(String name) String helloWor

15、ld ="Hello , " + name;System. out .println(helloWorld); 最后我們編寫一個測試類對這兩個類的sayHelloWorld(String name)方法進(jìn)行測試,下面是該類的內(nèi)容:package org.amigo.reflection;/*HelloWorld 測試.</a></a>*author <a href="mailto:xiexingxing1121">AmigoXie*Creationdate:2007 - 10-2-上午 10:45:13*/ publi

16、cclass HelloWorldTest /*測試 Chinese 和 American 的 sayHelloWorld() 方法. paranargs* author<a href="mailto:xiexingxing1121">AmigoXie*Creationdate:2007- 10-2-上午 10:43:51*/publicstaticvoidmain(String args) Chinese chinese =chinese.sayHelloWorld(new Chinese。;"阿蜜果");American american

17、 =american.sayHelloWorld( new American。;"Amigo");觀察HelloWorldTest 我們可以很清楚的看到,該類與 Chinese.java 類和American.java 類都存在強(qiáng)耦合關(guān)系。上面的例子讓我們想到的是在 但是當(dāng)發(fā)展到了 一定的階段后,N年以前,當(dāng)我們需要某個東西時,我們一般是自己制造。工廠出現(xiàn)了,我們可以工廠中購買我們需要的東西,這極大的方便了我們。在上例中,我們都是通過new來創(chuàng)建新的對象, 在開發(fā)中,這種強(qiáng)耦合關(guān)系是我們所不提倡的,那么我們應(yīng)該如何來實(shí)現(xiàn)這個例子的解耦呢?我們接著想到了使用工廠模式,要新建一

18、個工廠類來完成對象的創(chuàng)建,并采用依賴接口的方式,此時需要對代碼進(jìn)行如下修改: 首先建立接口類 Human.java ,其內(nèi)容如下。package org.amigo.reflection;我們需/*人類接口類.* author <a href="mailto:xiexingxing1121">AmigoXie</a>* Creation date: 2007-10-2 -上午 11:04:56*/public interface Human /* 對某人問好.* param name 姓名*/public void sayHelloWorld(Str

19、ing name);并將American.java 類和Chinese.java 類改為實(shí)現(xiàn)該接口,即類頭分別改成:public classAmerican implements Human 和 public class Chinese implements Human 接著編寫HumanFactory.java 工廠類,其內(nèi)容為: package org.amigo.reflection;/*工廠類.* author <a href="mailto:xiexingxing1121">AmigoXie</a>* Creation date: 2007

20、-10-2 -上午 11:09:30*/public class HumanFactory /*通過類型字段獲取人的相應(yīng)實(shí)例param type 類型return返回相應(yīng)實(shí)例*/public Human getHuman(String type) if ("chinese".equals(type) return new Chinese(); else return new American();最后我們還需要修改測試類HelloWorld.java 類,修改后的內(nèi)容如下:package org.amigo.reflection;/* HelloWorld 測試 .* au

21、thor <a href="mailto:xiexingxing1121">AmigoXie</a>* Creation date: 2007-10-2 -上午 10:45:13* /public class HelloWorldTest /* 測試 sayHelloWorld() 方法 .* param args* author <a href="mailto:xiexingxing1121">AmigoXie</a>* Creation date: 2007-10-2 -上午 10:43:51* / p

22、ublic static void main(String args) HumanFactory factory = new HumanFactory();Human human1 = factory.getHuman("chinese");human1.sayHelloWorld("阿蜜果 ");Human human2 = factory.getHuman("american");human2.sayHelloWorld("Amigo"); 觀察此例我們可以看到,該類不再與具體的實(shí)現(xiàn)類Chinese 和 Ame

23、rican 存在耦合關(guān)系,而只是與它們的接口類Human存在耦合關(guān)系,具體對象的獲取只是通過傳入字符串來獲取,很大程度上降低了類與類之間的耦合性。但是我們還是不太滿足,因?yàn)檫€需要通過chinese 和 american 在類中獲取實(shí)例,那么當(dāng)我們需要修改時實(shí)現(xiàn)時,我們還需要在類中修改這些字符串,那么還有沒有更好的辦法呢?讓我們在下節(jié)中進(jìn)行繼續(xù)探討。IOC 粉墨登場IOC( Inverse of Control )可翻譯為“控制反轉(zhuǎn)”,但大多數(shù)人都習(xí)慣將它稱為“依賴注入”。在Spring中,通過IOC可以將實(shí)現(xiàn)類、參數(shù)信息等配置在其對應(yīng)的配置文件中,那么當(dāng)需要更改實(shí)現(xiàn)類或參數(shù)信息時,只需要修改配

24、置文件即可,這種方法在上例的基礎(chǔ)上更進(jìn)一步的降低了類與類之間的耦合。我們還可以對某對象所需要的其它對象進(jìn)行注入,這種注入都是在配置文件中做的,Spring 的 IOC 的實(shí)現(xiàn)原理利用的就是Java 的反射機(jī)制,Spring 還充當(dāng)了工廠的角色,我們不需要自己建立工廠類。Spring 的工廠類會幫我們完成配置文件的讀取、利用反射機(jī)制注入對象等工作,我們可以通過bean 的名稱獲取對應(yīng)的對象。下面讓我們看看如下的模擬Spring 的 bean 工廠類:package org.amigo.reflection;import java.io.InputStream;import java.lang.r

25、eflect.Method;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import org.dom4j.Attribute;import org.dom4j.Document;import org.dom4j.Element;import org.dom4j.io.SAXReader;/ bean 工廠的初始化.* param xml xml 配置文件 */public void init(String xml) try /讀取指定的配置文件SAXReader reader = new SAX

26、Reader();ClassLoader classLoader =Thread.currentThread().getContextClassLoader();/從 class 目錄下獲取指定的xml 文件InputStream ins = classLoader.getResourceAsStream(xml);Document doc = reader.read(ins);Element root = doc.getRootElement();Element foo;* bean 工廠類 .* author <a href="mailto:xiexingxing1121&

27、quot;>AmigoXie</a>上午 10:04:41* Creation date: 2007-10-6 -*/public class BeanFactory private Map<String, Object> beanMap = new HashMap<String, Object>();/for遍歷 beani.hasNext();)(Iterator i = root.elementIterator("bean");foo = (Element) i.next();/獲取 bean 的屬性 id 和 classAt

28、tribute id = foo.attribute("id");Attribute cls = foo.attribute("class");/利用 Java 反射機(jī)制,通過class 的名稱獲取Class 對象Class bean = Class.forName(cls.getText();/獲取對應(yīng)class 的信息java.beans.BeanInfo info =java.beans.Introspector.getBeanInfo(bean);/獲取其屬性描述java.beans.PropertyDescriptor pd =info.get

29、PropertyDescriptors();/設(shè)置值的方法Method mSet = null;/創(chuàng)建一個對象Object obj = bean.newInstance();/遍歷該bean 的 property 屬性for(Iterator ite = foo.elementIterator("property");ite.hasNext();) Element foo2 = (Element) ite.next();/獲取該property 的name屬性Attribute name = foo2.attribute("name");String v

30、alue = null;/獲取該 property 的子元素value 的值for(Iterator ite1 =foo2.elementIterator("value"); ite1.hasNext();) Element node = (Element) ite1.next();value = node.getText();break;for (int k = 0; k < pd.length; k+) if(pdk.getName().equalsIgnoreCase(name.getText() mSet = pdk.getWriteMethod();/利用

31、Java 的反射極致調(diào)用對象set 方法,并將值設(shè)置進(jìn)去 mSet.invoke(obj, value);/將對象放入 beanMap中,其中key為id值,value為對beanMap.put(id.getText(), obj); catch (Exception e) System.out.println(e.toString();/*通過bean 的 id 獲取 bean 的對象 .* param beanName bean 的 id* return 返回對應(yīng)對象* /public Object getBean(String beanName) Object obj = beanMap

32、.get(beanName);return obj;/*測試方法.* param args* author <a href="mailto:xiexingxing1121">AmigoXie</a>* Creation date: 2007-10-6 -上午 11:21:14* /public static void main(String args) BeanFactory factory = new BeanFactory();factory.init("config.xml");JavaBean javaBean = (Ja

33、vaBean) factory.getBean("javaBean");System.out.println("userName=" + javaBean.getUserName();System.out.println("password=" + javaBean.getPassword(); 該類的 init(xml) 方法, 通過指定的xml 來給對象注入屬性,為了對該類進(jìn)行測試,我還需要新建一個JavaBean 和在 src 目錄下新建一個名為config.xml 的配置文件。JavaBean的內(nèi)容如下:package org

34、.amigo.reflection;/*簡單的bean ,用于測試* author <a href="mailto:xiexingxing1121">AmigoXie</a>* Creation date: 2007-10-6 -上午 11:24:30*/public class JavaBean private String userName;private String password;public String getPassword() return password;public String getUserName() return userName;public void setUserName(String userName) this.userName = userName;public void setPassword(String password) this.password =

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論