1
1
/*
2
- * Copyright 2002-2024 the original author or authors.
2
+ * Copyright 2002-2025 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
@@ -109,11 +109,11 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
109
109
110
110
private @ Nullable BeanFactory beanFactory ;
111
111
112
- private transient @ Nullable ClassLoader pointcutClassLoader ;
112
+ private transient volatile @ Nullable ClassLoader pointcutClassLoader ;
113
113
114
- private transient @ Nullable PointcutExpression pointcutExpression ;
114
+ private transient volatile @ Nullable PointcutExpression pointcutExpression ;
115
115
116
- private transient boolean pointcutParsingFailed = false ;
116
+ private transient volatile boolean pointcutParsingFailed ;
117
117
118
118
119
119
/**
@@ -193,11 +193,14 @@ private void checkExpression() {
193
193
* Lazily build the underlying AspectJ pointcut expression.
194
194
*/
195
195
private PointcutExpression obtainPointcutExpression () {
196
- if (this .pointcutExpression == null ) {
197
- this .pointcutClassLoader = determinePointcutClassLoader ();
198
- this .pointcutExpression = buildPointcutExpression (this .pointcutClassLoader );
196
+ PointcutExpression pointcutExpression = this .pointcutExpression ;
197
+ if (pointcutExpression == null ) {
198
+ ClassLoader pointcutClassLoader = determinePointcutClassLoader ();
199
+ pointcutExpression = buildPointcutExpression (pointcutClassLoader );
200
+ this .pointcutClassLoader = pointcutClassLoader ;
201
+ this .pointcutExpression = pointcutExpression ;
199
202
}
200
- return this . pointcutExpression ;
203
+ return pointcutExpression ;
201
204
}
202
205
203
206
/**
@@ -460,40 +463,24 @@ private ShadowMatch getTargetShadowMatch(Method method, Class<?> targetClass) {
460
463
}
461
464
462
465
private ShadowMatch getShadowMatch (Method targetMethod , Method originalMethod ) {
463
- ShadowMatch shadowMatch = ShadowMatchUtils .getShadowMatch (this , targetMethod );
466
+ ShadowMatchKey key = new ShadowMatchKey (this , targetMethod );
467
+ ShadowMatch shadowMatch = ShadowMatchUtils .getShadowMatch (key );
464
468
if (shadowMatch == null ) {
465
- PointcutExpression fallbackExpression = null ;
466
- Method methodToMatch = targetMethod ;
467
- try {
468
- try {
469
- shadowMatch = obtainPointcutExpression ().matchesMethodExecution (methodToMatch );
470
- }
471
- catch (ReflectionWorldException ex ) {
472
- // Failed to introspect target method, probably because it has been loaded
473
- // in a special ClassLoader. Let's try the declaring ClassLoader instead...
474
- try {
475
- fallbackExpression = getFallbackPointcutExpression (methodToMatch .getDeclaringClass ());
476
- if (fallbackExpression != null ) {
477
- shadowMatch = fallbackExpression .matchesMethodExecution (methodToMatch );
478
- }
479
- }
480
- catch (ReflectionWorldException ex2 ) {
481
- fallbackExpression = null ;
482
- }
469
+ PointcutExpression pointcutExpression = obtainPointcutExpression ();
470
+ synchronized (pointcutExpression ) {
471
+ shadowMatch = ShadowMatchUtils .getShadowMatch (key );
472
+ if (shadowMatch != null ) {
473
+ return shadowMatch ;
483
474
}
484
- if (targetMethod != originalMethod && (shadowMatch == null ||
485
- (Proxy .isProxyClass (targetMethod .getDeclaringClass ()) &&
486
- (shadowMatch .neverMatches () || containsAnnotationPointcut ())))) {
487
- // Fall back to the plain original method in case of no resolvable match or a
488
- // negative match on a proxy class (which doesn't carry any annotations on its
489
- // redeclared methods), as well as for annotation pointcuts.
490
- methodToMatch = originalMethod ;
475
+ PointcutExpression fallbackExpression = null ;
476
+ Method methodToMatch = targetMethod ;
477
+ try {
491
478
try {
492
- shadowMatch = obtainPointcutExpression () .matchesMethodExecution (methodToMatch );
479
+ shadowMatch = pointcutExpression .matchesMethodExecution (methodToMatch );
493
480
}
494
481
catch (ReflectionWorldException ex ) {
495
- // Could neither introspect the target class nor the proxy class ->
496
- // let's try the original method 's declaring class before we give up ...
482
+ // Failed to introspect target method, probably because it has been loaded
483
+ // in a special ClassLoader. Let 's try the declaring ClassLoader instead ...
497
484
try {
498
485
fallbackExpression = getFallbackPointcutExpression (methodToMatch .getDeclaringClass ());
499
486
if (fallbackExpression != null ) {
@@ -504,21 +491,45 @@ private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
504
491
fallbackExpression = null ;
505
492
}
506
493
}
494
+ if (targetMethod != originalMethod && (shadowMatch == null ||
495
+ (Proxy .isProxyClass (targetMethod .getDeclaringClass ()) &&
496
+ (shadowMatch .neverMatches () || containsAnnotationPointcut ())))) {
497
+ // Fall back to the plain original method in case of no resolvable match or a
498
+ // negative match on a proxy class (which doesn't carry any annotations on its
499
+ // redeclared methods), as well as for annotation pointcuts.
500
+ methodToMatch = originalMethod ;
501
+ try {
502
+ shadowMatch = pointcutExpression .matchesMethodExecution (methodToMatch );
503
+ }
504
+ catch (ReflectionWorldException ex ) {
505
+ // Could neither introspect the target class nor the proxy class ->
506
+ // let's try the original method's declaring class before we give up...
507
+ try {
508
+ fallbackExpression = getFallbackPointcutExpression (methodToMatch .getDeclaringClass ());
509
+ if (fallbackExpression != null ) {
510
+ shadowMatch = fallbackExpression .matchesMethodExecution (methodToMatch );
511
+ }
512
+ }
513
+ catch (ReflectionWorldException ex2 ) {
514
+ fallbackExpression = null ;
515
+ }
516
+ }
517
+ }
507
518
}
519
+ catch (Throwable ex ) {
520
+ // Possibly AspectJ 1.8.10 encountering an invalid signature
521
+ logger .debug ("PointcutExpression matching rejected target method" , ex );
522
+ fallbackExpression = null ;
523
+ }
524
+ if (shadowMatch == null ) {
525
+ shadowMatch = new ShadowMatchImpl (org .aspectj .util .FuzzyBoolean .NO , null , null , null );
526
+ }
527
+ else if (shadowMatch .maybeMatches () && fallbackExpression != null ) {
528
+ shadowMatch = new DefensiveShadowMatch (shadowMatch ,
529
+ fallbackExpression .matchesMethodExecution (methodToMatch ));
530
+ }
531
+ shadowMatch = ShadowMatchUtils .setShadowMatch (key , shadowMatch );
508
532
}
509
- catch (Throwable ex ) {
510
- // Possibly AspectJ 1.8.10 encountering an invalid signature
511
- logger .debug ("PointcutExpression matching rejected target method" , ex );
512
- fallbackExpression = null ;
513
- }
514
- if (shadowMatch == null ) {
515
- shadowMatch = new ShadowMatchImpl (org .aspectj .util .FuzzyBoolean .NO , null , null , null );
516
- }
517
- else if (shadowMatch .maybeMatches () && fallbackExpression != null ) {
518
- shadowMatch = new DefensiveShadowMatch (shadowMatch ,
519
- fallbackExpression .matchesMethodExecution (methodToMatch ));
520
- }
521
- shadowMatch = ShadowMatchUtils .setShadowMatch (this , targetMethod , shadowMatch );
522
533
}
523
534
return shadowMatch ;
524
535
}
@@ -713,4 +724,8 @@ public void setMatchingContext(MatchingContext aMatchContext) {
713
724
}
714
725
}
715
726
727
+
728
+ private record ShadowMatchKey (AspectJExpressionPointcut expression , Method method ) {
729
+ }
730
+
716
731
}
0 commit comments