日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
讀懂框架設(shè)計的靈魂—Java反射機制

本文轉(zhuǎn)載自微信公眾號「飛天小牛肉」,作者飛天小牛肉 。轉(zhuǎn)載本文請聯(lián)系飛天小牛肉公眾號。

創(chuàng)新互聯(lián):自2013年創(chuàng)立以來為各行業(yè)開拓出企業(yè)自己的“網(wǎng)站建設(shè)”服務(wù),為1000多家公司企業(yè)提供了專業(yè)的網(wǎng)站設(shè)計制作、成都做網(wǎng)站、網(wǎng)頁設(shè)計和網(wǎng)站推廣服務(wù), 按需規(guī)劃網(wǎng)站由設(shè)計師親自精心設(shè)計,設(shè)計的效果完全按照客戶的要求,并適當(dāng)?shù)奶岢龊侠淼慕ㄗh,擁有的視覺效果,策劃師分析客戶的同行競爭對手,根據(jù)客戶的實際情況給出合理的網(wǎng)站構(gòu)架,制作客戶同行業(yè)具有領(lǐng)先地位的。

Java 反射機制對于小白來說,真的是一道巨大的坎兒,其他的東西吧,無非就是內(nèi)容多點,多看看多背背就好了,反射真的就是不管看了多少遍不理解就還是不理解,而且學(xué)校里面的各大教材應(yīng)該都沒有反射這個章節(jié),有也是一帶而過。說實話,在這篇文章之前,我對反射也并非完全了解,畢竟平常開發(fā)基本用不到,不過,看完這篇文章相信你對反射就沒啥疑點了。

全文脈絡(luò)思維導(dǎo)圖如下:

1. 拋磚引玉:為什么要使用反射前文我們說過,接口的使用提高了代碼的可維護(hù)性和可擴(kuò)展性,并且降低了代碼的耦合度。來看個例子:

