本文向您展示Java反射机制的一个实例,该实例持简单EL的taglib,基本上实现了多级bean的属性的访问。
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到容器中的,这就是Java反射机制。
我们从容器中取出以bean为名字的Object,通过Java反射机制知道它的真实类型,然后通过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
ackage 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
好了,看看怎么通过一个串和一个对象来取出其中的字段来:
kage 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"));
}
}
分享到:
相关推荐
3. **高阶函数**:接受一个或多个函数作为参数或返回一个函数的函数。在JavaScript中,可以轻松实现这一点。 4. **组合**:通过组合小的纯函数来构建更大的功能模块。 #### 实际案例分析 假设有一个简单的书签应用...
当我们使用`new`关键字实例化这个构造函数时,就会生成一个新的对象,并且可以访问构造函数中定义的属性和方法。 例如,创建一个表示圆的构造函数`Circle`,可以通过以下方式: ```javascript function Circle(r) ...
标题中的“一个动态的Tip的实现”指的是在软件开发中创建一种动态提示信息的技术。Tip通常是指在用户界面上短暂显示的小型信息框,用于提供额外的帮助或指示。动态Tip意味着它可以根据用户的交互或者特定条件实时...
1. 闭包是指一个函数和其周围状态(词法环境)的引用捆绑在一起的组合。它允许函数在定义时的词法作用域外执行,因此可以在外部函数调用之后访问到内部函数的变量。闭包在JavaScript中是处理私有变量、模块化编程...
这是一个泛型扩展方法,接受一个委托作为参数,委托返回的是转换后的结果类型。 ```csharp public static IEnumerable<TResult> Select, TResult>( this IEnumerable<TSource> source, Func, TResult> selector )...
Let's Go 服务器的基线这是一个简单的 RESTFul 服务器,用于 Let' Go 在线商店服务器,它现在是用 Ruby 编写的。 它包含一些快速开始 Web 开发的基本部分。 作为 Web 服务器作为 ORM Sqlite3 作为数据库(单文件...
Let's Go 服务器的基线这是一个简单的 RESTFul 服务器,用于 Let' Go 在线商店服务器,它现在是用 Ruby 编写的。 它包含一些快速开始 Web 开发的基本部分。 作为 Web 服务器作为 ORM Sqlite3 作为数据库(单文件...
Let's Go 服务器的基线这是一个简单的 RESTFul 服务器,用于 Let' Go 在线商店服务器,它现在是用 Ruby 编写的。 它包含一些快速开始 Web 开发的基本部分。 作为 Web 服务器作为 ORM Sqlite3 作为数据库(单文件...
一个非常简单的 Reveal.js 模板 对于那些只想创建新幻灯片的人 git clone然后在浏览器中打开 index.html,就是这样。 其实你可以更进一步,试着生动地编辑你的幻灯片(见下面的部分)。 $ git clone git@github....
文件中有 2 个占位符: <!-- include source files here... --> <!-- include spec files here... --> 您应该记住的一件事是, source代码应该在针对它的specification测试BEFORE放置。 玩得开心!
git clone git@github.com:abruzzi/tw-testable-javascript.git 并初始化环境: cd tw-testable-javascript bower install 安装完成后,您应确保后端服务按预期工作: curl ...