Freemarker 是否支持 MethodDescriptors?

Does Freemarker honor MethodDescriptors?

(背景:我断断续续地使用 Java beans 大约 18 年;我使用 Freemarker 一两周。:-))

我有一个手工工具 BeanInfo 表示 class 的属性,它不遵循 "ordinary"(但显然是任意的)get/set-方法命名风格。

从语义上讲,对于名为 x 的 Java bean 属性,您将在此 class 上调用名为 x() 的方法。

所以我的 BeanInfo 实现(Freemarker 正在查找和加载)实现了这个模式。很好。

问题中的class其实有一个方法叫target(),return是某个对象(这里就叫Target),表示为一个 PropertyDescriptor 其名称是 target 并且其 readMethod 是该方法。很好。

在我的 Freemarker 模板中,如果我这样做:

theObject.target

...我收到一条错误消息,说 target 实际上是一种方法,而不是 属性,这表明我的 PropertyDescriptor 虽然在技术上可以找到,但没有被参考.如果我改为:

theObject.target()

...然后一切正常。换句话说,target() 方法似乎被 Freemarker 视为一种方法——就好像 Freemarker 不是 "getting through" 到 PropertyDescriptor,否则它会告诉它这实际上是"read method" 一个 Java bean 属性.

我尝试将我的 BeanInfo 编辑为 return MethodDescriptors 的空列表,认为这可能是问题所在:如果您 return nullBeanInfo 中的特定方法,然后 Introspector 对那个东西进行低级内省。 null 是默认值。因此,如果您从 BeanInfo#getMethodDescriptors() return nullIntrospector 可能会在您的 class 中找到所有 public 方法并创建 MethodDescriptor给他们。

无论如何,所以我 return 编辑了一个 MethodDescriptor 的空列表,希望我可以强制 Freemarker 不是 "seeing" target 作为一种方法,而是作为一个 Java beans 属性("falling through" 到我的 BeanInfoPropertyDescriptor,如上所述)。这没有用。

简而言之,我怎样才能使我的:

someObject.target

...咒语访问我的 属性 描述符,而不是 target() 方法?

由于 FreeMarker 使用 java.beans.Introspector 来发现 bean 属性和操作,因此它确实遵循 BeanInfo 的内容。问题是,在您的情况下, return PropertyDescriptor-s 和 MethodDescriptor-s 的名称会冲突。由于模板语言没有用于属性和方法的单独命名空间,因此一个必须隐藏另一个。默认情况下,方法会隐藏属性(现在这不是很实用,因为 fluent API-s 通常有像 Foo foo() 而不是 Foo getFoo() 这样的方法)。您可以通过将 DefaultObjectWrapperBuildermethodAppearanceFineTuner 属性 设置为总是调用 decision.setMethodShadowsProperty(false).

MethodAppearanceFineTurner 对象来更改它