首先,我們擁有一個接口 X 及其方法 test,和兩個對應(yīng)的實現(xiàn)類 A、B:

 
 
 
 
  1. public class Test {
  2.     
  3.     interface X {
  4.      public void test();
  5.  }
  6.     class A implements X{
  7.         @Override
  8.         public void test() {
  9.              System.out.println("I am A");
  10.         }
  11.     }
  12.     class B implements X{
  13.         @Override
  14.         public void test() {
  15.             System.out.println("I am B");
  16.     }
  17. }

通常情況下,我們需要使用哪個實現(xiàn)類就直接 new 一個就好了,看下面這段代碼:

 
 
 
 
  1. public class Test {    
  2.     ......
  3.  public static void main(String[] args) {
  4.         X a = create1("A");
  5.         a.test();
  6.         X b = create1("B");
  7.         b.test();
  8.     }
  9.     public static X create1(String name){
  10.         if (name.equals("A")) {
  11.             return new A();
  12.         } else if(name.equals("B")){
  13.             return new B();
  14.         }
  15.         return null;
  16.     }
  17. }

按照上面這種寫法,如果有成百上千個不同的 X 的實現(xiàn)類需要創(chuàng)建,那我們豈不是就需要寫上千個 if 語句來返回不同的 X 對象?

我們來看看看反射機制是如何做的:

 
 
 
 
  1. public class Test {
  2.     public static void main(String[] args) {
  3.   X a = create2("A");
  4.         a.test();
  5.         X b = create2("B");
  6.         b.testReflect();
  7.     }
  8.     
  9.  // 使用反射機制
  10.     public static X create2(String name){
  11.         Class class = Class.forName(name);
  12.         X x = (X) class.newInstance();
  13.         return x;
  14.     }
  15. }

向 create2() 方法傳入包名和類名,通過反射機制動態(tài)的加載指定的類,然后再實例化對象。

看完上面這個例子,相信諸位對反射有了一定的認(rèn)識。反射擁有以下四大功能:

  • 在運行時(動態(tài)編譯)獲知任意一個對象所屬的類。
  • 在運行時構(gòu)造任意一個類的對象。
  • 在運行時獲知任意一個類所具有的成員變量和方法。
  • 在運行時調(diào)用任意一個對象的方法和屬性。

上述這種「動態(tài)獲取信息、動態(tài)調(diào)用對象的方法」的功能稱為 Java 語言的反射機制。

2. 理解 Class 類

要想理解反射,首先要理解 Class 類,因為 Class 類是反射實現(xiàn)的基礎(chǔ)。

在程序運行期間,JVM 始終為所有的對象維護(hù)一個被稱為「運行時的類型標(biāo)識」,這個信息跟蹤著每個對象所屬的類的完整結(jié)構(gòu)信息,包括包名、類名、實現(xiàn)的接口、擁有的方法和字段等??梢酝ㄟ^專門的 Java 類訪問這些信息,這個類就是 Class類。我們可以把 Class 類理解為「類的類型」,一個 Class 對象,稱為類的類型對象,「一個 Class 對象對應(yīng)一個加載到 JVM 中的一個 .class 文件」。

在通常情況下,一定是先有類再有對象。以下面這段代碼為例,類的正常加載過程是這樣的:

 
 
 
 
  1. import java.util.Date; // 先有類
  2. public class Test {
  3.     public static void main(String[] args) {
  4.         Date date = new Date(); // 后有對象
  5.         System.out.println(date);
  6.     }
  7. }

首先 JVM 會將你的代碼編譯成一個 .class 字節(jié)碼文件,然后被類加載器(Class Loader)加載進(jìn) JVM 的內(nèi)存中,「同時會創(chuàng)建一個 Date 類的 Class 對象存到堆中」(注意這個不是 new 出來的對象,而是類的類型對象)。JVM 在創(chuàng)建 Date對象前,會先檢查其類是否加載,尋找類對應(yīng)的 Class 對象,若加載好,則為其分配內(nèi)存,然后再進(jìn)行初始化 new Date()。

需要注意的是,「每個類只有一個 Class 對象」,也就是說如果我們有第二條 new Date() 語句,JVM 不會再生成一個 Date 的 Class 對象,因為已經(jīng)存在一個了。這也使得我們可以利用 == 運算符實現(xiàn)兩個類對象比較的操作:

 
 
 
 
  1. System.out.println(date.getClass() == Date.getClass()); // true

OK,那么在加載完一個類后,堆內(nèi)存的方法區(qū)就產(chǎn)生了一個 Class 對象,這個對象就包含了完整的類的結(jié)構(gòu)信息,「我們可以通過這個 Class 對象看到類的結(jié)構(gòu)」,就好比一面鏡子。所以我們形象的稱之為:反射。

說的再詳細(xì)點,再解釋一下。上文說過,在通常情況下,一定是先有類再有對象,我們把這個通常情況稱為 “正”。那么反射中的這個 “反” 我們就可以理解為根據(jù)對象找到對象所屬的類(對象的出處)

 
 
 
 
  1. Date date = new Date();
  2. System.out.println(date.getClass()); // "class java.util.Date"

通過反射,也就是調(diào)用了 getClass() 方法后,我們就獲得了 Date 類對應(yīng)的 Class 對象,看到了 Date 類的結(jié)構(gòu),輸出了 Date 對象所屬的類的完整名稱,即找到了對象的出處。當(dāng)然,獲取 Class 對象的方式不止這一種。

3. 獲取 Class 類對象的四種方式

從 Class 類的源碼可以看出,它的構(gòu)造函數(shù)是私有的,也就是說只有 JVM 可以創(chuàng)建 Class 類的對象,我們不能像普通類一樣直接 new 一個 Class 對象。

我們只能通過已有的類來得到一個 Class類對象,Java 提供了四種方式:

「第一種:知道具體類的情況下可以使用」:

 
 
 
 
  1. Class alunbarClass = TargetObject.class;

但是我們一般是不知道具體類的,基本都是通過遍歷包下面的類來獲取 Class 對象,通過此方式獲取 Class 對象不會進(jìn)行初始化。

「第二種:通過 Class.forName()傳入全類名獲取」:

 
 
 
 
  1. Class alunbarClass1 = Class.forName("com.xxx.TargetObject");

這個方法內(nèi)部實際調(diào)用的是 forName0:

第 2 個 boolean 參數(shù)表示類是否需要初始化,默認(rèn)是需要初始化。一旦初始化,就會觸發(fā)目標(biāo)對象的 static 塊代碼執(zhí)行,static 參數(shù)也會被再次初始化。

「第三種:通過對象實例 instance.getClass() 獲取」:

 
 
 
 
  1. Date date = new Date();
  2. Class alunbarClass2 = date.getClass(); // 獲取該對象實例的 Class 類對象

「第四種:通過類加載器 xxxClassLoader.loadClass() 傳入類路徑獲取」

 
 
 
 
  1. class clazz = ClassLoader.LoadClass("com.xxx.TargetObject");

通過類加載器獲取 Class 對象不會進(jìn)行初始化,意味著不進(jìn)行包括初始化等一些列步驟,靜態(tài)塊和靜態(tài)對象不會得到執(zhí)行。這里可以和 forName 做個對比。

4. 通過反射構(gòu)造一個類的實例

上面我們介紹了獲取 Class 類對象的方式,那么成功獲取之后,我們就需要構(gòu)造對應(yīng)類的實例。下面介紹三種方法,第一種最為常見,最后一種大家稍作了解即可。

① 使用 Class.newInstance

舉個例子:

 
 
 
 
  1. Date date1 = new Date();
  2. Class alunbarClass2 = date1.getClass();
  3. Date date2 = alunbarClass2.newInstance(); // 創(chuàng)建一個與 alunbarClass2 具有相同類類型的實例

創(chuàng)建了一個與 alunbarClass2 具有相同類類型的實例。

需要注意的是,「newInstance方法調(diào)用默認(rèn)的構(gòu)造函數(shù)(無參構(gòu)造函數(shù))初始化新創(chuàng)建的對象。如果這個類沒有默認(rèn)的構(gòu)造函數(shù), 就會拋出一個異?!埂?/p>

② 通過反射先獲取構(gòu)造方法再調(diào)用

由于不是所有的類都有無參構(gòu)造函數(shù)又或者類構(gòu)造器是 private 的,在這樣的情況下,如果我們還想通過反射來實例化對象,Class.newInstance 是無法滿足的。

此時,我們可以使用 Constructor 的 newInstance 方法來實現(xiàn),先獲取構(gòu)造函數(shù),再執(zhí)行構(gòu)造函數(shù)。

從上面代碼很容易看出,Constructor.newInstance 是可以攜帶參數(shù)的,而 Class.newInstance 是無參的,這也就是為什么它只能調(diào)用無參構(gòu)造函數(shù)的原因了。

大家不要把這兩個 newInstance 方法弄混了。如果被調(diào)用的類的構(gòu)造函數(shù)為默認(rèn)的構(gòu)造函數(shù),采用Class.newInstance() 是比較好的選擇, 一句代碼就 OK;如果需要調(diào)用類的帶參構(gòu)造函數(shù)、私有構(gòu)造函數(shù)等, 就需要采用 Constractor.newInstance()

Constructor.newInstance 是執(zhí)行構(gòu)造函數(shù)的方法。我們來看看獲取構(gòu)造函數(shù)可以通過哪些渠道,作用如其名,以下幾個方法都比較好記也容易理解,返回值都通過 Cnostructor 類型來接收。

「批量獲取構(gòu)造函數(shù)」:

1)獲取所有"公有的"構(gòu)造方法

 
 
 
 
  1. public Constructor[] getConstructors() { }

