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

下載本文檔

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

文檔簡(jiǎn)介

1、在 Java 中, 其反射和動(dòng)態(tài)代理機(jī)制極其強(qiáng)大,我們可以通過(guò)其反射機(jī)制在運(yùn)行時(shí)獲取信息。而代理是一種基本的設(shè)計(jì)模式,它是一種為了提供額外的或不同的操作而插入到真實(shí)對(duì)象中的某個(gè)對(duì)象。而Java 的動(dòng)態(tài)代理在代理上更進(jìn)一步,既能動(dòng)態(tài)的創(chuàng)建代理對(duì)象,又能動(dòng)態(tài)的調(diào)用代理 方法。 Java 的反射和動(dòng)態(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í)。那么讓我們?cè)谶@兩篇文章中分別詳細(xì)的學(xué)習(xí)IOC和AO

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

3、在 src 目錄下分別建立org.amigo. reflection 目錄和 xy 目錄來(lái)分別存放代理和反射的實(shí)例。我們?cè)趓eflection 目錄下建立ReflectionTest.java 文件,在該文件中編寫(xiě)代碼來(lái) 演示 Java Reflection API 的使用。該類(lèi)的代碼如下所示: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() 方法測(cè)試.* throwsException* /publicvoidgetNameTest() throws Exception System.out .println("=begin getNameTest=" );String name =" 阿蜜果 " ;Class cls = name.getClass();System. out .println( "String 類(lèi)名 : " + cls.getName();B

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

7、rintln(forName( "java.awt.Button");"clsTest name: "+ clsTest.getName();"=end getNameTest=);/* *ClassgetMethod()方法測(cè)試.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;" 返回值" ;" 測(cè)試testMethod() 方法調(diào)用" );"str= "+ str);" 名字 = " + (String) ht.get("name");" 結(jié)束testMethod() 方法調(diào)用" );運(yùn)行該例,可在控制臺(tái)看到如下內(nèi)容:=

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

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

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

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

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

16、cclass HelloWorldTest /*測(cè)試 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 我們可以很清楚的看到,該類(lèi)與 Chinese.java 類(lèi)和American.java 類(lèi)都存在強(qiáng)耦合關(guān)系。上面的例子讓我們想到的是在 但是當(dāng)發(fā)展到了 一定的階段后,N年以前,當(dāng)我們需要某個(gè)東西時(shí),我們一般是自己制造。工廠出現(xiàn)了,我們可以工廠中購(gòu)買(mǎi)我們需要的東西,這極大的方便了我們。在上例中,我們都是通過(guò)new來(lái)創(chuàng)建新的對(duì)象, 在開(kāi)發(fā)中,這種強(qiáng)耦合關(guān)系是我們所不提倡的,那么我們應(yīng)該如何來(lái)實(shí)現(xiàn)這個(gè)例子的解耦呢?我們接著想到了使用工廠模式,要新建一

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

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

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

21、thor <a href="mailto:xiexingxing1121">AmigoXie</a>* Creation date: 2007-10-2 -上午 10:45:13* /public class HelloWorldTest /* 測(cè)試 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"); 觀察此例我們可以看到,該類(lèi)不再與具體的實(shí)現(xiàn)類(lèi)Chinese 和 Ame

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

24、置文件即可,這種方法在上例的基礎(chǔ)上更進(jìn)一步的降低了類(lèi)與類(lèi)之間的耦合。我們還可以對(duì)某對(duì)象所需要的其它對(duì)象進(jìn)行注入,這種注入都是在配置文件中做的,Spring 的 IOC 的實(shí)現(xiàn)原理利用的就是Java 的反射機(jī)制,Spring 還充當(dāng)了工廠的角色,我們不需要自己建立工廠類(lèi)。Spring 的工廠類(lèi)會(huì)幫我們完成配置文件的讀取、利用反射機(jī)制注入對(duì)象等工作,我們可以通過(guò)bean 的名稱(chēng)獲取對(duì)應(yīng)的對(duì)象。下面讓我們看看如下的模擬Spring 的 bean 工廠類(lèi):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 工廠類(lèi) .* 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ī)制,通過(guò)class 的名稱(chēng)獲取Class 對(duì)象Class bean = Class.forName(cls.getText();/獲取對(duì)應(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)建一個(gè)對(duì)象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)用對(duì)象set 方法,并將值設(shè)置進(jìn)去 mSet.invoke(obj, value);/將對(duì)象放入 beanMap中,其中key為id值,value為對(duì)beanMap.put(id.getText(), obj); catch (Exception e) System.out.println(e.toString();/*通過(guò)bean 的 id 獲取 bean 的對(duì)象 .* param beanName bean 的 id* return 返回對(duì)應(yīng)對(duì)象* /public Object getBean(String beanName) Object obj = beanMap

32、.get(beanName);return obj;/*測(cè)試方法.* 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(); 該類(lèi)的 init(xml) 方法, 通過(guò)指定的xml 來(lái)給對(duì)象注入屬性,為了對(duì)該類(lèi)進(jìn)行測(cè)試,我還需要新建一個(gè)JavaBean 和在 src 目錄下新建一個(gè)名為config.xml 的配置文件。JavaBean的內(nèi)容如下:package org

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

評(píng)論

0/150

提交評(píng)論