在前往您的答案之前:
- 是的,您是正确的,Hibernate 当前使用 Javassist(过去使用 GCLib,但已弃用)在运行时检测类。
- Hibernate 确实会在运行时创建子类,这些子类可以为您的持久实体提供代理。
简答
遗憾的是,我认为您无法将 Hibernate 配置为使用您自己的工厂。有关详细信息,我邀请您阅读长答案部分。
长答案
据我所知,目前,Hibernate 4.x 仅支持 Javassist 作为其字节码操作提供程序。虽然,它曾经允许您在 3.x 版本中在 GClib 和 Javassist 之间切换。回到那些版本,您可以通过配置名为hibernate.bytecode.provider 的休眠全局设置来修改要使用的工厂。
此设置不再显示在 Hibernate 4.1 documentation 中,但您仍然可以在 optional configuration properties 下的 Hibernate 3.2 文档中找到有关它的信息。
作为一名开发人员,我知道有时我们是一些棘手的家伙,仅仅因为某些东西不在文档中并不意味着它一定不在代码中 :-) 所以,我认为 也许如果该设置仍然存在,我们可以尝试利用它来做你想做的事情(尽管以不受支持的方式)。
出于好奇,因为我的机器中有 Hibernate 4.0.1 代码(但请注意这不是最新的),我做了一些挖掘......而且惊喜,惊喜财产仍然存在!在跟踪使用过的参考资料(感谢 Eclipse)后,我最终进入了 org.hibernate.cfg.Environment 类(code for version 4.2.0.CR2),在那里我找到了以下代码(我的版本和 4.2.0CR2 中的代码相同):
public static BytecodeProvider buildBytecodeProvider(Properties properties) {
String provider = ConfigurationHelper.getString( BYTECODE_PROVIDER, properties, "javassist" );
LOG.bytecodeProvider( provider );
return buildBytecodeProvider( provider );
}
private static BytecodeProvider buildBytecodeProvider(String providerName) {
if ( "javassist".equals( providerName ) ) {
return new org.hibernate.bytecode.internal.javassist.BytecodeProviderImpl();
}
LOG.unknownBytecodeProvider( providerName );
return new org.hibernate.bytecode.internal.javassist.BytecodeProviderImpl();
}
到目前为止,我可以说它是您的代理工厂的 Javassist 实现,并且不会有标准的方法来更改它。
疯子旁注
我要说的是纯粹的疯狂,它不应该被考虑到生产代码中,但只有在它真的可以工作/学术/让事情发生变化的情况下。
- 您可以尝试扩展您自己的框架来检测类,以便不仅添加满足您需要的字节码,还添加hibernate 需要的字节码——我想说这就像将您的操作与
org.hibernate.bytecode.internal.javassist.BytecodeProviderImpl 操作合并。
- 然后你可以将你的扩展类重命名为
BytecodeProviderImpl 把它放在同一个包org.hibernate.bytecode.internal.javassist 中,最后把它放在类路径中的某个位置,类加载器会在jar 中的那个之前找到它(或者可能使用自定义类加载器)
然后你就可以享受聆听 Hibernate、你的框架和可能整个 JVM 惊慌失措的尖叫,不知道该做什么,或者它可以工作......
锤子黑客>
无论如何,如果您有时间并愿意尝试,请告诉我是否成功。
更新
在 cmets 部分讨论了一下之后,我有了使用自定义 EntityPersister 的想法。因为我对此不太确定,所以我用谷歌搜索了一下,看看我是否能找到一些可以告诉我我的想法是否可行的东西。
我在 Stackoverflow 中发现了一个似乎是 pretty similar to yours 的问题,这比找出我的直觉是否正确要好。可悲的是,那里没有公认的答案。
但该问题的第一个答案提供了与我的想法类似的链接。引用 Pascal Thivent:
一个自定义的 EntityPersister 实现(你可以register for a particular entity during Hibernate initialization using a custom Configuration)
这个例子确实是针对 Grails 中的 Hibernate 的,但在纯 Java 中几乎是一样的:
public void registerCustomEntityPersister(Configuration configuration) {
final Iterator<PersistentClass> classesIterator = configuration.getClassMappings();
while (classesIterator.hasNext()) {
final PersistentClass persistentClass = classesIterator.next();
if (checkIfIsOneTheClassesThatMatters(persistentClass)) {
persistentClass.etEntityPersisterClass(CustomEntityPersister.class);
}
}
尽管这看起来可行,但看起来工作量太大了,因为实现 EntityPersister 看起来并不那么简单……太多的事情。您可以尝试扩展 Hibernate 使用的默认一个(我真的不知道是哪一个)并尝试覆盖 getProxy() 方法以返回您的检测类之一。
很抱歉,如果它仍然不是答案,但遗憾的是我不是 Hibernate 专家,我通常只是开箱即用,实际上由于 javassist 标签,我发现了你的问题,发现它很有趣。
我希望至少我给了你可以帮助你的信息。