2)獲取所有的構(gòu)造方法(包括私有、受保護(hù)、默認(rèn)、公有)

 
 
 
 
  1. public Constructor[] getDeclaredConstructors() { }

「單個獲取構(gòu)造函數(shù)」:

1)獲取一個指定參數(shù)類型的"公有的"構(gòu)造方法

 
 
 
 
  1. public Constructor getConstructor(Class... parameterTypes) { }

2)獲取一個指定參數(shù)類型的"構(gòu)造方法",可以是私有的,或受保護(hù)、默認(rèn)、公有

 
 
 
 
  1. public Constructor getDeclaredConstructor(Class... parameterTypes) { }

舉個例子:

 
 
 
 
  1. package fanshe;
  2. public class Student {
  3.  //(默認(rèn)的構(gòu)造方法)
  4.  Student(String str){
  5.   System.out.println("(默認(rèn))的構(gòu)造方法 s = " + str);
  6.  }
  7.  // 無參構(gòu)造方法
  8.  public Student(){
  9.   System.out.println("調(diào)用了公有、無參構(gòu)造方法執(zhí)行了。。。");
  10.  }
  11.  // 有一個參數(shù)的構(gòu)造方法
  12.  public Student(char name){
  13.   System.out.println("姓名:" + name);
  14.  }
  15.  // 有多個參數(shù)的構(gòu)造方法
  16.  public Student(String name ,int age){
  17.   System.out.println("姓名:"+name+"年齡:"+ age);//這的執(zhí)行效率有問題,以后解決。
  18.  }
  19.  // 受保護(hù)的構(gòu)造方法
  20.  protected Student(boolean n){
  21.   System.out.println("受保護(hù)的構(gòu)造方法 n = " + n);
  22.  }
  23.  // 私有構(gòu)造方法
  24.  private Student(int age){
  25.   System.out.println("私有的構(gòu)造方法年齡:"+ age);
  26.  }
  27. }
  28. ----------------------------------
  29.     
  30. public class Constructors {
  31.  public static void main(String[] args) throws Exception {
  32.   // 加載Class對象
  33.   Class clazz = Class.forName("fanshe.Student");
  34.         
  35.   // 獲取所有公有構(gòu)造方法
  36.   Constructor[] conArray = clazz.getConstructors();
  37.   for(Constructor c : conArray){
  38.    System.out.println(c);
  39.   }
  40.         
  41.   // 獲取所有的構(gòu)造方法(包括:私有、受保護(hù)、默認(rèn)、公有)
  42.   conArray = clazz.getDeclaredConstructors();
  43.   for(Constructor c : conArray){
  44.    System.out.println(c);
  45.   }
  46.         
  47.   // 獲取公有、無參的構(gòu)造方法
  48.         // 因為是無參的構(gòu)造方法所以類型是一個null,不寫也可以:這里需要的是一個參數(shù)的類型,切記是類型
  49.   // 返回的是描述這個無參構(gòu)造函數(shù)的類對象。
  50.   Constructor con = clazz.getConstructor(null);
  51.   Object obj = con.newInstance(); // 調(diào)用構(gòu)造方法
  52.   
  53.   // 獲取私有構(gòu)造方法
  54.   con = clazz.getDeclaredConstructor(int.class);
  55.   System.out.println(con);
  56.   con.setAccessible(true); // 為了調(diào)用 private 方法/域 我們需要取消安全檢查
  57.   obj = con.newInstance(12); // 調(diào)用構(gòu)造方法
  58.  }
  59. }

