Fel是最近javaeye比较火的关键词,这是由网友lotusyu开发的一个高性能的EL,从作者给出的数据来看,性能非常优异,跟前段时间温少开源的Simple EL有的一拼。首先要说,这是个好现象,国内的开源项目越来越多,可以看出开发者的水平是越来越高了,比如我最近还看到有人开源的类似kestel的轻量级MQ——fqueue也非常不错,有兴趣可以看下我的分析《fqueue初步分析》。
expression string -> antlr -> AST -> comiple -> java source template -> java class -> Expression
FelEngine fel = new FelEngineImpl();
Expression exp = fel.comp
Expression exp = fel.comp
package com.greenpineyu.fel.compile;
import com.greenpineyu.fel.common.NumberUtil;
import com.greenpineyu.fel.Expression;
import com.greenpineyu.fel.context.FelContext;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
public class Fel_0 implements Expression{
public Object eval(FelContext context) {
java.lang.Object var_1 = (java.lang.Object)context.get(“b“); //b
java.lang.Object var_0 = (java.lang.Object)context.get(“a“); //a
return (ObjectUtils.toString(var_0))+(ObjectUtils.toString(var_1));
}
}
import com.greenpineyu.fel.common.NumberUtil;
import com.greenpineyu.fel.Expression;
import com.greenpineyu.fel.context.FelContext;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
public class Fel_0 implements Expression{
public Object eval(FelContext context) {
java.lang.Object var_1 = (java.lang.Object)context.get(“b“); //b
java.lang.Object var_0 = (java.lang.Object)context.get(“a“); //a
return (ObjectUtils.toString(var_0))+(ObjectUtils.toString(var_1));
}
}
FelEngine fel = new FelEngineImpl();
Expression exp = fel.compile(“a+b“, null);
Map<String, Object> env=new HashMap<String, Object>();
env.put(“a“, 1);
env.put(“b“, 3.14);
System.out.println(exp.eval(new MapContext(env)));
Expression exp = fel.compile(“a+b“, null);
Map<String, Object> env=new HashMap<String, Object>();
env.put(“a“, 1);
env.put(“b“, 3.14);
System.out.println(exp.eval(new MapContext(env)));
输出:
13.14
com.greenpineyu.fel.exception.CompileException: package com.greenpineyu.fel.compile;
import com.greenpineyu.fel.common.NumberUtil;
import com.greenpineyu.fel.Expression;
import com.greenpineyu.fel.context.FelContext;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
public class Fel_0 implements Expression{
public Object eval(FelContext context) {
java.lang.Object var_1 = (java.lang.Object)context.get(“b“); //b
java.lang.Object var_0 = (java.lang.Object)context.get(“a“); //a
return (var_0)(var_1);
}
}
[Fel_0.java:14: 运算符 不能应用于 java.lang.Object,java.lang.Object]
at com.greenpineyu.fel.compile.FelCompiler16.compileToClass(FelCompiler16.java:113)
at com.greenpineyu.fel.compile.FelCompiler16.compile(FelCompiler16.java:87)
at com.greenpineyu.fel.compile.CompileService.compile(CompileService.java:66)
at com.greenpineyu.fel.FelEngineImpl.compile(FelEngineImpl.java:62)
at TEst.main(TEst.java:14)
Exception in thread “main“ java.lang.NullPointerException
at TEst.main(TEst.java:18)
import com.greenpineyu.fel.common.NumberUtil;
import com.greenpineyu.fel.Expression;
import com.greenpineyu.fel.context.FelContext;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
public class Fel_0 implements Expression{
public Object eval(FelContext context) {
java.lang.Object var_1 = (java.lang.Object)context.get(“b“); //b
java.lang.Object var_0 = (java.lang.Object)context.get(“a“); //a
return (var_0)(var_1);
}
}
[Fel_0.java:14: 运算符 不能应用于 java.lang.Object,java.lang.Object]
at com.greenpineyu.fel.compile.FelCompiler16.compileToClass(FelCompiler16.java:113)
at com.greenpineyu.fel.compile.FelCompiler16.compile(FelCompiler16.java:87)
at com.greenpineyu.fel.compile.CompileService.compile(CompileService.java:66)
at com.greenpineyu.fel.FelEngineImpl.compile(FelEngineImpl.java:62)
at TEst.main(TEst.java:14)
Exception in thread “main“ java.lang.NullPointerException
at TEst.main(TEst.java:18)
FelEngine fel = new FelEngineImpl();
fel.getContext().set(“a“, 1);
fel.getContext().set(“b“, 3.14);
Expression exp = fel.compile(“a+b“, null);
Map<String, Object> env = new HashMap<String, Object>();
env.put(“a“, 1);
env.put(“b“, 3.14);
System.out.println(exp.eval(new MapContext(env)));
fel.getContext().set(“a“, 1);
fel.getContext().set(“b“, 3.14);
Expression exp = fel.compile(“a+b“, null);
Map<String, Object> env = new HashMap<String, Object>();
env.put(“a“, 1);
env.put(“b“, 3.14);
System.out.println(exp.eval(new MapContext(env)));
package com.greenpineyu.fel.compile;
import com.greenpineyu.fel.common.NumberUtil;
import com.greenpineyu.fel.Expression;
import com.greenpineyu.fel.context.FelContext;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
public class Fel_0 implements Expression{
public Object eval(FelContext context) {
double var_1 = ((java.lang.Number)context.get(“b“)).doubleValue(); //b
double var_0 = ((java.lang.Number)context.get(“a“)).doubleValue(); //a
return (var_0)+(var_1);
}
}
import com.greenpineyu.fel.common.NumberUtil;
import com.greenpineyu.fel.Expression;
import com.greenpineyu.fel.context.FelContext;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
public class Fel_0 implements Expression{
public Object eval(FelContext context) {
double var_1 = ((java.lang.Number)context.get(“b“)).doubleValue(); //b
double var_0 = ((java.lang.Number)context.get(“a“)).doubleValue(); //a
return (var_0)+(var_1);
}
}
可以看到这次将a和b都强制转为double类型了,做数值相加,结果也正确了:
4.140000000000001
强类型还是弱类型,这是一个选择问题,如果你能在运行前就确定变量的类型,那么使用Fel应该可以达到或者接近于原生java执行的效率,但是失去了灵活性;如果你无法确定变量类型,则只能采用弱类型的EL。
EL涌现的越来越多,这个现象有点类似消息中间件领域,越来越多面向特定领域的轻量级MQ的出现,而不是原来那种大而笨重的通用MQ大行其道,一方面是互 联网应用的发展,需求不是通用系统能够满足的,另一方面我认为也是开发者素质的提高,大家都能造适合自己的*。从EL这方面来说,我也认为会有越来越多 特定于领域的,优点和缺点一样鲜明的EL出现,它们包含设计者自己的目标和口味,选择很多,就看取舍。
本文来源于"阿里中间件团队播客",原文发表时间" 2011-09-17"