最终方法是否阻止Hibernate为这样的实体创建代理?

Rob*_*bin 6 hibernate

Hibernate使用代理来启用延迟加载集合甚至单端关联.根据Hibernate的(3.6.5)参考文档(第21.1.3节,单端关联代理),如果Hibernate包含" 任何最终方法 ",则不能构造这样的代理.
我的问题是,这个限制是仅适用于持久字段的getter/setter还是实际上适用于实体类中的任何方法?那么,这样的方法是这样的:

public final String toString() {
   return this.getClass().getSimpleName() + id;
}
Run Code Online (Sandbox Code Playgroud)

真的阻止为这个实体创建(CGLIB或Javassist)代理吗?使用基于字段或属性访问是否重要?由于CGLIB被Javassist取代,这是否提供了这方面的更多功能?

我喜欢在我的实体层次结构中使用继承,因此需要定义一些最终方法,例如,在基类中,以防止子类覆盖这些方法.

提前致谢!

Rob*_*bin 6

在Hibernate邮件列表的帮助下(感谢Emmanuel Bernardt!)我能够回答我自己的问题,总结是:
最终方法不会阻止Hibernate创建代理,但除非这些方法不使用任何状态这个实体是非常不可取的.

一些背景信息:Hibernate既不使用cglib也不使用字节码增强,因此,为了让代理懒惰地初始化其目标实体,它必须拦截任何可能使用该目标实体的状态的方法.现在完全可以拥有这样的最终方法

public final doSomething(String a, Integer b ) {
  // do complicated stuff using only a and b (no instance members accessed!)
}
Run Code Online (Sandbox Code Playgroud)

但是一旦此方法直接或通过另一个实例方法使用任何持久字段,这将绕过代理,从而导致意外行为.

作为旁注,这与您不应直接访问其他实例的字段的原因相同,例如在实体equals方法中:

// XXX bad code!
public boolean equals(Object o) {
  if (this == o) return true;
  if (!(o instanceof Profile)) return false;
  Profile profile = (Profile) o;
  // XXX this bypasses a possible proxy, use profile.getName() instead!
  return (name == null ? profile.name == null : name.equals(profile.name));
}
Run Code Online (Sandbox Code Playgroud)