浏览 4808 次
锁定老帖子 主题:Java反射机制的一个实例
精华帖 (0) :: 良好帖 (2) :: 新手帖 (1) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-04-03
最后修改:2009-04-03
JSP的规范中,有个表达式语言(Expression Language, 简称EL),可以算是一个微型的语言,其中对request, page, session, application中预存的JavaBean对象的引用方式很是简单。最近正好需要写一个支持简单EL的taglib,所以就研究了下Java中的反射机制,目前基本上实现了多级bean的属性的访问,经测试,还是可以用的。
如: public static void main(String[] args){ UserBean bean = new UserBean(); bean.setName("John Abruzzi"); bean.setNick("Abruzzi"); bean.setAge(24); AddressBean addr = new AddressBean(); addr.setZip("0086"); addr.setStreet("Bell Street #12"); bean.setAddress(addr); System.out.println(BeanParser.doParse(bean, "bean.address.street")); System.out.println(BeanParser.doParse(bean, "bean.address.zip")); System.out.println(BeanParser.doParse(bean, "bean.name")); System.out.println(BeanParser.doParse(bean, "bean.nick")); System.out.println(BeanParser.doParse(bean, "bean.age")); } 需要可以输出: Bell Street #12 0086 John Abruzzi Abruzzi 24 反射,即由一个抽象的对象(如Object),取出这个具体对象的属性或者方法(就EL中关于Bean的引用来说,这个定义已经够了)。在EL中,对一个Bean的某字段进行引用,只需 ${bean.field},当然,这个bean是已经被set到容器中的。
我们从容器中取出以bean为名字的Object,通过反射知道它的真实类型,然后通过field以javabean规范拼出方法名,进行调用,如果这个表达式是多级的,如${bean.field.field},其中第一个field本身就是一个bean对象,同样需要递归的进行解析。
大概原理就是这些了,看代码吧:
现有一个UserBean, 其中的一个字段Address本身又是一个AddressBean。
package elparser; public class AddressBean { private String street; private String zip; public String getZip() { return zip; } public void setZip(String zip) { this.zip = zip; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } }
然后是UserBean
package elparser; public class UserBean { private String name; private String nick; private AddressBean address; private int age; public int getAge(){ return this.age; } public void setAge(int age){ this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getNick() { return nick; } public void setNick(String nick) { this.nick = nick; } public AddressBean getAddress() { return address; } public void setAddress(AddressBean address) { this.address = address; } } Bean都是很简单的,考虑到对基本类型的支持,所以在UserBean中加入一个int型的字段age
好了,看看怎么通过一个串和一个对象来取出其中的字段来:
package elparser; import java.lang.reflect.Method; public class BeanParser { private static String getMethodName(String property, String prefix){ String prop = Character.toUpperCase(property.charAt(0))+property.substring(1); String methodName = prefix + prop; return methodName; } private static Object parse(Object bean, String expr){ Class beanClass = bean.getClass(); Method method = null; Object result = null; try{ //这两步是关键,get方法不需要传入参数,所以只是new出两个空数组传入 method = beanClass.getMethod(getMethodName(expr, "get"), new Class[]{}); result = method.invoke(bean, new Object[]{}); }catch(Exception e){ System.out.println(e.getMessage()); } return result; } public static Object doParse(Object bean, String expr){ String keys[] = expr.split("\\."); Object obj = null; for(int i = 1; i < keys.length;i++){ obj = parse(bean, keys[i]); bean = obj; }//递归parse return obj; } public static void main(String[] args){ UserBean bean = new UserBean(); bean.setName("John Abruzzi"); bean.setNick("Abruzzi"); bean.setAge(24); AddressBean addr = new AddressBean(); addr.setZip("0086"); addr.setStreet("Bell Street #12"); bean.setAddress(addr); System.out.println(BeanParser.doParse(bean, "bean.address.street")); System.out.println(BeanParser.doParse(bean, "bean.address.zip")); System.out.println(BeanParser.doParse(bean, "bean.name")); System.out.println(BeanParser.doParse(bean, "bean.nick")); System.out.println(BeanParser.doParse(bean, "bean.age")); } } 代码比较简短,重要部分有注释,应该很容易理解。当然这篇文章主要是关于Java的反射的,如果需要对EL完全支持,可以使用JavaCC做一个简单的分析器(Apache的commons中包含一个el的项目,就是用javacc写的分析器)。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-04-03
这个工具类真不错,项目中应该可以用到
|
|
返回顶楼 | |
发表时间:2009-04-03
正是来源于实际项目,呵呵。最近在做一个部分支持EL规范的工具。
|
|
返回顶楼 | |
发表时间:2009-04-09
如果用户们都使用JavaBean命名规范的话就最好了,可惜有的用户比较那个,什么都不按规范,不按套路出牌。不过这个工具还是很好用的,呵呵
|
|
返回顶楼 | |
发表时间:2009-04-09
还不错哦!
|
|
返回顶楼 | |
发表时间:2009-04-09
我们在项目中用到反射比较多,不过我现在很少使用方法来操作了,个人感觉JavaBean中的setXXX和getXXX有点多余(可以是接触脚本语言太多了吧)
我的做法是直接getField(xxx),然后setAccessible(true),就可以get了,这样写代码会少,也会清晰点(最起码不用组装方法名了,楼主的代码处理不了boolean属性) |
|
返回顶楼 | |
发表时间:2009-04-09
JavaBean中的getter/setter属于JavaBean规范的一部分,JSP/EL等中对bean的引用就可以基于这个规范来做,这个是最重要的。而且,如eclipse之类的IDE都可以自己生成getter/setter,所以代码量倒还不是很大。
我的代码目前对boolean的支持不够标准,谢谢提出,我有时间再好好改一下,呵呵。 |
|
返回顶楼 | |