How do I retrieve the proxied class from the proxy

2020-07-10 06:45发布

I'm using Hibernate with proxies, and I get objects belonging to classes such as test.DBUser$$EnhancerByCGLIB$$40e99a2d.

Is there a Hibernate method to retrieve the base class (test.DBUser in this case) from the proxied class? I know about Hibernate.getClass(), but it takes an Object, while I'm looking for a method which takes as input a Class.

4条回答
可以哭但决不认输i
2楼-- · 2020-07-10 06:51

While I really like the simplicity of the approach posted by Flavio, I can't use it in production code unless it's documented as supported. Also, if you call .getImplementation() on the LazyInitializer, it will force the initialization of the proxy if it isn't already, which is a negative performance impact. I've come up with this approach which addresses both of these concerns:

public static Class<?> getClassForHibernateObject(Object object) {
  if (object instanceof HibernateProxy) {
    LazyInitializer lazyInitializer =
        ((HibernateProxy) object).getHibernateLazyInitializer();
    return lazyInitializer.getPersistentClass();
  } else {
    return object.getClass();
  }
}
查看更多
forever°为你锁心
3楼-- · 2020-07-10 06:56

There is no such method. You will need to write a helper class yourself in order to retrieve the wrapped object and thus the class information from inside the proxy. If you only need the object in the given scenario, try to remove all the lazy loading. Hibernate should then give you the plain object.

Consider trying not to need the object. Maybe you can redesign the application so that you do not need it, for example by adding a field containing the desired information at runtime.

查看更多
Animai°情兽
4楼-- · 2020-07-10 07:15

Classes like test.DBUser$$EnhancerByCGLIB$$40e99a2d are dynamic proxies. The concept of "real class behind" does not make much sense in most cases. Every single time a proxy is created, it can be instance of any class as Hibernate defines it.

What you are really asking for is static Map of { Class<Proxy>, Class<RealObject>}. I don't believe there's such a thing nor I believe there's a need for this. Just look at the source of Hibernate.getClass():

339     public static Class getClass(Object proxy) {
340     if ( proxy instanceof HibernateProxy ) {
341         return ( ( HibernateProxy ) proxy ).getHibernateLazyInitializer()
342                 .getImplementation()
343                 .getClass();
344     }
345     else {
346         return proxy.getClass();
347     }
348 }

It would be much much cheaper to do a static map lookup to get the real class, but Hibernate goes all the way to the lazy initializer to get the implementing class.

查看更多
在下西门庆
5楼-- · 2020-07-10 07:17

I found out, it is easier than I thought: just call getSuperclass() on the proxied class to obtain the unproxied, original class. I'm not sure how general this is, but it appears to work.

查看更多
登录 后发表回答