③ 使用開源庫 Objenesis

Objenesis 是一個開源庫,和上述第二種方法一樣,可以調(diào)用任意的構(gòu)造函數(shù),不過封裝的比較簡潔:

 
 
 
 
  1. public class Test {
  2.     // 不存在無參構(gòu)造函數(shù)
  3.     private int i;
  4.     public Test(int i){
  5.         this.i = i;
  6.     }
  7.     public void show(){
  8.         System.out.println("test..." + i);
  9.     }
  10. }
  11. ------------------------
  12.     
  13. public static void main(String[] args) {
  14.         Objenesis objenesis = new ObjenesisStd(true);
  15.         Test test = objenesis.newInstance(Test.class);
  16.         test.show();
  17.     }

使用非常簡單,Objenesis 由子類 ObjenesisObjenesisStd實現(xiàn)。詳細(xì)源碼此處就不深究了,了解即可。

5. 通過反射獲取成員變量并使用

和獲取構(gòu)造函數(shù)差不多,獲取成員變量也分批量獲取和單個獲取。返回值通過Field 類型來接收。

「批量獲取」:

1)獲取所有公有的字段

 
 
 
 
  1. public Field[] getFields() { }

2)獲取所有的字段(包括私有、受保護(hù)、默認(rèn)的)

 
 
 
 
  1. public Field[] getDeclaredFields() { }

「單個獲取」:

1)獲取一個指定名稱的公有的字段

 
 
 
 
  1. public Field getField(String name) { }

2)獲取一個指定名稱的字段,可以是私有、受保護(hù)、默認(rèn)的

 
 
 
 
  1. public Field getDeclaredField(String name) { }

獲取到成員變量之后,如何修改它們的值呢?

set 方法包含兩個參數(shù):

  • obj:哪個對象要修改這個成員變量
  • value:要修改成哪個值

