疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

java反射机制实例讲解


 

 
       本文向您展示Java反射机制的一个实例,该实例持简单EL的taglib,基本上实现了多级bean的属性的访问。JSP的规范中,有个表达式语言(Expression Language, 简称EL),可以算是一个微型的语言,其中对request, page, session, application中预存的JavaBean对象的引用方式很是简单。最近正好需要写一个支持简单EL的taglib,所以就研究了下Java反射机制,目前基本上实现了多级bean的属性的访问,经测试,还是可以用的。如:
 
1. public static void main(String[] args){  
2.     UserBean bean = new UserBean();  
3.     bean.setName("John Abruzzi");  
4.     bean.setNick("Abruzzi");  
5.     bean.setAge(24);  
6.       
7.     AddressBean addr = new AddressBean();  
8.     addr.setZip("0086");  
9.     addr.setStreet("Bell Street #12");  
10.     bean.setAddress(addr);  
11.       
12.     System.out.println(BeanParser.doParse(bean, "bean.address.street"));  
13.     System.out.println(BeanParser.doParse(bean, "bean.address.zip"));  
14.     System.out.println(BeanParser.doParse(bean, "bean.name"));  
15.     System.out.println(BeanParser.doParse(bean, "bean.nick"));  
16.     System.out.println(BeanParser.doParse(bean, "bean.age"));  
17. } 
        需要可以输出:
1. Bell Street #12 
2. 0086 
3. John Abruzzi  
4. Abruzzi  
5. 24 
反射,即由一个抽象的对象(如Object),取出这个具体对象的属性或者方法(就EL中关于Bean的引用来说,这个定义已经够了)。在EL中,对一个Bean的某字段进行引用,只需 ${bean.field},当然,这个bean是已经被set到容器中的,这就是Java反射机制。
我们从容器中取出以bean为名字的Object,通过Java反射机制知道它的真实类型,然后通过field以javabean规范拼出方法名,进行调用,如果这个表达式是多级的,如${bean.field.field},其中第一个field本身就是一个bean对象,同样需要递归的进行解析。
大概原理就是这些了,看代码吧:
现有一个UserBean, 其中的一个字段Address本身又是一个AddressBean。
         1. package elparser;  
         2.  
         3. public class AddressBean {  
         4.     private String street;  
         5.     private String zip;  
         6.       
         7.     public String getZip() {  
         8.         return zip;  
         9.     }  
        10.  
        11.     public void setZip(String zip) {  
        12.         this.zip = zip;  
        13.     }  
        14.  
        15.     public String getStreet() {  
        16.         return street;  
        17.     }  
        18.  
        19.     public void setStreet(String street) {  
        20.         this.street = street;  
        21.     }  
        22.       
        23. } 
然后是UserBean
         1. package elparser;  
         2.  
         3. public class UserBean {  
         4.     private String name;  
         5.     private String nick;  
         6.     private AddressBean address;  
         7.     private int age;  
         8.       
         9.     public int getAge(){  
        10.         return this.age;  
        11.     }  
        12.       
        13.     public void setAge(int age){  
        14.         this.age = age;  
        15.     }  
        16.       
        17.     public String getName() {  
        18.         return name;  
        19.     }  
        20.     public void setName(String name) {  
        21.         this.name = name;  
        22.     }  
        23.     public String getNick() {  
        24.         return nick;  
        25.     }  
        26.     public void setNick(String nick) {  
        27.         this.nick = nick;  
        28.     }  
        29.     public AddressBean getAddress() {  
        30.         return address;  
        31.     }  
        32.     public void setAddress(AddressBean address) {  
        33.         this.address = address;  
        34.     }  
        35. } 
      Bean都是很简单的,考虑到对基本类型的支持,所以在UserBean中加入一个int型的字段age好了,看看怎么通过一个串和一个对象来取出其中的字段来:
         1. package elparser;  
         2.  
         3. import java.lang.reflect.Method;  
         4.  
         5. public class BeanParser {  
         6.       
         7.     private static String getMethodName(String property, String prefix){  
         8.         String prop = Character.toUpperCase(property.charAt(0))+property.substring(1);  
         9.       
        10.         String methodName = prefix + prop;  
        11.       
        12.         return methodName;  
        13.     }  
        14.       
        15.     private static Object parse(Object bean, String expr){  
        16.         Class beanClass = bean.getClass();  
        17.           
        18.         Method method = null;  
        19.         Object result = null;  
        20.           
        21.         try{  
        22.             //这两步是关键,get方法不需要传入参数,所以只是new出两个空数组传入  
        23.             method = beanClass.getMethod(getMethodName(expr, "get"), new Class[]{});  
        24.             result = method.invoke(bean, new Object[]{});  
        25.         }catch(Exception e){  
        26.             System.out.println(e.getMessage());  
        27.         }  
        28.           
        29.         return result;  
        30.     }  
        31.       
        32.     public static Object doParse(Object bean, String expr){  
        33.         String keys[] = expr.split(".");  
        34.           
        35.         Object obj = null;  
        36.           
        37.         for(int i = 1; i < keys.length;i++){  
        38.             obj = parse(bean, keys[i]);  
        39.             bean = obj;  
        40.         }//递归parse  
        41.           
        42.         return obj;  
        43.     }  
        44.       
        45.     public static void main(String[] args){  
        46.         UserBean bean = new UserBean();  
        47.         bean.setName("John Abruzzi");  
        48.         bean.setNick("Abruzzi");  
        49.         bean.setAge(24);  
        50.           
        51.         AddressBean addr = new AddressBean();  
        52.         addr.setZip("0086");  
        53.         addr.setStreet("Bell Street #12");  
        54.         bean.setAddress(addr);  
        55.           
        56.         System.out.println(BeanParser.doParse(bean, "bean.address.street")); 
 
 
        57.         System.out.println(BeanParser.doParse(bean, "bean.address.zip"));  
        58.         System.out.println(BeanParser.doParse(bean, "bean.name"));  
        59.         System.out.println(BeanParser.doParse(bean, "bean.nick"));  
        60.         System.out.println(BeanParser.doParse(bean, "bean.age"));  
        61.     }  
        62. } 
代码比较简短,重要部分有注释,应该很容易理解。当然这篇文章主要是关于Java的反射机制,如果需要对EL完全支持,可以使用JavaCC做一个简单的分析器(Apache的commons中包含一个el的项目,就是用javacc写的分析器)。