25
25
26
26
import org .aopalliance .intercept .MethodInterceptor ;
27
27
import org .aopalliance .intercept .MethodInvocation ;
28
- import org .objenesis .Objenesis ;
29
- import org .objenesis .ObjenesisStd ;
30
28
import org .springframework .aop .framework .ProxyFactory ;
31
- import org .springframework .beans .BeanUtils ;
32
29
import org .springframework .cglib .proxy .Callback ;
33
30
import org .springframework .cglib .proxy .Enhancer ;
34
31
import org .springframework .cglib .proxy .Factory ;
39
36
import org .springframework .data .mongodb .MongoDbFactory ;
40
37
import org .springframework .data .mongodb .core .mapping .MongoPersistentEntity ;
41
38
import org .springframework .data .mongodb .core .mapping .MongoPersistentProperty ;
39
+ import org .springframework .objenesis .ObjenesisStd ;
42
40
import org .springframework .util .Assert ;
43
- import org .springframework .util .ClassUtils ;
44
41
import org .springframework .util .ReflectionUtils ;
45
42
import org .springframework .util .StringUtils ;
46
43
57
54
*/
58
55
public class DefaultDbRefResolver implements DbRefResolver {
59
56
60
- private static final boolean OBJENESIS_PRESENT = ClassUtils .isPresent ("org.objenesis.Objenesis" , null );
61
-
62
57
private final MongoDbFactory mongoDbFactory ;
63
58
private final PersistenceExceptionTranslator exceptionTranslator ;
59
+ private final ObjenesisStd objenesis ;
64
60
65
61
/**
66
62
* Creates a new {@link DefaultDbRefResolver} with the given {@link MongoDbFactory}.
@@ -73,6 +69,7 @@ public DefaultDbRefResolver(MongoDbFactory mongoDbFactory) {
73
69
74
70
this .mongoDbFactory = mongoDbFactory ;
75
71
this .exceptionTranslator = mongoDbFactory .getExceptionTranslator ();
72
+ this .objenesis = new ObjenesisStd (true );
76
73
}
77
74
78
75
/*
@@ -117,32 +114,44 @@ public DBRef createDbRef(org.springframework.data.mongodb.core.mapping.DBRef ann
117
114
*/
118
115
private Object createLazyLoadingProxy (MongoPersistentProperty property , DBRef dbref , DbRefResolverCallback callback ) {
119
116
120
- ProxyFactory proxyFactory = new ProxyFactory ();
121
117
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 ();
122
129
123
130
for (Class <?> type : propertyType .getInterfaces ()) {
124
131
proxyFactory .addInterface (type );
125
132
}
126
133
127
- LazyLoadingInterceptor interceptor = new LazyLoadingInterceptor (property , dbref , exceptionTranslator , callback );
128
-
129
134
proxyFactory .addInterface (LazyLoadingProxy .class );
135
+ proxyFactory .addInterface (propertyType );
136
+ proxyFactory .addAdvice (interceptor );
130
137
131
- if (propertyType .isInterface ()) {
132
- proxyFactory .addInterface (propertyType );
133
- proxyFactory .addAdvice (interceptor );
134
- return proxyFactory .getProxy ();
135
- }
138
+ return proxyFactory .getProxy ();
139
+ }
136
140
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 ) {
139
148
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 });
144
153
145
- return ObjenesisProxyEnhancer . enhanceAndGet ( proxyFactory , propertyType , interceptor );
154
+ return enhancer . createClass ( );
146
155
}
147
156
148
157
/**
@@ -371,109 +380,4 @@ private synchronized Object resolve() {
371
380
return result ;
372
381
}
373
382
}
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
- }
479
383
}
0 commit comments