舉個例子:

 
 
 
 
  1. package fanshe.field;
  2. public class Student {
  3.  public Student(){
  4.         
  5.  }
  6.  
  7.  public String name;
  8.  protected int age;
  9.  char sex;
  10.  private String phoneNum;
  11.  
  12.  @Override
  13.  public String toString() {
  14.   return "Student [name=" + name + ", age=" + age + ", sex=" + sex
  15.     + ", phoneNum=" + phoneNum + "]";
  16.  }
  17. }
  18. ----------------------------------
  19.     
  20. public class Fields {
  21.     public static void main(String[] args) throws Exception {
  22.         // 獲取 Class 對象
  23.         Class stuClass = Class.forName("fanshe.field.Student");
  24.         // 獲取公有的無參構(gòu)造函數(shù)
  25.         Constructor con = stuClass.getConstructor();
  26.   
  27.   // 獲取私有構(gòu)造方法
  28.   con = clazz.getDeclaredConstructor(int.class);
  29.   System.out.println(con);
  30.   con.setAccessible(true); // 為了調(diào)用 private 方法/域 我們需要取消安全檢查
  31.   obj = con.newInstance(12); // 調(diào)用構(gòu)造方法
  32.         
  33.         // 獲取所有公有的字段
  34.         Field[] fieldArray = stuClass.getFields();
  35.         for(Field f : fieldArray){
  36.             System.out.println(f);
  37.         }
  38.          // 獲取所有的字段 (包括私有、受保護(hù)、默認(rèn)的)
  39.         fieldArray = stuClass.getDeclaredFields();
  40.         for(Field f : fieldArray){
  41.             System.out.println(f);
  42.         }
  43.         // 獲取指定名稱的公有字段
  44.         Field f = stuClass.getField("name");
  45.         Object obj = con.newInstance(); // 調(diào)用構(gòu)造函數(shù),創(chuàng)建該類的實例
  46.         f.set(obj, "劉德華"); // 為 Student 對象中的 name 屬性賦值
  47.         // 獲取私有字段
  48.         f = stuClass.getDeclaredField("phoneNum");
  49.         f.setAccessible(true); // 暴力反射,解除私有限定
  50.         f.set(obj, "18888889999"); // 為 Student 對象中的 phoneNum 屬性賦值
  51.     }
  52. }

6. 通過反射獲取成員方法并調(diào)用

同樣的,獲取成員方法也分批量獲取和單個獲取。返回值通過 Method 類型來接收。

「批量獲取」:

1)獲取所有"公有方法"(包含父類的方法,當(dāng)然也包含 Object 類)

 
 
 
 
  1. public Method[] getMethods() { }

2)獲取所有的成員方法,包括私有的(不包括繼承的)

 
 
 
 
  1. public Method[] getDeclaredMethods() { }

「單個獲取」:

獲取一個指定方法名和參數(shù)類型的成員方法:

 
 
 
 
  1. public Method getMethod(String name, Class... parameterTypes)

獲取到方法之后該怎么調(diào)用它們呢?

invoke 方法中包含兩個參數(shù):

  • obj:哪個對象要來調(diào)用這個方法
  • args:調(diào)用方法時所傳遞的實參

舉個例子:

 
 
 
 
  1. package fanshe.method;
  2.  
  3. public class Student {
  4.  public void show1(String s){
  5.   System.out.println("調(diào)用了:公有的,String參數(shù)的show1(): s = " + s);
  6.  }
  7.  protected void show2(){
  8.   System.out.println("調(diào)用了:受保護(hù)的,無參的show2()");
  9.  }
  10.  void show3(){
  11.   System.out.println("調(diào)用了:默認(rèn)的,無參的show3()");
  12.  }
  13.  private String show4(int age){
  14.   System.out.println("調(diào)用了,私有的,并且有返回值的,int參數(shù)的show4(): age = " + age);
  15.   return "abcd";
  16.  }
  17. }
  18. -------------------------------------------
  19. public class MethodClass {
  20.  public static void main(String[] args) throws Exception {
  21.   // 獲取 Class對象
  22.   Class stuClass = Class.forName("fanshe.method.Student");
  23.         // 獲取公有的無參構(gòu)造函數(shù)
  24.         Constructor con = stuClass.getConstructor();
  25.         
  26.   // 獲取所有公有方法
  27.   stuClass.getMethods();
  28.   Method[] methodArray = stuClass.getMethods();
  29.   for(Method m : methodArray){
  30.    System.out.println(m);
  31.   }
  32.         
  33.   // 獲取所有的方法,包括私有的
  34.   methodArray = stuClass.getDeclaredMethods();
  35.   for(Method m : methodArray){
  36.    System.out.println(m);
  37.   }
  38.         
  39.   // 獲取公有的show1()方法
  40.   Method m = stuClass.getMethod("show1", String.class);
  41.   System.out.println(m);
  42.   Object obj = con.newInstance(); // 調(diào)用構(gòu)造函數(shù),實例化一個 Student 對象
  43.   m.invoke(obj, "小牛肉");
  44.   
  45.   // 獲取私有的show4()方法
  46.   m = stuClass.getDeclaredMethod("show4", int.class);
  47.   m.setAccessible(true); // 解除私有限定
  48.   Object result = m.invoke(obj, 20);
  49.   System.out.println("返回值:" + result);
  50.  }
  51. }

