Skip to content

Commit cd68a8d

Browse files
committed
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.
1 parent df8477d commit cd68a8d

File tree

1 file changed

+30
-126
lines changed

1 file changed

+30
-126
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java

Lines changed: 30 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,7 @@
2525

2626
import org.aopalliance.intercept.MethodInterceptor;
2727
import org.aopalliance.intercept.MethodInvocation;
28-
import org.objenesis.Objenesis;
29-
import org.objenesis.ObjenesisStd;
3028
import org.springframework.aop.framework.ProxyFactory;
31-
import org.springframework.beans.BeanUtils;
3229
import org.springframework.cglib.proxy.Callback;
3330
import org.springframework.cglib.proxy.Enhancer;
3431
import org.springframework.cglib.proxy.Factory;
@@ -39,8 +36,8 @@
3936
import org.springframework.data.mongodb.MongoDbFactory;
4037
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
4138
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
39+
import org.springframework.objenesis.ObjenesisStd;
4240
import org.springframework.util.Assert;
43-
import org.springframework.util.ClassUtils;
4441
import org.springframework.util.ReflectionUtils;
4542
import org.springframework.util.StringUtils;
4643

@@ -57,10 +54,9 @@
5754
*/
5855
public class DefaultDbRefResolver implements DbRefResolver {
5956

60-
private static final boolean OBJENESIS_PRESENT = ClassUtils.isPresent("org.objenesis.Objenesis", null);
61-
6257
private final MongoDbFactory mongoDbFactory;
6358
private final PersistenceExceptionTranslator exceptionTranslator;
59+
private final ObjenesisStd objenesis;
6460

6561
/**
6662
* Creates a new {@link DefaultDbRefResolver} with the given {@link MongoDbFactory}.
@@ -73,6 +69,7 @@ public DefaultDbRefResolver(MongoDbFactory mongoDbFactory) {
7369

7470
this.mongoDbFactory = mongoDbFactory;
7571
this.exceptionTranslator = mongoDbFactory.getExceptionTranslator();
72+
this.objenesis = new ObjenesisStd(true);
7673
}
7774

7875
/*
@@ -117,32 +114,44 @@ public DBRef createDbRef(org.springframework.data.mongodb.core.mapping.DBRef ann
117114
*/
118115
private Object createLazyLoadingProxy(MongoPersistentProperty property, DBRef dbref, DbRefResolverCallback callback) {
119116

120-
ProxyFactory proxyFactory = new ProxyFactory();
121117
Class<?> propertyType = property.getType();
118+
LazyLoadingInterceptor interceptor = new LazyLoadingInterceptor(property, dbref, exceptionTranslator, callback);
119+
120+
if (!propertyType.isInterface()) {
121+
122+
Factory factory = (Factory) objenesis.newInstance(getEnhancedTypeFor(propertyType));
123+
factory.setCallbacks(new Callback[] { interceptor });
124+
125+
return factory;
126+
}
127+
128+
ProxyFactory proxyFactory = new ProxyFactory();
122129

123130
for (Class<?> type : propertyType.getInterfaces()) {
124131
proxyFactory.addInterface(type);
125132
}
126133

127-
LazyLoadingInterceptor interceptor = new LazyLoadingInterceptor(property, dbref, exceptionTranslator, callback);
128-
129134
proxyFactory.addInterface(LazyLoadingProxy.class);
135+
proxyFactory.addInterface(propertyType);
136+
proxyFactory.addAdvice(interceptor);
130137

131-
if (propertyType.isInterface()) {
132-
proxyFactory.addInterface(propertyType);
133-
proxyFactory.addAdvice(interceptor);
134-
return proxyFactory.getProxy();
135-
}
138+
return proxyFactory.getProxy();
139+
}
136140

137-
proxyFactory.setProxyTargetClass(true);
138-
proxyFactory.setTargetClass(propertyType);
141+
/**
142+
* Returns the CGLib enhanced type for the given source type.
143+
*
144+
* @param type
145+
* @return
146+
*/
147+
private Class<?> getEnhancedTypeFor(Class<?> type) {
139148

140-
if (!OBJENESIS_PRESENT) {
141-
proxyFactory.addAdvice(interceptor);
142-
return proxyFactory.getProxy();
143-
}
149+
Enhancer enhancer = new Enhancer();
150+
enhancer.setSuperclass(type);
151+
enhancer.setCallbackType(org.springframework.cglib.proxy.MethodInterceptor.class);
152+
enhancer.setInterfaces(new Class[] { LazyLoadingProxy.class });
144153

145-
return ObjenesisProxyEnhancer.enhanceAndGet(proxyFactory, propertyType, interceptor);
154+
return enhancer.createClass();
146155
}
147156

148157
/**
@@ -371,109 +380,4 @@ private synchronized Object resolve() {
371380
return result;
372381
}
373382
}
374-
375-
/**
376-
* Static class to accommodate optional dependency on Objenesis.
377-
*
378-
* @author Oliver Gierke
379-
* @author Thomas Darimont
380-
* @since 1.4
381-
*/
382-
private static class ObjenesisProxyEnhancer {
383-
384-
private static final boolean IS_SPRING_4_OR_BETTER = ClassUtils.isPresent(
385-
"org.springframework.core.DefaultParameterNameDiscoverer", null);
386-
387-
private static final InstanceCreatorStrategy INSTANCE_CREATOR;
388-
389-
static {
390-
391-
if (IS_SPRING_4_OR_BETTER) {
392-
INSTANCE_CREATOR = new Spring4ObjenesisInstanceCreatorStrategy();
393-
} else {
394-
INSTANCE_CREATOR = new DefaultObjenesisInstanceCreatorStrategy();
395-
}
396-
}
397-
398-
public static Object enhanceAndGet(ProxyFactory proxyFactory, Class<?> type,
399-
org.springframework.cglib.proxy.MethodInterceptor interceptor) {
400-
401-
Enhancer enhancer = new Enhancer();
402-
enhancer.setSuperclass(type);
403-
enhancer.setCallbackType(org.springframework.cglib.proxy.MethodInterceptor.class);
404-
enhancer.setInterfaces(new Class[] { LazyLoadingProxy.class });
405-
406-
Factory factory = (Factory) INSTANCE_CREATOR.newInstance(enhancer.createClass());
407-
factory.setCallbacks(new Callback[] { interceptor });
408-
return factory;
409-
}
410-
411-
/**
412-
* Strategy for constructing new instances of a given {@link Class}.
413-
*
414-
* @author Thomas Darimont
415-
*/
416-
interface InstanceCreatorStrategy {
417-
Object newInstance(Class<?> clazz);
418-
}
419-
420-
/**
421-
* An {@link InstanceCreatorStrategy} that uses Objenesis from the classpath.
422-
*
423-
* @author Thomas Darimont
424-
*/
425-
private static class DefaultObjenesisInstanceCreatorStrategy implements InstanceCreatorStrategy {
426-
427-
private static final Objenesis OBJENESIS = new ObjenesisStd(true);
428-
429-
/*
430-
* (non-Javadoc)
431-
* @see org.springframework.data.mongodb.core.convert.DefaultDbRefResolver.ObjenesisProxyEnhancer.InstanceCreatorStrategy#newInstance(java.lang.Class)
432-
*/
433-
@Override
434-
public Object newInstance(Class<?> clazz) {
435-
return OBJENESIS.newInstance(clazz);
436-
}
437-
}
438-
439-
/**
440-
* An {@link InstanceCreatorStrategy} that uses a repackaged version of Objenesis from Spring 4.
441-
*
442-
* @author Thomas Darimont
443-
*/
444-
private static class Spring4ObjenesisInstanceCreatorStrategy implements InstanceCreatorStrategy {
445-
446-
private static final String SPRING4_OBJENESIS_CLASS_NAME = "org.springframework.objenesis.ObjenesisStd";
447-
private static final Object OBJENESIS;
448-
private static final Method NEW_INSTANCE_METHOD;
449-
450-
static {
451-
452-
try {
453-
Class<?> objenesisClass = ClassUtils.forName(SPRING4_OBJENESIS_CLASS_NAME,
454-
ObjenesisProxyEnhancer.class.getClassLoader());
455-
456-
OBJENESIS = BeanUtils.instantiateClass(objenesisClass.getConstructor(boolean.class), true);
457-
NEW_INSTANCE_METHOD = objenesisClass.getMethod("newInstance", Class.class);
458-
459-
} catch (Exception e) {
460-
throw new RuntimeException("Could not setup Objenesis infrastructure with Spring 4 ", e);
461-
}
462-
}
463-
464-
/*
465-
* (non-Javadoc)
466-
* @see org.springframework.data.mongodb.core.convert.DefaultDbRefResolver.ObjenesisProxyEnhancer.InstanceCreatorStrategy#newInstance(java.lang.Class)
467-
*/
468-
@Override
469-
public Object newInstance(Class<?> clazz) {
470-
471-
try {
472-
return NEW_INSTANCE_METHOD.invoke(OBJENESIS, clazz);
473-
} catch (Exception e) {
474-
throw new RuntimeException("Could not created instance for " + clazz, e);
475-
}
476-
}
477-
}
478-
}
479383
}

0 commit comments

Comments
 (0)