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