1
1
package org .apache .ibatis .executor .loader ;
2
2
3
- import java .io .ObjectStreamException ;
4
3
import java .lang .reflect .Method ;
5
4
import java .util .Arrays ;
6
5
import java .util .HashSet ;
7
6
import java .util .List ;
7
+ import java .util .Locale ;
8
8
import java .util .Set ;
9
9
10
- import net .sf .cglib .core . Signature ;
10
+ import net .sf .cglib .proxy . Callback ;
11
11
import net .sf .cglib .proxy .Enhancer ;
12
- import net .sf .cglib .proxy .InterfaceMaker ;
13
12
import net .sf .cglib .proxy .MethodInterceptor ;
14
13
import net .sf .cglib .proxy .MethodProxy ;
15
14
15
+ import org .apache .ibatis .executor .ExecutorException ;
16
16
import org .apache .ibatis .logging .Log ;
17
17
import org .apache .ibatis .logging .LogFactory ;
18
18
import org .apache .ibatis .reflection .ExceptionUtil ;
19
19
import org .apache .ibatis .reflection .factory .ObjectFactory ;
20
20
import org .apache .ibatis .reflection .property .PropertyCopier ;
21
21
import org .apache .ibatis .reflection .property .PropertyNamer ;
22
22
import org .apache .ibatis .type .TypeHandlerRegistry ;
23
- import org .objectweb .asm .Type ;
24
23
25
24
public class ResultObjectProxy {
26
25
@@ -31,23 +30,50 @@ public class ResultObjectProxy {
31
30
private static final String FINALIZE_METHOD = "finalize" ;
32
31
private static final String WRITE_REPLACE_METHOD = "writeReplace" ;
33
32
34
- public static Object createProxy (Object target , ResultLoaderMap lazyLoader , boolean aggressive ,
35
- ObjectFactory objectFactory , List <Class > constructorArgTypes , List <Object > constructorArgs ) {
36
- return EnhancedResultObjectProxyImpl .createProxy (target , lazyLoader , aggressive , objectFactory ,
37
- constructorArgTypes , constructorArgs );
33
+ public static Object createProxy (Object target , ResultLoaderMap lazyLoader , boolean aggressive , ObjectFactory objectFactory , List <Class > constructorArgTypes , List <Object > constructorArgs ) {
34
+ return EnhancedResultObjectProxyImpl .createProxy (target , lazyLoader , aggressive , objectFactory , constructorArgTypes , constructorArgs );
38
35
}
39
36
40
- private static class EnhancedResultObjectProxyImpl implements MethodInterceptor {
37
+ public static Object createDeserializationProxy (Object target , Set <String > unloadedProperties , ObjectFactory objectFactory , List <Class > constructorArgTypes , List <Object > constructorArgs ) {
38
+ return EnhancedDeserializationProxyImpl .createProxy (target , unloadedProperties , objectFactory , constructorArgTypes , constructorArgs );
39
+ }
40
+
41
+ private static Object crateProxy (Class type , Callback callback , List <Class > constructorArgTypes , List <Object > constructorArgs ) {
42
+
43
+ Enhancer enhancer = new Enhancer ();
44
+ enhancer .setCallback (callback );
45
+ enhancer .setSuperclass (type );
46
+
47
+ try {
48
+ type .getDeclaredMethod (WRITE_REPLACE_METHOD );
49
+ // ObjectOutputStream will call writeReplace of objects returned by writeReplace
50
+ log .debug (WRITE_REPLACE_METHOD + " method was found on bean " + type + ", make sure it returns this" );
51
+ } catch (NoSuchMethodException e ) {
52
+ enhancer .setInterfaces (new Class [] { WriteReplaceInterface .class });
53
+ } catch (SecurityException e ) {
54
+ // nothing to do here
55
+ }
41
56
57
+ Object enhanced = null ;
58
+ if (constructorArgTypes .isEmpty ()) {
59
+ enhanced = enhancer .create ();
60
+ } else {
61
+ Class [] typesArray = constructorArgTypes .toArray (new Class [constructorArgTypes .size ()]);
62
+ Object [] valuesArray = constructorArgs .toArray (new Object [constructorArgs .size ()]);
63
+ enhanced = enhancer .create (typesArray , valuesArray );
64
+ }
65
+ return enhanced ;
66
+ }
67
+
68
+ private static class EnhancedResultObjectProxyImpl implements MethodInterceptor {
42
69
private Class type ;
43
70
private ResultLoaderMap lazyLoader ;
44
71
private boolean aggressive ;
45
72
private ObjectFactory objectFactory ;
46
73
private List <Class > constructorArgTypes ;
47
74
private List <Object > constructorArgs ;
48
75
49
- private EnhancedResultObjectProxyImpl (Class type , ResultLoaderMap lazyLoader , boolean aggressive ,
50
- ObjectFactory objectFactory , List <Class > constructorArgTypes , List <Object > constructorArgs ) {
76
+ private EnhancedResultObjectProxyImpl (Class type , ResultLoaderMap lazyLoader , boolean aggressive , ObjectFactory objectFactory , List <Class > constructorArgTypes , List <Object > constructorArgs ) {
51
77
this .type = type ;
52
78
this .lazyLoader = lazyLoader ;
53
79
this .aggressive = aggressive ;
@@ -56,39 +82,13 @@ private EnhancedResultObjectProxyImpl(Class type, ResultLoaderMap lazyLoader, bo
56
82
this .constructorArgs = constructorArgs ;
57
83
}
58
84
59
- public static Object createProxy (Object target , ResultLoaderMap lazyLoader , boolean aggressive ,
60
- ObjectFactory objectFactory , List <Class > constructorArgTypes , List <Object > constructorArgs ) {
85
+ public static Object createProxy (Object target , ResultLoaderMap lazyLoader , boolean aggressive , ObjectFactory objectFactory , List <Class > constructorArgTypes , List <Object > constructorArgs ) {
61
86
final Class type = target .getClass ();
62
87
if (registry .hasTypeHandler (type )) {
63
88
return target ;
64
- } else {
65
- EnhancedResultObjectProxyImpl proxy = new EnhancedResultObjectProxyImpl (type , lazyLoader , aggressive ,
66
- objectFactory , constructorArgTypes , constructorArgs );
67
- Enhancer enhancer = new Enhancer ();
68
- enhancer .setCallback (proxy );
69
- enhancer .setSuperclass (type );
70
-
71
- try {
72
- type .getDeclaredMethod (WRITE_REPLACE_METHOD );
73
- // ObjectOutputStream will call writeReplace of objects returned by writeReplace
74
- log .warn (WRITE_REPLACE_METHOD + " method was found on bean " + type + ", make sure it returns this" );
75
- } catch (NoSuchMethodException e ) {
76
- InterfaceMaker writeReplaceInterface = new InterfaceMaker ();
77
- Signature signature = new Signature (WRITE_REPLACE_METHOD , Type .getType (Object .class ), new Type [] {});
78
- writeReplaceInterface .add (signature , new Type [] { Type .getType (ObjectStreamException .class ) });
79
- enhancer .setInterfaces (new Class [] { writeReplaceInterface .create () });
80
- } catch (SecurityException e ) {
81
- // nothing to do here
82
- }
83
-
84
- Object enhanced = null ;
85
- if (constructorArgTypes .isEmpty ()) {
86
- enhanced = enhancer .create ();
87
- } else {
88
- Class [] typesArray = constructorArgTypes .toArray (new Class [constructorArgTypes .size ()]);
89
- Object [] valuesArray = constructorArgs .toArray (new Object [constructorArgs .size ()]);
90
- enhanced = enhancer .create (typesArray , valuesArray );
91
- }
89
+ } else {
90
+ EnhancedResultObjectProxyImpl callback = new EnhancedResultObjectProxyImpl (type , lazyLoader , aggressive , objectFactory , constructorArgTypes , constructorArgs );
91
+ Object enhanced = crateProxy (type , callback , constructorArgTypes , constructorArgs );
92
92
PropertyCopier .copyBeanProperties (type , target , enhanced );
93
93
return enhanced ;
94
94
}
@@ -107,8 +107,7 @@ public Object intercept(Object enhanced, Method method, Object[] args, MethodPro
107
107
}
108
108
PropertyCopier .copyBeanProperties (type , enhanced , original );
109
109
if (lazyLoader .size () > 0 ) {
110
- return new SerialStateHolder (original , lazyLoader .getPropertyNames (), objectFactory ,
111
- constructorArgTypes , constructorArgs );
110
+ return new SerialStateHolder (original , lazyLoader .getPropertyNames (), objectFactory , constructorArgTypes , constructorArgs );
112
111
} else {
113
112
return original ;
114
113
}
@@ -132,4 +131,56 @@ public Object intercept(Object enhanced, Method method, Object[] args, MethodPro
132
131
}
133
132
}
134
133
134
+ private static class EnhancedDeserializationProxyImpl implements MethodInterceptor {
135
+ private Class type ;
136
+ private Set <String > unloadedProperties ;
137
+ private ObjectFactory objectFactory ;
138
+ private List <Class > constructorArgTypes ;
139
+ private List <Object > constructorArgs ;
140
+
141
+ private EnhancedDeserializationProxyImpl (Class type , Set <String > unloadedProperties , ObjectFactory objectFactory , List <Class > constructorArgTypes , List <Object > constructorArgs ) {
142
+ this .type = type ;
143
+ this .unloadedProperties = unloadedProperties ;
144
+ this .objectFactory = objectFactory ;
145
+ this .constructorArgTypes = constructorArgTypes ;
146
+ this .constructorArgs = constructorArgs ;
147
+ }
148
+
149
+ public static Object createProxy (Object target , Set <String > unloadedProperties , ObjectFactory objectFactory , List <Class > constructorArgTypes , List <Object > constructorArgs ) {
150
+ final Class type = target .getClass ();
151
+ EnhancedDeserializationProxyImpl callback = new EnhancedDeserializationProxyImpl (type , unloadedProperties , objectFactory , constructorArgTypes , constructorArgs );
152
+ Object enhanced = crateProxy (type , callback , constructorArgTypes , constructorArgs );
153
+ PropertyCopier .copyBeanProperties (type , target , enhanced );
154
+ return enhanced ;
155
+ }
156
+
157
+ public Object intercept (Object enhanced , Method method , Object [] args , MethodProxy methodProxy ) throws Throwable {
158
+ final String methodName = method .getName ();
159
+ try {
160
+ if (WRITE_REPLACE_METHOD .equals (methodName )) {
161
+ Object original = null ;
162
+ if (constructorArgTypes .isEmpty ()) {
163
+ original = objectFactory .create (type );
164
+ } else {
165
+ original = objectFactory .create (type , constructorArgTypes , constructorArgs );
166
+ }
167
+ PropertyCopier .copyBeanProperties (type , enhanced , original );
168
+ return new SerialStateHolder (original , unloadedProperties , objectFactory , constructorArgTypes , constructorArgs );
169
+ } else {
170
+ if (!FINALIZE_METHOD .equals (methodName ) && PropertyNamer .isProperty (methodName )) {
171
+ final String property = PropertyNamer .methodToProperty (methodName );
172
+ if (unloadedProperties .contains (property .toUpperCase (Locale .ENGLISH ))) {
173
+ throw new ExecutorException ("An attempt has been made to read a not loaded lazy property '"
174
+ + property
175
+ + "' of a disconnected object" );
176
+ }
177
+ }
178
+ return methodProxy .invokeSuper (enhanced , args );
179
+ }
180
+ } catch (Throwable t ) {
181
+ throw ExceptionUtil .unwrapThrowable (t );
182
+ }
183
+ }
184
+ }
185
+
135
186
}
0 commit comments