我想知道,是否有可能在freemarker模板模型中實現某種屬性代理/範圍繼承? 考慮一下:代理對象屬性
public class A {
String aProperty;
}
public class B {
String bProperty;
A parent;
}
所以在我的模板,我可以寫類似${obj.aProperty}
,它會無論是從obj
檢索 aProperty
直接,如果它有一個(obj
是A
一個實例),或檢索parent.aProperty
如果它有none(obj
是B
的一個實例)。
我唯一想到的就是使用自定義BeansWrapper
,但也許還有其他創新性較小的解決方案?任何幫助將不勝感激。
更新
解決方案與Proxy。
public interface TemplateModelObject {
String getaProperty();
}
public class BProxy implements InvocationHandler {
private B target;
public BProxy(B target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass().equals(TemplateModelObject.class)) {
return method.invoke(target.getParent(), args);
} else {
return method.invoke(target, args);
}
}
}
假設A implements TemplateModelObject
。
public class CustomWrapper extends BeansWrapper {
public TemplateModel wrap(Object object) throws TemplateModelException {
if (object != null && B.class.isAssignableFrom(object.getClass())) {
try {
return super.wrap(Proxy.newProxyInstance(TemplateModelObject.class.getClassLoader(), new Class[]{TemplateModelObject.class}, new BProxy((B) object)));
} catch (Exception e) {
throw new TemplateModelException(e);
}
} else {
return super.wrap(object);
}
}
}
我還需要一個接口聲明的B
特定成員,使他們可以通過代理來訪問。但主要的問題是:不會CustomWrapper
在Freemarker中打破了什麼?
我沒有想到我需要改變所有'BeanModel'的實現,這確實使事情變得非常複雜。其實我認爲我找到了一個更簡單的解決方案,請參閱我的問題的更新。如果您能指出任何有關Freemarker的潛在問題,那將是非常好的。 – chimmi
我沒有看到你在那裏擴展'BeansWrapper'的方式有什麼問題。請注意,它比我上面描述的要慢,但它肯定是比較爽的。 – ddekany
實際上,我看到一個問題......如果你是'super.wrap'代理,並且稍後將該對象從模板傳回給Java方法,則它將被解包到代理實例,否則返回原始狀態目的。因此,您從模板調用的Java方法將獲取代理實例,而不是原始實例。 – ddekany