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.
@@ -112,12 +112,12 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
112
112
private BeanFactory beanFactory ;
113
113
114
114
@ Nullable
115
- private transient ClassLoader pointcutClassLoader ;
115
+ private transient volatile ClassLoader pointcutClassLoader ;
116
116
117
117
@ Nullable
118
- private transient PointcutExpression pointcutExpression ;
118
+ private transient volatile PointcutExpression pointcutExpression ;
119
119
120
- private transient boolean pointcutParsingFailed = false ;
120
+ private transient volatile boolean pointcutParsingFailed ;
121
121
122
122
123
123
/**
@@ -197,11 +197,14 @@ private void checkExpression() {
197
197
* Lazily build the underlying AspectJ pointcut expression.
198
198
*/
199
199
private PointcutExpression obtainPointcutExpression () {
200
- if (this .pointcutExpression == null ) {
201
- this .pointcutClassLoader = determinePointcutClassLoader ();
202
- this .pointcutExpression = buildPointcutExpression (this .pointcutClassLoader );
200
+ PointcutExpression pointcutExpression = this .pointcutExpression ;
201
+ if (pointcutExpression == null ) {
202
+ ClassLoader pointcutClassLoader = determinePointcutClassLoader ();
203
+ pointcutExpression = buildPointcutExpression (pointcutClassLoader );
204
+ this .pointcutClassLoader = pointcutClassLoader ;
205
+ this .pointcutExpression = pointcutExpression ;
203
206
}
204
- return this . pointcutExpression ;
207
+ return pointcutExpression ;
205
208
}
206
209
207
210
/**
@@ -467,40 +470,24 @@ private ShadowMatch getTargetShadowMatch(Method method, Class<?> targetClass) {
467
470
}
468
471
469
472
private ShadowMatch getShadowMatch (Method targetMethod , Method originalMethod ) {
470
- ShadowMatch shadowMatch = ShadowMatchUtils .getShadowMatch (this , targetMethod );
473
+ ShadowMatchKey key = new ShadowMatchKey (this , targetMethod );
474
+ ShadowMatch shadowMatch = ShadowMatchUtils .getShadowMatch (key );
471
475
if (shadowMatch == null ) {
472
- PointcutExpression fallbackExpression = null ;
473
- Method methodToMatch = targetMethod ;
474
- try {
475
- try {
476
- shadowMatch = obtainPointcutExpression ().matchesMethodExecution (methodToMatch );
477
- }
478
- catch (ReflectionWorldException ex ) {
479
- // Failed to introspect target method, probably because it has been loaded
480
- // in a special ClassLoader. Let's try the declaring ClassLoader instead...
481
- try {
482
- fallbackExpression = getFallbackPointcutExpression (methodToMatch .getDeclaringClass ());
483
- if (fallbackExpression != null ) {
484
- shadowMatch = fallbackExpression .matchesMethodExecution (methodToMatch );
485
- }
486
- }
487
- catch (ReflectionWorldException ex2 ) {
488
- fallbackExpression = null ;
489
- }
476
+ PointcutExpression pointcutExpression = obtainPointcutExpression ();
477
+ synchronized (pointcutExpression ) {
478
+ shadowMatch = ShadowMatchUtils .getShadowMatch (key );
479
+ if (shadowMatch != null ) {
480
+ return shadowMatch ;
490
481
}
491
- if (targetMethod != originalMethod && (shadowMatch == null ||
492
- (Proxy .isProxyClass (targetMethod .getDeclaringClass ()) &&
493
- (shadowMatch .neverMatches () || containsAnnotationPointcut ())))) {
494
- // Fall back to the plain original method in case of no resolvable match or a
495
- // negative match on a proxy class (which doesn't carry any annotations on its
496
- // redeclared methods), as well as for annotation pointcuts.
497
- methodToMatch = originalMethod ;
482
+ PointcutExpression fallbackExpression = null ;
483
+ Method methodToMatch = targetMethod ;
484
+ try {
498
485
try {
499
- shadowMatch = obtainPointcutExpression () .matchesMethodExecution (methodToMatch );
486
+ shadowMatch = pointcutExpression .matchesMethodExecution (methodToMatch );
500
487
}
501
488
catch (ReflectionWorldException ex ) {
502
- // Could neither introspect the target class nor the proxy class ->
503
- // let's try the original method 's declaring class before we give up ...
489
+ // Failed to introspect target method, probably because it has been loaded
490
+ // in a special ClassLoader. Let 's try the declaring ClassLoader instead ...
504
491
try {
505
492
fallbackExpression = getFallbackPointcutExpression (methodToMatch .getDeclaringClass ());
506
493
if (fallbackExpression != null ) {
@@ -511,21 +498,45 @@ private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
511
498
fallbackExpression = null ;
512
499
}
513
500
}
501
+ if (targetMethod != originalMethod && (shadowMatch == null ||
502
+ (Proxy .isProxyClass (targetMethod .getDeclaringClass ()) &&
503
+ (shadowMatch .neverMatches () || containsAnnotationPointcut ())))) {
504
+ // Fall back to the plain original method in case of no resolvable match or a
505
+ // negative match on a proxy class (which doesn't carry any annotations on its
506
+ // redeclared methods), as well as for annotation pointcuts.
507
+ methodToMatch = originalMethod ;
508
+ try {
509
+ shadowMatch = pointcutExpression .matchesMethodExecution (methodToMatch );
510
+ }
511
+ catch (ReflectionWorldException ex ) {
512
+ // Could neither introspect the target class nor the proxy class ->
513
+ // let's try the original method's declaring class before we give up...
514
+ try {
515
+ fallbackExpression = getFallbackPointcutExpression (methodToMatch .getDeclaringClass ());
516
+ if (fallbackExpression != null ) {
517
+ shadowMatch = fallbackExpression .matchesMethodExecution (methodToMatch );
518
+ }
519
+ }
520
+ catch (ReflectionWorldException ex2 ) {
521
+ fallbackExpression = null ;
522
+ }
523
+ }
524
+ }
514
525
}
526
+ catch (Throwable ex ) {
527
+ // Possibly AspectJ 1.8.10 encountering an invalid signature
528
+ logger .debug ("PointcutExpression matching rejected target method" , ex );
529
+ fallbackExpression = null ;
530
+ }
531
+ if (shadowMatch == null ) {
532
+ shadowMatch = new ShadowMatchImpl (org .aspectj .util .FuzzyBoolean .NO , null , null , null );
533
+ }
534
+ else if (shadowMatch .maybeMatches () && fallbackExpression != null ) {
535
+ shadowMatch = new DefensiveShadowMatch (shadowMatch ,
536
+ fallbackExpression .matchesMethodExecution (methodToMatch ));
537
+ }
538
+ shadowMatch = ShadowMatchUtils .setShadowMatch (key , shadowMatch );
515
539
}
516
- catch (Throwable ex ) {
517
- // Possibly AspectJ 1.8.10 encountering an invalid signature
518
- logger .debug ("PointcutExpression matching rejected target method" , ex );
519
- fallbackExpression = null ;
520
- }
521
- if (shadowMatch == null ) {
522
- shadowMatch = new ShadowMatchImpl (org .aspectj .util .FuzzyBoolean .NO , null , null , null );
523
- }
524
- else if (shadowMatch .maybeMatches () && fallbackExpression != null ) {
525
- shadowMatch = new DefensiveShadowMatch (shadowMatch ,
526
- fallbackExpression .matchesMethodExecution (methodToMatch ));
527
- }
528
- shadowMatch = ShadowMatchUtils .setShadowMatch (this , targetMethod , shadowMatch );
529
540
}
530
541
return shadowMatch ;
531
542
}
@@ -720,4 +731,8 @@ public void setMatchingContext(MatchingContext aMatchContext) {
720
731
}
721
732
}
722
733
734
+
735
+ private record ShadowMatchKey (AspectJExpressionPointcut expression , Method method ) {
736
+ }
737
+
723
738
}
0 commit comments