29
29
import org .apache .commons .logging .LogFactory ;
30
30
import org .aspectj .weaver .BCException ;
31
31
import org .aspectj .weaver .patterns .NamePattern ;
32
- import org .aspectj .weaver .reflect .ReflectionWorld ;
33
32
import org .aspectj .weaver .reflect .ReflectionWorld .ReflectionWorldException ;
34
33
import org .aspectj .weaver .reflect .ShadowMatchImpl ;
35
34
import org .aspectj .weaver .tools .ContextBasedMatcher ;
@@ -108,6 +107,8 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
108
107
109
108
private BeanFactory beanFactory ;
110
109
110
+ private transient ClassLoader pointcutClassLoader ;
111
+
111
112
private transient PointcutExpression pointcutExpression ;
112
113
113
114
private transient Map <Method , ShadowMatch > shadowMatchCache = new ConcurrentHashMap <Method , ShadowMatch >(32 );
@@ -182,20 +183,13 @@ private void checkReadyToMatch() {
182
183
throw new IllegalStateException ("Must set property 'expression' before attempting to match" );
183
184
}
184
185
if (this .pointcutExpression == null ) {
185
- this .pointcutExpression = buildPointcutExpression ();
186
+ this .pointcutClassLoader = (this .beanFactory instanceof ConfigurableBeanFactory ?
187
+ ((ConfigurableBeanFactory ) this .beanFactory ).getBeanClassLoader () :
188
+ ClassUtils .getDefaultClassLoader ());
189
+ this .pointcutExpression = buildPointcutExpression (this .pointcutClassLoader );
186
190
}
187
191
}
188
192
189
- /**
190
- * Build the underlying AspectJ pointcut expression.
191
- */
192
- private PointcutExpression buildPointcutExpression () {
193
- ClassLoader cl = (this .beanFactory instanceof ConfigurableBeanFactory ?
194
- ((ConfigurableBeanFactory ) this .beanFactory ).getBeanClassLoader () :
195
- ClassUtils .getDefaultClassLoader ());
196
- return buildPointcutExpression (cl );
197
- }
198
-
199
193
/**
200
194
* Build the underlying AspectJ pointcut expression.
201
195
*/
@@ -248,23 +242,22 @@ public PointcutExpression getPointcutExpression() {
248
242
public boolean matches (Class <?> targetClass ) {
249
243
checkReadyToMatch ();
250
244
try {
251
- return this .pointcutExpression .couldMatchJoinPointsInType (targetClass );
252
- }
253
- catch (ReflectionWorldException rwe ) {
254
- logger .debug ("PointcutExpression matching rejected target class" , rwe );
255
245
try {
256
- // Actually this is still a "maybe" - treat the pointcut as dynamic if we don't know enough yet
257
- return getFallbackPointcutExpression (targetClass ).couldMatchJoinPointsInType (targetClass );
246
+ return this .pointcutExpression .couldMatchJoinPointsInType (targetClass );
258
247
}
259
- catch (BCException bce ) {
260
- logger .debug ("Fallback PointcutExpression matching rejected target class" , bce );
261
- return false ;
248
+ catch (ReflectionWorldException ex ) {
249
+ logger .debug ("PointcutExpression matching rejected target class - trying fallback expression" , ex );
250
+ // Actually this is still a "maybe" - treat the pointcut as dynamic if we don't know enough yet
251
+ PointcutExpression fallbackExpression = getFallbackPointcutExpression (targetClass );
252
+ if (fallbackExpression != null ) {
253
+ return fallbackExpression .couldMatchJoinPointsInType (targetClass );
254
+ }
262
255
}
263
256
}
264
257
catch (BCException ex ) {
265
258
logger .debug ("PointcutExpression matching rejected target class" , ex );
266
- return false ;
267
259
}
260
+ return false ;
268
261
}
269
262
270
263
public boolean matches (Method method , Class <?> targetClass , boolean beanHasIntroductions ) {
@@ -357,12 +350,19 @@ protected String getCurrentProxiedBeanName() {
357
350
358
351
359
352
/**
360
- * Get a new pointcut expression based on a target class's loader, rather
361
- * than the default.
353
+ * Get a new pointcut expression based on a target class's loader rather than the default.
362
354
*/
363
355
private PointcutExpression getFallbackPointcutExpression (Class <?> targetClass ) {
364
- ClassLoader classLoader = targetClass .getClassLoader ();
365
- return (classLoader != null ? buildPointcutExpression (classLoader ) : this .pointcutExpression );
356
+ try {
357
+ ClassLoader classLoader = targetClass .getClassLoader ();
358
+ if (classLoader != null && classLoader != this .pointcutClassLoader ) {
359
+ return buildPointcutExpression (classLoader );
360
+ }
361
+ }
362
+ catch (Throwable ex ) {
363
+ logger .debug ("Failed to create fallback PointcutExpression" , ex );
364
+ }
365
+ return null ;
366
366
}
367
367
368
368
private RuntimeTestWalker getRuntimeTestWalker (ShadowMatch shadowMatch ) {
@@ -388,46 +388,51 @@ private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
388
388
if (shadowMatch == null ) {
389
389
synchronized (this .shadowMatchCache ) {
390
390
// Not found - now check again with full lock...
391
+ PointcutExpression fallbackExpression = null ;
391
392
Method methodToMatch = targetMethod ;
392
- PointcutExpression fallbackPointcutExpression = null ;
393
- shadowMatch = this .shadowMatchCache .get (methodToMatch );
393
+ shadowMatch = this .shadowMatchCache .get (targetMethod );
394
394
if (shadowMatch == null ) {
395
395
try {
396
- shadowMatch = this .pointcutExpression .matchesMethodExecution (targetMethod );
396
+ shadowMatch = this .pointcutExpression .matchesMethodExecution (methodToMatch );
397
397
}
398
- catch (ReflectionWorld . ReflectionWorldException ex ) {
398
+ catch (ReflectionWorldException ex ) {
399
399
// Failed to introspect target method, probably because it has been loaded
400
- // in a special ClassLoader. Let's try the original method instead...
400
+ // in a special ClassLoader. Let's try the declaring ClassLoader instead...
401
401
try {
402
- fallbackPointcutExpression = getFallbackPointcutExpression (methodToMatch .getDeclaringClass ());
403
- shadowMatch = fallbackPointcutExpression .matchesMethodExecution (methodToMatch );
404
- }
405
- catch (ReflectionWorld .ReflectionWorldException ex2 ) {
406
- if (targetMethod == originalMethod ) {
407
- shadowMatch = new ShadowMatchImpl (org .aspectj .util .FuzzyBoolean .NO , null , null , null );
402
+ fallbackExpression = getFallbackPointcutExpression (methodToMatch .getDeclaringClass ());
403
+ if (fallbackExpression != null ) {
404
+ shadowMatch = fallbackExpression .matchesMethodExecution (methodToMatch );
408
405
}
409
- else {
410
- try {
411
- shadowMatch = this .pointcutExpression .matchesMethodExecution (originalMethod );
412
- }
413
- catch (ReflectionWorld .ReflectionWorldException ex3 ) {
414
- // Could neither introspect the target class nor the proxy class ->
415
- // let's simply consider this method as non-matching.
416
- methodToMatch = originalMethod ;
417
- fallbackPointcutExpression = getFallbackPointcutExpression (methodToMatch .getDeclaringClass ());
418
- try {
419
- shadowMatch = fallbackPointcutExpression .matchesMethodExecution (methodToMatch );
420
- }
421
- catch (ReflectionWorld .ReflectionWorldException ex4 ) {
422
- shadowMatch = new ShadowMatchImpl (org .aspectj .util .FuzzyBoolean .NO , null , null , null );
423
- }
406
+ }
407
+ catch (ReflectionWorldException ex2 ) {
408
+ fallbackExpression = null ;
409
+ }
410
+ }
411
+ if (shadowMatch == null && targetMethod != originalMethod ) {
412
+ methodToMatch = originalMethod ;
413
+ try {
414
+ shadowMatch = this .pointcutExpression .matchesMethodExecution (methodToMatch );
415
+ }
416
+ catch (ReflectionWorldException ex3 ) {
417
+ // Could neither introspect the target class nor the proxy class ->
418
+ // let's try the original method's declaring class before we give up...
419
+ try {
420
+ fallbackExpression = getFallbackPointcutExpression (methodToMatch .getDeclaringClass ());
421
+ if (fallbackExpression != null ) {
422
+ shadowMatch = fallbackExpression .matchesMethodExecution (methodToMatch );
424
423
}
425
424
}
425
+ catch (ReflectionWorldException ex4 ) {
426
+ fallbackExpression = null ;
427
+ }
426
428
}
427
429
}
428
- if (shadowMatch .maybeMatches () && fallbackPointcutExpression != null ) {
430
+ if (shadowMatch == null ) {
431
+ shadowMatch = new ShadowMatchImpl (org .aspectj .util .FuzzyBoolean .NO , null , null , null );
432
+ }
433
+ else if (shadowMatch .maybeMatches () && fallbackExpression != null ) {
429
434
shadowMatch = new DefensiveShadowMatch (shadowMatch ,
430
- fallbackPointcutExpression .matchesMethodExecution (methodToMatch ));
435
+ fallbackExpression .matchesMethodExecution (methodToMatch ));
431
436
}
432
437
this .shadowMatchCache .put (targetMethod , shadowMatch );
433
438
}
@@ -545,7 +550,7 @@ public boolean mayNeedDynamicTest() {
545
550
return false ;
546
551
}
547
552
548
- private FuzzyBoolean contextMatch (Class targetType ) {
553
+ private FuzzyBoolean contextMatch (Class <?> targetType ) {
549
554
String advisedBeanName = getCurrentProxiedBeanName ();
550
555
if (advisedBeanName == null ) { // no proxy creation in progress
551
556
// abstain; can't return YES, since that will make pointcut with negation fail
0 commit comments