从模板直接访问 JavaBean 字段与 getter
Direct JavaBean field access from templates vs getter
这周,我调试了一些使用 JasperReport v5.5 完成的模板。在与一个奇怪的错误斗争了很长时间之后,我在想,在(至少)某些情况下,使用直接访问而不是调用适当的 getter (你写 $F{toto } 并且它访问私有字段 toto 而不是调用 getToto()).
模板以这种方式定义字段:
...
<field name="someValue" class="java.lang.String">
<fieldDescription><![CDATA[someValue]]></fieldDescription>
</field>
...
java bean class 是一个具有 BaseClass -> ConcretClass 的层次结构。它定义了一个标准的 属性 someValue,getter 和 setter。 ConcretClass 覆盖此 属性 以实现一些业务逻辑(我知道这可以称为反模式,但这不是这里的重点 - 我不希望遗留代码也没有时间重构)。
所以java有这个:
public class BaseClass {
private String someValue;
public String getSomeValue() { return someValue; }
public void setSomeValue(String someValue) { this.someValue = someValue; }
}
public class ConcretClass extends BaseClass {
private String someValue;
@Override public String getSomeValue() {
LOG.info("invoking getter");
// more business logic here
return someValue;
}
@Override public void setSomeValue(String someValue) { this.someValue = someValue; }
}
它被简化了,但仍然包含了这个想法。
文档指出使用 getter 访问字段:
https://community.jaspersoft.com/documentation/tibco-jaspersoft-studio-user-guide/v60/registration-javabean-fields
Jaspersoft Studio parses a description such as address.state (with a period character between the two attributes) as an attribute path. This attribute path is passed to the function getAddress() in order to locate the target attribute, and then to getState() in order to query the status of the attribute.
运行 我的带有 ConcretClass 实例的代码从不显示日志 "invoking getter"。相反,它显示 BaseClass#someValue 的值(此时为 null)。我至少浪费了一天时间...
我错过了什么?这是一个错误吗?
好的,正如评论中提到的,@AlexK 为我指明了正确的方向。有问题的开发人员不在 Jasper 的团队中,而是在我的团队中。有一天,有人认为(几乎)在所有地方使用反射是个好主意,他所做的一个地方是我们自定义 JRDataSource 的 public Object getFieldValue(JRField jrField) throws JRException
的实现。
显然是个坏主意(处理反射时几乎总是这样)...
道德:在您的流程中添加代码审查:)
这周,我调试了一些使用 JasperReport v5.5 完成的模板。在与一个奇怪的错误斗争了很长时间之后,我在想,在(至少)某些情况下,使用直接访问而不是调用适当的 getter (你写 $F{toto } 并且它访问私有字段 toto 而不是调用 getToto()).
模板以这种方式定义字段:
...
<field name="someValue" class="java.lang.String">
<fieldDescription><![CDATA[someValue]]></fieldDescription>
</field>
...
java bean class 是一个具有 BaseClass -> ConcretClass 的层次结构。它定义了一个标准的 属性 someValue,getter 和 setter。 ConcretClass 覆盖此 属性 以实现一些业务逻辑(我知道这可以称为反模式,但这不是这里的重点 - 我不希望遗留代码也没有时间重构)。
所以java有这个:
public class BaseClass {
private String someValue;
public String getSomeValue() { return someValue; }
public void setSomeValue(String someValue) { this.someValue = someValue; }
}
public class ConcretClass extends BaseClass {
private String someValue;
@Override public String getSomeValue() {
LOG.info("invoking getter");
// more business logic here
return someValue;
}
@Override public void setSomeValue(String someValue) { this.someValue = someValue; }
}
它被简化了,但仍然包含了这个想法。
文档指出使用 getter 访问字段: https://community.jaspersoft.com/documentation/tibco-jaspersoft-studio-user-guide/v60/registration-javabean-fields
Jaspersoft Studio parses a description such as address.state (with a period character between the two attributes) as an attribute path. This attribute path is passed to the function getAddress() in order to locate the target attribute, and then to getState() in order to query the status of the attribute.
运行 我的带有 ConcretClass 实例的代码从不显示日志 "invoking getter"。相反,它显示 BaseClass#someValue 的值(此时为 null)。我至少浪费了一天时间...
我错过了什么?这是一个错误吗?
好的,正如评论中提到的,@AlexK 为我指明了正确的方向。有问题的开发人员不在 Jasper 的团队中,而是在我的团队中。有一天,有人认为(几乎)在所有地方使用反射是个好主意,他所做的一个地方是我们自定义 JRDataSource 的 public Object getFieldValue(JRField jrField) throws JRException
的实现。
显然是个坏主意(处理反射时几乎总是这样)...
道德:在您的流程中添加代码审查:)