25
25
import org .springframework .beans .BeanInstantiationException ;
26
26
import org .springframework .beans .BeanUtils ;
27
27
import org .springframework .beans .factory .BeanFactory ;
28
-
29
28
import org .springframework .cglib .core .SpringNamingPolicy ;
30
29
import org .springframework .cglib .proxy .Callback ;
31
30
import org .springframework .cglib .proxy .CallbackFilter ;
34
33
import org .springframework .cglib .proxy .MethodInterceptor ;
35
34
import org .springframework .cglib .proxy .MethodProxy ;
36
35
import org .springframework .cglib .proxy .NoOp ;
36
+ import org .springframework .util .StringUtils ;
37
37
38
38
/**
39
39
* Default object instantiation strategy for use in BeanFactories.
@@ -89,14 +89,13 @@ protected Object instantiateWithMethodInjection(RootBeanDefinition beanDefinitio
89
89
*/
90
90
private static class CglibSubclassCreator {
91
91
92
- private static final Class <?>[] CALLBACK_TYPES = new Class <?>[] { NoOp . class ,
93
- LookupOverrideMethodInterceptor .class , ReplaceOverrideMethodInterceptor .class };
92
+ private static final Class <?>[] CALLBACK_TYPES = new Class <?>[]
93
+ { NoOp . class , LookupOverrideMethodInterceptor .class , ReplaceOverrideMethodInterceptor .class };
94
94
95
95
private final RootBeanDefinition beanDefinition ;
96
96
97
97
private final BeanFactory owner ;
98
98
99
-
100
99
CglibSubclassCreator (RootBeanDefinition beanDefinition , BeanFactory owner ) {
101
100
this .beanDefinition = beanDefinition ;
102
101
this .owner = owner ;
@@ -113,7 +112,6 @@ private static class CglibSubclassCreator {
113
112
*/
114
113
Object instantiate (Constructor <?> ctor , Object [] args ) {
115
114
Class <?> subclass = createEnhancedSubclass (this .beanDefinition );
116
-
117
115
Object instance ;
118
116
if (ctor == null ) {
119
117
instance = BeanUtils .instantiate (subclass );
@@ -123,19 +121,17 @@ Object instantiate(Constructor<?> ctor, Object[] args) {
123
121
Constructor <?> enhancedSubclassConstructor = subclass .getConstructor (ctor .getParameterTypes ());
124
122
instance = enhancedSubclassConstructor .newInstance (args );
125
123
}
126
- catch (Exception e ) {
124
+ catch (Exception ex ) {
127
125
throw new BeanInstantiationException (this .beanDefinition .getBeanClass (), String .format (
128
- "Failed to invoke construcor for CGLIB enhanced subclass [%s]" , subclass .getName ()), e );
126
+ "Failed to invoke constructor for CGLIB enhanced subclass [%s]" , subclass .getName ()), ex );
129
127
}
130
128
}
131
-
132
129
// SPR-10785: set callbacks directly on the instance instead of in the
133
130
// enhanced class (via the Enhancer) in order to avoid memory leaks.
134
131
Factory factory = (Factory ) instance ;
135
- factory .setCallbacks (new Callback [] { NoOp .INSTANCE ,//
136
- new LookupOverrideMethodInterceptor (beanDefinition , owner ),//
137
- new ReplaceOverrideMethodInterceptor (beanDefinition , owner ) });
138
-
132
+ factory .setCallbacks (new Callback [] {NoOp .INSTANCE ,
133
+ new LookupOverrideMethodInterceptor (this .beanDefinition , this .owner ),
134
+ new ReplaceOverrideMethodInterceptor (this .beanDefinition , this .owner )});
139
135
return instance ;
140
136
}
141
137
@@ -153,6 +149,7 @@ private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
153
149
}
154
150
}
155
151
152
+
156
153
/**
157
154
* Class providing hashCode and equals methods required by CGLIB to
158
155
* ensure that CGLIB doesn't generate a distinct class per bean.
@@ -162,7 +159,6 @@ private static class CglibIdentitySupport {
162
159
163
160
private final RootBeanDefinition beanDefinition ;
164
161
165
-
166
162
CglibIdentitySupport (RootBeanDefinition beanDefinition ) {
167
163
this .beanDefinition = beanDefinition ;
168
164
}
@@ -173,8 +169,8 @@ RootBeanDefinition getBeanDefinition() {
173
169
174
170
@ Override
175
171
public boolean equals (Object other ) {
176
- return other . getClass ().equals (this .getClass ())
177
- && (( CglibIdentitySupport ) other ).getBeanDefinition (). equals ( this . getBeanDefinition ( ));
172
+ return ( getClass ().equals (other .getClass ()) &&
173
+ this . beanDefinition . equals ((( CglibIdentitySupport ) other ).beanDefinition ));
178
174
}
179
175
180
176
@ Override
@@ -183,14 +179,14 @@ public int hashCode() {
183
179
}
184
180
}
185
181
182
+
186
183
/**
187
184
* CGLIB callback for filtering method interception behavior.
188
185
*/
189
186
private static class MethodOverrideCallbackFilter extends CglibIdentitySupport implements CallbackFilter {
190
187
191
188
private static final Log logger = LogFactory .getLog (MethodOverrideCallbackFilter .class );
192
189
193
-
194
190
MethodOverrideCallbackFilter (RootBeanDefinition beanDefinition ) {
195
191
super (beanDefinition );
196
192
}
@@ -210,11 +206,12 @@ else if (methodOverride instanceof LookupOverride) {
210
206
else if (methodOverride instanceof ReplaceOverride ) {
211
207
return METHOD_REPLACER ;
212
208
}
213
- throw new UnsupportedOperationException ("Unexpected MethodOverride subclass: "
214
- + methodOverride .getClass ().getName ());
209
+ throw new UnsupportedOperationException ("Unexpected MethodOverride subclass: " +
210
+ methodOverride .getClass ().getName ());
215
211
}
216
212
}
217
213
214
+
218
215
/**
219
216
* CGLIB MethodInterceptor to override methods, replacing them with an
220
217
* implementation that returns a bean looked up in the container.
@@ -223,7 +220,6 @@ private static class LookupOverrideMethodInterceptor extends CglibIdentitySuppor
223
220
224
221
private final BeanFactory owner ;
225
222
226
-
227
223
LookupOverrideMethodInterceptor (RootBeanDefinition beanDefinition , BeanFactory owner ) {
228
224
super (beanDefinition );
229
225
this .owner = owner ;
@@ -233,10 +229,17 @@ private static class LookupOverrideMethodInterceptor extends CglibIdentitySuppor
233
229
public Object intercept (Object obj , Method method , Object [] args , MethodProxy mp ) throws Throwable {
234
230
// Cast is safe, as CallbackFilter filters are used selectively.
235
231
LookupOverride lo = (LookupOverride ) getBeanDefinition ().getMethodOverrides ().getOverride (method );
236
- return this .owner .getBean (lo .getBeanName ());
232
+ Object [] argsToUse = (args .length > 0 ? args : null ); // if no-arg, don't insist on args at all
233
+ if (StringUtils .hasText (lo .getBeanName ())) {
234
+ return this .owner .getBean (lo .getBeanName (), argsToUse );
235
+ }
236
+ else {
237
+ return this .owner .getBean (method .getReturnType (), argsToUse );
238
+ }
237
239
}
238
240
}
239
241
242
+
240
243
/**
241
244
* CGLIB MethodInterceptor to override methods, replacing them with a call
242
245
* to a generic MethodReplacer.
@@ -245,7 +248,6 @@ private static class ReplaceOverrideMethodInterceptor extends CglibIdentitySuppo
245
248
246
249
private final BeanFactory owner ;
247
250
248
-
249
251
ReplaceOverrideMethodInterceptor (RootBeanDefinition beanDefinition , BeanFactory owner ) {
250
252
super (beanDefinition );
251
253
this .owner = owner ;
@@ -255,7 +257,7 @@ private static class ReplaceOverrideMethodInterceptor extends CglibIdentitySuppo
255
257
public Object intercept (Object obj , Method method , Object [] args , MethodProxy mp ) throws Throwable {
256
258
ReplaceOverride ro = (ReplaceOverride ) getBeanDefinition ().getMethodOverrides ().getOverride (method );
257
259
// TODO could cache if a singleton for minor performance optimization
258
- MethodReplacer mr = owner .getBean (ro .getMethodReplacerBeanName (), MethodReplacer .class );
260
+ MethodReplacer mr = this . owner .getBean (ro .getMethodReplacerBeanName (), MethodReplacer .class );
259
261
return mr .reimplement (obj , method , args );
260
262
}
261
263
}
0 commit comments