Java內省詳解


  內省和反射有什么區別:

  反射式在運行狀態把Java類中的各種成分映射成相應的Java類,可以動態的獲取所有的屬性以及動態調用任意一個方法,強調的是運行狀態。 
  內省機制是通過反射來實現的,BeanInfo用來暴露一個bean的屬性、方法和事件,以后我們就可以操縱該JavaBean的屬性。

  1.通過PropertyDescriptor修改屬性方式

 1 public class BeanInfoUtil {  
 2     public static void setProperty(UserInfo userInfo,String userName)throws Exception{  
 3         PropertyDescriptor propDesc=new PropertyDescriptor(userName,UserInfo.class);  
 4         Method methodSetUserName=propDesc.getWriteMethod();  
 5         methodSetUserName.invoke(userInfo, "wong");  
 6         System.out.println("set userName:"+userInfo.getUserName());  
 7     }  
 8 
 9     public static void getProperty(UserInfo userInfo,String userName)throws Exception{  
10         PropertyDescriptor proDescriptor =new PropertyDescriptor(userName,UserInfo.class);  
11         Method methodGetUserName=proDescriptor.getReadMethod();  
12         Object objUserName=methodGetUserName.invoke(userInfo);  
13         System.out.println("get userName:"+objUserName.toString());  
14     }  
15 
16 }  

  2.通過Introspector類修改屬性

 1 public class BeanInfoUtil2 {  
 2     public static void setPropertyByIntrospector(UserInfo userInfo,  
 3             String userName) throws Exception {  
 4 
 5         BeanInfo beanInfo = Introspector.getBeanInfo(UserInfo.class);  
 6         PropertyDescriptor[] proDescrtptors = beanInfo.getPropertyDescriptors();  
 7         if (proDescrtptors != null && proDescrtptors.length > 0) {  
 8             for (PropertyDescriptor propDesc : proDescrtptors) {  
 9                 if (propDesc.getName().equals(userName)) {  
10                     Method methodSetUserName = propDesc.getWriteMethod();  
11                     methodSetUserName.invoke(userInfo, "alan");  
12                     System.out  
13                             .println("set userName:" + userInfo.getUserName());  
14                     break;  
15                 }  
16             }  
17         }  
18     }  
19 
20     public static void getPropertyByIntrospector(UserInfo userInfo,  
21             String userName) throws Exception {  
22         BeanInfo beanInfo = Introspector.getBeanInfo(UserInfo.class);  
23         PropertyDescriptor[] proDescrtptors = beanInfo.getPropertyDescriptors();  
24         if (proDescrtptors != null && proDescrtptors.length > 0) {  
25             for (PropertyDescriptor propDesc : proDescrtptors) {  
26                 if (propDesc.getName().equals(userName)) {  
27                     Method methodGetUserName = propDesc.getReadMethod();  
28                     Object objUserName = methodGetUserName.invoke(userInfo);  
29                     System.out  
30                             .println("get userName:" + objUserName.toString());  
31                     break;  
32                 }  
33             }  
34         }  
35     }  
36 
37 }  

  注意事項,在上述修改JavaBean屬性的時候,如果數據類型不對的話,會報錯。例如BeanInfoUtil.setProperty(userInfo, “age”);報錯是應為age屬性是int數據類型,而setProperty方法里面默認給age屬性賦的值是String類型。所以會爆出argument type mismatch參數類型不匹配的錯誤信息。 
  為了解決上述問題,Apache開發了一套簡單、易用的API來操作Bean的屬性——BeanUtils工具包。 

  

public static void main(String[] args) throws Exception {     
        Point point = new Point(2, 5);     
        String proName = "x";     
        BeanUtils.setProperty(point, proName, "8");     
        System.out.println(point.getX());// 8     
        System.out.println(BeanUtils.getProperty(point, proName));// 8     
        System.out.println(BeanUtils.getProperty(point, proName).getClass().getName());// java.lang.String     
        
        BeanUtils.setProperty(point, proName, 8);     
       System.out.println(BeanUtils.getProperty(point, proName).getClass().getName());// java.lang.String     
   }     
   //我們看到雖然屬性x的類型是Integer,但是我們設置的時候無論是Integer還是String,BeanUtils的內部都是當成String來處理的。  

  BeanUtils支持javabean屬性的級聯操作;

 1 public static void main(String[] args) throws Exception {     
 2     Point point = new Point(2, 5);//在point中加一個屬性 private Date birth = new Date();並產生setter/getter方法     
 3     String proName = "birth";     
 4     Date date= new Date();     
 5     date.setTime(10000);     
 6     BeanUtils.setProperty(point, proName, date);     
 7     System.out.println(BeanUtils.getProperty(point, proName));     
 8          
 9     BeanUtils.setProperty(point, "birth.time", 10000);     
10     System.out.println(BeanUtils.getProperty(point, "birth.time"));//10000     
11 }     
12 //之所以可以 BeanUtils.setProperty(point, "birth.time", 10000);這樣寫,那是因為Date類中有getTime()和setTime()方法,即Date類中相當於有time這個屬性。   

  BeanUtils和PropertyUtils對比:

 1 public static void main(String[] args) throws Exception {     
 2     Point point = new Point(2, 5);     
 3     String proName = "x";     
 4     BeanUtils.setProperty(point, proName, "8");     
 5     System.out.println(BeanUtils.getProperty(point, proName));//8     
 6     System.out.println(BeanUtils.getProperty(point, proName).getClass().getName());//java.lang.String     
 7          
 8 // PropertyUtils.setProperty(point, proName, "8");//exception:argument type mismatch     
 9     PropertyUtils.setProperty(point, proName, 8);     
10     System.out.println(PropertyUtils.getProperty(point, proName));//8     
11     System.out.println(PropertyUtils.getProperty(point, proName).getClass().getName());//java.lang.Integer     
12 }     
13 //BeanUtils它以字符串的形式對javabean進行轉換,而PropertyUtils是以原本的類型對javabean進行操作。如果類型不對,就會有argument type mismatch異常。  

  理解了相應的原理,那些現成的工具用起來就會更舒服,如Beanutils與 PropertyUtils工具。這兩個工具設置屬性的時候一個主要區別是PropertyUtils.getPropety方法獲得的屬性值的類型為該 屬性本來的類型,而BeanUtils.getProperty則是將該屬性的值轉換成字符串后才返回。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM