@ -1,5 +1,5 @@
/ *
/ *
* Copyright 2002 - 2017 the original author or authors .
* Copyright 2002 - 2018 the original author or authors .
*
*
* Licensed under the Apache License , Version 2 . 0 ( the "License" ) ;
* Licensed under the Apache License , Version 2 . 0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* you may not use this file except in compliance with the License .
@ -49,13 +49,13 @@ import org.springframework.aop.ProxyMethodInvocation;
import org.springframework.aop.framework.autoproxy.ProxyCreationContext ;
import org.springframework.aop.framework.autoproxy.ProxyCreationContext ;
import org.springframework.aop.interceptor.ExposeInvocationInterceptor ;
import org.springframework.aop.interceptor.ExposeInvocationInterceptor ;
import org.springframework.aop.support.AbstractExpressionPointcut ;
import org.springframework.aop.support.AbstractExpressionPointcut ;
import org.springframework.aop.support.AopUtils ;
import org.springframework.beans.factory.BeanFactory ;
import org.springframework.beans.factory.BeanFactory ;
import org.springframework.beans.factory.BeanFactoryAware ;
import org.springframework.beans.factory.BeanFactoryAware ;
import org.springframework.beans.factory.BeanFactoryUtils ;
import org.springframework.beans.factory.BeanFactoryUtils ;
import org.springframework.beans.factory.FactoryBean ;
import org.springframework.beans.factory.FactoryBean ;
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils ;
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils ;
import org.springframework.beans.factory.config.ConfigurableBeanFactory ;
import org.springframework.beans.factory.config.ConfigurableBeanFactory ;
import org.springframework.core.BridgeMethodResolver ;
import org.springframework.lang.Nullable ;
import org.springframework.lang.Nullable ;
import org.springframework.util.Assert ;
import org.springframework.util.Assert ;
import org.springframework.util.ClassUtils ;
import org.springframework.util.ClassUtils ;
@ -289,10 +289,9 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
}
}
@Override
@Override
public boolean matches ( Method method , @Nullable Class < ? > targetClass , boolean beanH asIntroductions) {
public boolean matches ( Method method , @Nullable Class < ? > targetClass , boolean h asIntroductions) {
obtainPointcutExpression ( ) ;
obtainPointcutExpression ( ) ;
Method targetMethod = AopUtils . getMostSpecificMethod ( method , targetClass ) ;
ShadowMatch shadowMatch = getTargetShadowMatch ( method , targetClass ) ;
ShadowMatch shadowMatch = getShadowMatch ( targetMethod , method ) ;
// Special handling for this, target, @this, @target, @annotation
// Special handling for this, target, @this, @target, @annotation
// in Spring - we can optimize since we know we have exactly this class,
// in Spring - we can optimize since we know we have exactly this class,
@ -305,7 +304,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
}
}
else {
else {
// the maybe case
// the maybe case
if ( beanH asIntroductions) {
if ( h asIntroductions) {
return true ;
return true ;
}
}
// A match test returned maybe - if there are any subtype sensitive variables
// A match test returned maybe - if there are any subtype sensitive variables
@ -331,8 +330,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
@Override
@Override
public boolean matches ( Method method , @Nullable Class < ? > targetClass , Object . . . args ) {
public boolean matches ( Method method , @Nullable Class < ? > targetClass , Object . . . args ) {
obtainPointcutExpression ( ) ;
obtainPointcutExpression ( ) ;
ShadowMatch shadowMatch = getShadowMatch ( AopUtils . getMostSpecificMethod ( method , targetClass ) , method ) ;
ShadowMatch shadowMatch = getTargetShadowMatch ( method , targetClass ) ;
ShadowMatch originalShadowMatch = getShadowMatch ( method , method ) ;
// Bind Spring AOP proxy to AspectJ "this" and Spring AOP target to AspectJ target,
// Bind Spring AOP proxy to AspectJ "this" and Spring AOP target to AspectJ target,
// consistent with return of MethodInvocationProceedingJoinPoint
// consistent with return of MethodInvocationProceedingJoinPoint
@ -367,7 +365,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
* < p > See SPR - 2979 for the original bug .
* < p > See SPR - 2979 for the original bug .
* /
* /
if ( pmi ! = null & & thisObject ! = null ) { // there is a current invocation
if ( pmi ! = null & & thisObject ! = null ) { // there is a current invocation
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker ( originalShadowMatch ) ;
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker ( getShadowMatch ( method , method ) ) ;
if ( ! originalMethodResidueTest . testThisInstanceOfResidue ( thisObject . getClass ( ) ) ) {
if ( ! originalMethodResidueTest . testThisInstanceOfResidue ( thisObject . getClass ( ) ) ) {
return false ;
return false ;
}
}
@ -427,6 +425,23 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
invocation . setUserAttribute ( resolveExpression ( ) , jpm ) ;
invocation . setUserAttribute ( resolveExpression ( ) , jpm ) ;
}
}
private ShadowMatch getTargetShadowMatch ( Method method , @Nullable Class < ? > targetClass ) {
Method targetMethod = method ;
if ( targetClass ! = null ) {
targetMethod = ClassUtils . getMostSpecificMethod ( method , ClassUtils . getUserClass ( targetClass ) ) ;
if ( targetMethod . getDeclaringClass ( ) . isInterface ( ) ) {
Set < Class < ? > > ifcs = ClassUtils . getAllInterfacesForClassAsSet ( targetClass ) ;
if ( ifcs . size ( ) > 1 ) {
Class < ? > compositeInterface = ClassUtils . createCompositeInterface (
ClassUtils . toClassArray ( ifcs ) , targetClass . getClassLoader ( ) ) ;
targetMethod = ClassUtils . getMostSpecificMethod ( targetMethod , compositeInterface ) ;
}
}
}
targetMethod = BridgeMethodResolver . findBridgedMethod ( targetMethod ) ;
return getShadowMatch ( targetMethod , method ) ;
}
private ShadowMatch getShadowMatch ( Method targetMethod , Method originalMethod ) {
private ShadowMatch getShadowMatch ( Method targetMethod , Method originalMethod ) {
// Avoid lock contention for known Methods through concurrent access...
// Avoid lock contention for known Methods through concurrent access...
ShadowMatch shadowMatch = this . shadowMatchCache . get ( targetMethod ) ;
ShadowMatch shadowMatch = this . shadowMatchCache . get ( targetMethod ) ;
@ -434,9 +449,9 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
synchronized ( this . shadowMatchCache ) {
synchronized ( this . shadowMatchCache ) {
// Not found - now check again with full lock...
// Not found - now check again with full lock...
PointcutExpression fallbackExpression = null ;
PointcutExpression fallbackExpression = null ;
Method methodToMatch = targetMethod ;
shadowMatch = this . shadowMatchCache . get ( targetMethod ) ;
shadowMatch = this . shadowMatchCache . get ( targetMethod ) ;
if ( shadowMatch = = null ) {
if ( shadowMatch = = null ) {
Method methodToMatch = targetMethod ;
try {
try {
try {
try {
shadowMatch = obtainPointcutExpression ( ) . matchesMethodExecution ( methodToMatch ) ;
shadowMatch = obtainPointcutExpression ( ) . matchesMethodExecution ( methodToMatch ) ;
@ -459,7 +474,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
try {
try {
shadowMatch = obtainPointcutExpression ( ) . matchesMethodExecution ( methodToMatch ) ;
shadowMatch = obtainPointcutExpression ( ) . matchesMethodExecution ( methodToMatch ) ;
}
}
catch ( ReflectionWorldException ex3 ) {
catch ( ReflectionWorldException ex ) {
// Could neither introspect the target class nor the proxy class ->
// Could neither introspect the target class nor the proxy class ->
// let's try the original method's declaring class before we give up...
// let's try the original method's declaring class before we give up...
try {
try {
@ -468,7 +483,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
shadowMatch = fallbackExpression . matchesMethodExecution ( methodToMatch ) ;
shadowMatch = fallbackExpression . matchesMethodExecution ( methodToMatch ) ;
}
}
}
}
catch ( ReflectionWorldException ex4 ) {
catch ( ReflectionWorldException ex2 ) {
fallbackExpression = null ;
fallbackExpression = null ;
}
}
}
}