显示逻辑AOP, 复杂页面逻辑Craker -- fastm. .....
这段时间在javaeye的关于fastm的讨论,令我受益良多。特此感谢大家。非常感谢。
很多人鼓励我的精神,很多人耐心指正我的错误,也有很多人提出尖锐深刻的问题。最感谢的是,甚至有些朋友深入研究了fastm,并提出了改进方案。
并且很多朋友也讨论了fastm之外的话题,令我的知识面开阔。
我这里把这几天针对fastm的一些尖锐深刻的问题列出来。并感谢大家对fastm的深入思考、详细讨论和尖锐抨击。
(1)格式化信息分布在Template DOM和ValueSet DOM两个地方
<c:choose> <c:when test="${copyMade}"> here we add a line. <h4><fmt:message key="copy.ok"/></h4> </c:when> <c:otherwise> here we add a line too. <h4><fmt:message key="copy.nok"/></h4> </c:otherwise> </c:choose>
因为逻辑嵌套只有两层,那么对应的fastm DOM也只有两层。
fastm DOM其实没有增加复杂度。而且,fastm DOM还简化了复杂度。
这是fastm的一个优点。
ValueSet DOM是fastm实现显示逻辑AOP和显示逻辑重用的关键结构。
也是Pipeline式处理过程的数据交换中枢。
不在这里讨论了。:-) 以后证明。
(5)fastm的代码长
其实,这个问题也有些误会。
只是“看起来”,fastm的代码比较长。
我本来是把fastm代码短作为一个优势来宣传的。
其它模板技术的代码分布在模板和Java Code两端。
即使不计算TagLib的代码。fastm代码其实还要比其它的模板技术短。
而且,fastm代码只存在于Java Code里,而且很多都是公用方法 -- 页面逻辑AOP。
不在这里讨论了。:-) 以后证明。public class ViewObject { private Object entity public ViewObject(Object entity);{ this.entity = entity; }}public interface ViewObjectFactory { public void ViewObject createViewObject(Obejct entity);;}
拦截createViewObject方法, pointcut使用正则表达式, 使ViewObject的get*Date()被拦截, 变成return format(entity.get*Date()); 而其他的getter都只是简单地代理调用entity.getter
另外这种格式化的代码用AOP来实现, 纯粹只是一个噱头, AOP, AOP, 只不过是炒冷饭而已......
:-) 我喜欢这种直截了当的直观交流方式。多谢你的代码。还有一点需要请教。
你采用的是Dynamic Proxy, 还是AspectJ的静态织入?
“拦截createViewObject方法”,然后在里面用reflection判断get*Date(), 还是用pointcut定义get*Date()?
我的理解是用reflection做到比较直观和容易。
用pointcut定义get*Date()的方法,能具体一点吗?
在我的印象中,Dynamic Proxy只能够截获Interface的方法。
我前面讲过了,不可能为不同的Entity,都声明一个getter, setter interface.
那么get*Date()是怎么被截获的?
hibernate用了cglib继承(extends)VO,动态实现PO。这种方法到是可能把一些代码加入到子类的实现当中去。但同样要为每一个entity建立一个配置问文件。
你给出的代码用的是哪一种AOP技术?
JDK Dynamic Proxy? CGLIB? AspectJ? Spring AOP? JBoss AOP?
sorry, 我的理解能力有限,希望能够多指教。
先向几位唐大哥请安了, 偶又回来了, 下面是正文:
偶知道的几种Dynamic Proxy技术如你所说只能支持interface, 面向interface, OOP的第一守则了吧, 这个就不用多说了, 拿cglib来举例:
SimpleInvocationHandler.java
import java.lang.reflect.Method;import java.text.SimpleDateFormat;import java.util.Date;import net.sf.cglib.proxy.InvocationHandler;public class SimpleInvocationHandler implements InvocationHandler { public static final SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");; private Object o = null; public SimpleInvocationHandler(Object o); { this.o = o; } public Object invoke(Object proxy, Method m, Object[] args); throws Throwable { Object r = m.invoke(o, args);; if(m.getName();.matches("get.*Date");); { return (new FDate((Date);r););; } return r; } private class FDate extends Date { public FDate (Date date); { super(date.getTime(););; } public String toString(); { return f.format(this);; } }}import java.util.Date;import junit.framework.TestCase;import net.sf.cglib.proxy.InvocationHandler;import net.sf.cglib.proxy.Proxy;public class TestProxy extends TestCase { public interface IFoo { public Date getBarDate();; public String getBarString();; } public class Foo implements IFoo { private Date barDate; private String barString; public Foo(Date date, String string); { barDate = date; barString = string; } public Date getBarDate(); { return barDate; } public String getBarString(); { return barString; } } public void testGetProxyInstance(); throws Exception { Foo foo = new Foo(new Date(0);, "huluhulu");; InvocationHandler handler = new SimpleInvocationHandler(foo);; IFoo proxy = (IFoo); Proxy.newProxyInstance(TestProxy.class.getClassLoader();, new Class[] { IFoo.class }, handler);; assertEquals("huluhulu", proxy.getBarString(););; assertEquals("1970-01-01", proxy.getBarDate();.toString(););; }}import java.util.Date;import junit.framework.TestCase;import net.sf.cglib.proxy.InvocationHandler;import net.sf.cglib.proxy.Proxy;public class TestProxy extends TestCase { public interface IFoo { public Date getBarDate();; public String getBarString();; } public class Foo implements IFoo { private Date barDate; private String barString; public Foo(Date date, String string); { barDate = date; barString = string; } public Date getBarDate(); { return barDate; } public String getBarString(); { return barString; } } public void testGetProxyInstance(); throws Exception { Foo foo = new Foo(new Date(0);, "huluhulu");; InvocationHandler handler = new SimpleInvocationHandler(foo);; IFoo proxy = (IFoo); Proxy.newProxyInstance(TestProxy.class.getClassLoader();, new Class[] { IFoo.class }, handler);; assertEquals("huluhulu", proxy.getBarString(););; assertEquals("1970-01-01", proxy.getBarDate();.toString(););; }}List options = makeOptions(all options, selected option value);;valueSet.setDynamicValueSets("state", options);;makeOptions method is a common function. It looks like.List makeOptions(String[][] options, String selectedOption);{ List valueSets = new ArrayList(options.length);; for(int i =0; i < options.length; i++);{ String[] pair = options[i]; String value = pair[0]; String display = pair[1]; IValueSet valueSet = new ValueSet();; valueSet.setVariable("{value}", value);; valueSet.setVariable("{display}", display);; valueSet.setVariable("{selected}", value.equals(selectedOption); ? "selected" : "" );; valueSets.add(valueSet);; } return valueSets;}<input name="a" value="1" {a_checked}/>valueSet.setVariable("{a_checked}", "checked");;