7. 反射機制優(yōu)缺點

「優(yōu)點」:比較靈活,能夠在運行時動態(tài)獲取類的實例。

「缺點」:

1)性能瓶頸:反射相當(dāng)于一系列解釋操作,通知 JVM 要做的事情,性能比直接的 Java 代碼要慢很多。

2)安全問題:反射機制破壞了封裝性,因為通過反射可以獲取并調(diào)用類的私有方法和字段。

8. 反射的經(jīng)典應(yīng)用場景

反射在我們實際編程中其實并不會直接大量的使用,但是實際上有很多設(shè)計都與反射機制有關(guān),比如:

  • 動態(tài)代理機制
  • 使用 JDBC 連接數(shù)據(jù)庫
  • Spring / Hibernate 框架(實際上是因為使用了動態(tài)代理,所以才和反射機制有關(guān))

為什么說動態(tài)代理使用了反射機制,下篇文章會給出詳細(xì)解釋。

JDBC 連接數(shù)據(jù)庫

在 JDBC 的操作中,如果要想進(jìn)行數(shù)據(jù)庫的連接,則必須按照以下幾步完成:

  • 通過 Class.forName() 加載數(shù)據(jù)庫的驅(qū)動程序 (通過反射加載)
  • 通過 DriverManager 類連接數(shù)據(jù)庫,參數(shù)包含數(shù)據(jù)庫的連接地址、用戶名、密碼
  • 通過 Connection 接口接收連接
  • 關(guān)閉連接
 
 
 
 
  1. public static void main(String[] args) throws Exception {  
  2.         Connection con = null; // 數(shù)據(jù)庫的連接對象  
  3.         // 1. 通過反射加載驅(qū)動程序
  4.         Class.forName("com.mysql.jdbc.Driver"); 
  5.         // 2. 連接數(shù)據(jù)庫  
  6.         con = DriverManager.getConnection(
  7.             "jdbc:mysql://localhost:3306/test","root","root"); 
  8.         // 3. 關(guān)閉數(shù)據(jù)庫連接
  9.         con.close(); 
  10. }

Spring 框架

反射機制是 Java 框架設(shè)計的靈魂,框架的內(nèi)部都已經(jīng)封裝好了,我們自己基本用不著寫。典型的除了Hibernate 之外,還有 Spring 也用到了很多反射機制,最典型的就是 Spring 通過 xml 配置文件裝載 Bean(創(chuàng)建對象),也就是 「Spring 的 IoC」,過程如下:

  • 加載配置文件,獲取 Spring 容器
  • 使用反射機制,根據(jù)傳入的字符串獲得某個類的 Class 實例
 
 
 
 
  1. // 獲取 Spring 的 IoC 容器,并根據(jù) id 獲取對象
  2. public static void main(String[] args) {
  3.     // 1.使用 ApplicationContext 接口加載配置文件,獲取 spring 容器
  4.     ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
  5.     // 2. 使用反射機制,根據(jù)這個字符串獲得某個類的 Class 實例
  6.     IAccountService aService = (IAccountService) ac.getBean("accountServiceImpl");
  7.     System.out.println(aService);
  8. }

另外,「Spring AOP 由于使用了動態(tài)代理,所以也使用了反射機制」,這點我會在 Spring 的系列文章中詳細(xì)解釋。


分享題目:讀懂框架設(shè)計的靈魂—Java反射機制
文章路徑:http://m.5511xx.com/article/dhcjidi.html