(背景:我已经断断续续地使用 Java bean 大约 18 年了;我已经使用Freemarker一两个星期了。 :-))
我有一个手工工具BeanInfo
,它表示一个不遵循方法命名的"普通"(但显然是任意的)get
/set
风格的类的属性。
从语义上讲,对于名为x
的 Java Bean 属性,您将在此类上调用名为x()
的方法。
所以我的BeanInfo
实现(Freemarker 正在查找和加载)实现了这种模式。 好。
有问题的类实际上有一个名为target()
的方法,它返回某个对象(我们在这里称之为Target
),它由一个名称为target
且readMethod
是该方法的PropertyDescriptor
表示。 好。
在我的自由标记模板中,如果我这样做:
theObject.target
。我收到一个错误,说target
实际上是一种方法,而不是属性,这表明我的PropertyDescriptor
虽然在技术上可以找到,但没有被咨询。 如果我将其更改为:
theObject.target()
。然后一切正常。 换句话说,target()
方法似乎被Freemarker视为一种方法——就像Freemarker没有"通过"PropertyDescriptor
,否则它会告诉它这实际上是Java bean属性的"读取方法"。
我尝试编辑我的BeanInfo
以返回一个空的MethodDescriptors
列表,认为这可能是问题所在:如果您从BeanInfo
中的特定方法返回null
,那么Introspector
会对该内容进行低级内省。null
是默认值。 因此,如果您从BeanInfo#getMethodDescriptors()
返回null
,Introspector
大概会找到类中的所有公共方法并为它们创建MethodDescriptor
。
无论如何,所以我返回了一个空的MethodDescriptor
列表,希望我可以强迫Freemarker不要"看到"target
作为一个方法,而是作为一个Java bean属性(如上所述"落入"我BeanInfo
的PropertyDescriptor
)。 这行不通。
简而言之,我怎样才能使我的:
someObject.target
。咒语访问我的属性描述符,而不是target()
方法?
由于FreeMarker使用java.beans.Introspector
来发现bean属性和操作,因此它确实尊重BeanInfo
的内容。问题是,在您的情况下,这将返回名称冲突的PropertyDescriptor
-s 和MethodDescriptor
-s。由于模板语言没有单独的属性和方法命名空间,因此一个必须隐藏另一个。默认情况下,方法隐藏属性(这在今天不是很实用,因为流畅的 API-s 通常具有像Foo foo()
而不是Foo getFoo()
这样的方法)。您可以通过将DefaultObjectWrapperBuilder
的methodAppearanceFineTuner
属性设置为始终调用decision.setMethodShadowsProperty(false)
的MethodAppearanceFineTurner
对象来更改它。