From cd68a8db54d698d4adb40ae1a63c1f4db28ed7af Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Wed, 2 Jul 2014 09:23:19 +0200 Subject: [PATCH] DATAMONGO-977 - Removed reflective detection of Spring 4 in DBRef proxy creation. After the Spring 4 upgrade we can now directly use the Objenesis infrastructure of it. --- .../core/convert/DefaultDbRefResolver.java | 156 ++++-------------- 1 file changed, 30 insertions(+), 126 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java index 4a69f7d0d..659d84bba 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java @@ -25,10 +25,7 @@ import java.lang.reflect.Method; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; -import org.objenesis.Objenesis; -import org.objenesis.ObjenesisStd; import org.springframework.aop.framework.ProxyFactory; -import org.springframework.beans.BeanUtils; import org.springframework.cglib.proxy.Callback; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.Factory; @@ -39,8 +36,8 @@ import org.springframework.data.mongodb.LazyLoadingException; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; +import org.springframework.objenesis.ObjenesisStd; import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; @@ -57,10 +54,9 @@ import com.mongodb.DBRef; */ public class DefaultDbRefResolver implements DbRefResolver { - private static final boolean OBJENESIS_PRESENT = ClassUtils.isPresent("org.objenesis.Objenesis", null); - private final MongoDbFactory mongoDbFactory; private final PersistenceExceptionTranslator exceptionTranslator; + private final ObjenesisStd objenesis; /** * Creates a new {@link DefaultDbRefResolver} with the given {@link MongoDbFactory}. @@ -73,6 +69,7 @@ public class DefaultDbRefResolver implements DbRefResolver { this.mongoDbFactory = mongoDbFactory; this.exceptionTranslator = mongoDbFactory.getExceptionTranslator(); + this.objenesis = new ObjenesisStd(true); } /* @@ -117,32 +114,44 @@ public class DefaultDbRefResolver implements DbRefResolver { */ private Object createLazyLoadingProxy(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback) { - ProxyFactory proxyFactory = new ProxyFactory(); Class propertyType = property.getType(); + LazyLoadingInterceptor interceptor = new LazyLoadingInterceptor(property, dbref, exceptionTranslator, callback); + + if (!propertyType.isInterface()) { + + Factory factory = (Factory) objenesis.newInstance(getEnhancedTypeFor(propertyType)); + factory.setCallbacks(new Callback[] { interceptor }); + + return factory; + } + + ProxyFactory proxyFactory = new ProxyFactory(); for (Class type : propertyType.getInterfaces()) { proxyFactory.addInterface(type); } - LazyLoadingInterceptor interceptor = new LazyLoadingInterceptor(property, dbref, exceptionTranslator, callback); - proxyFactory.addInterface(LazyLoadingProxy.class); + proxyFactory.addInterface(propertyType); + proxyFactory.addAdvice(interceptor); - if (propertyType.isInterface()) { - proxyFactory.addInterface(propertyType); - proxyFactory.addAdvice(interceptor); - return proxyFactory.getProxy(); - } + return proxyFactory.getProxy(); + } - proxyFactory.setProxyTargetClass(true); - proxyFactory.setTargetClass(propertyType); + /** + * Returns the CGLib enhanced type for the given source type. + * + * @param type + * @return + */ + private Class getEnhancedTypeFor(Class type) { - if (!OBJENESIS_PRESENT) { - proxyFactory.addAdvice(interceptor); - return proxyFactory.getProxy(); - } + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(type); + enhancer.setCallbackType(org.springframework.cglib.proxy.MethodInterceptor.class); + enhancer.setInterfaces(new Class[] { LazyLoadingProxy.class }); - return ObjenesisProxyEnhancer.enhanceAndGet(proxyFactory, propertyType, interceptor); + return enhancer.createClass(); } /** @@ -371,109 +380,4 @@ public class DefaultDbRefResolver implements DbRefResolver { return result; } } - - /** - * Static class to accommodate optional dependency on Objenesis. - * - * @author Oliver Gierke - * @author Thomas Darimont - * @since 1.4 - */ - private static class ObjenesisProxyEnhancer { - - private static final boolean IS_SPRING_4_OR_BETTER = ClassUtils.isPresent( - "org.springframework.core.DefaultParameterNameDiscoverer", null); - - private static final InstanceCreatorStrategy INSTANCE_CREATOR; - - static { - - if (IS_SPRING_4_OR_BETTER) { - INSTANCE_CREATOR = new Spring4ObjenesisInstanceCreatorStrategy(); - } else { - INSTANCE_CREATOR = new DefaultObjenesisInstanceCreatorStrategy(); - } - } - - public static Object enhanceAndGet(ProxyFactory proxyFactory, Class type, - org.springframework.cglib.proxy.MethodInterceptor interceptor) { - - Enhancer enhancer = new Enhancer(); - enhancer.setSuperclass(type); - enhancer.setCallbackType(org.springframework.cglib.proxy.MethodInterceptor.class); - enhancer.setInterfaces(new Class[] { LazyLoadingProxy.class }); - - Factory factory = (Factory) INSTANCE_CREATOR.newInstance(enhancer.createClass()); - factory.setCallbacks(new Callback[] { interceptor }); - return factory; - } - - /** - * Strategy for constructing new instances of a given {@link Class}. - * - * @author Thomas Darimont - */ - interface InstanceCreatorStrategy { - Object newInstance(Class clazz); - } - - /** - * An {@link InstanceCreatorStrategy} that uses Objenesis from the classpath. - * - * @author Thomas Darimont - */ - private static class DefaultObjenesisInstanceCreatorStrategy implements InstanceCreatorStrategy { - - private static final Objenesis OBJENESIS = new ObjenesisStd(true); - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.core.convert.DefaultDbRefResolver.ObjenesisProxyEnhancer.InstanceCreatorStrategy#newInstance(java.lang.Class) - */ - @Override - public Object newInstance(Class clazz) { - return OBJENESIS.newInstance(clazz); - } - } - - /** - * An {@link InstanceCreatorStrategy} that uses a repackaged version of Objenesis from Spring 4. - * - * @author Thomas Darimont - */ - private static class Spring4ObjenesisInstanceCreatorStrategy implements InstanceCreatorStrategy { - - private static final String SPRING4_OBJENESIS_CLASS_NAME = "org.springframework.objenesis.ObjenesisStd"; - private static final Object OBJENESIS; - private static final Method NEW_INSTANCE_METHOD; - - static { - - try { - Class objenesisClass = ClassUtils.forName(SPRING4_OBJENESIS_CLASS_NAME, - ObjenesisProxyEnhancer.class.getClassLoader()); - - OBJENESIS = BeanUtils.instantiateClass(objenesisClass.getConstructor(boolean.class), true); - NEW_INSTANCE_METHOD = objenesisClass.getMethod("newInstance", Class.class); - - } catch (Exception e) { - throw new RuntimeException("Could not setup Objenesis infrastructure with Spring 4 ", e); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.core.convert.DefaultDbRefResolver.ObjenesisProxyEnhancer.InstanceCreatorStrategy#newInstance(java.lang.Class) - */ - @Override - public Object newInstance(Class clazz) { - - try { - return NEW_INSTANCE_METHOD.invoke(OBJENESIS, clazz); - } catch (Exception e) { - throw new RuntimeException("Could not created instance for " + clazz, e); - } - } - } - } }