@ -17,9 +17,10 @@
@@ -17,9 +17,10 @@
package org.springframework.resilience.annotation ;
import java.lang.reflect.Method ;
import java.util.Collections ;
import java.util.IdentityHashMap ;
import java.util.Map ;
import java.util.concurrent.ConcurrentHashMap ;
import java.util.concurrent.ConcurrentMap ;
import org.aopalliance.intercept.MethodInterceptor ;
import org.aopalliance.intercept.MethodInvocation ;
@ -35,7 +36,6 @@ import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
@@ -35,7 +36,6 @@ import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
import org.springframework.context.EmbeddedValueResolverAware ;
import org.springframework.core.annotation.AnnotatedElementUtils ;
import org.springframework.util.Assert ;
import org.springframework.util.ConcurrentReferenceHashMap ;
import org.springframework.util.StringUtils ;
import org.springframework.util.StringValueResolver ;
@ -74,29 +74,29 @@ public class ConcurrencyLimitBeanPostProcessor extends AbstractBeanFactoryAwareA
@@ -74,29 +74,29 @@ public class ConcurrencyLimitBeanPostProcessor extends AbstractBeanFactoryAwareA
private class ConcurrencyLimitInterceptor implements MethodInterceptor {
private final Concurrent Map< Object , ConcurrencyThrottleCache > cac hePerInstance =
new ConcurrentReferenceHashMap < > ( 16 , ConcurrentReferenceHashMap . ReferenceType . WEAK ) ;
private final Map < Object , ConcurrencyThrottleHolder > hold er PerInstance =
Collections . synchronizedMap ( new IdentityHashMap < > ( 16 ) ) ;
@Override
public @Nullable Object invoke ( MethodInvocation invocation ) throws Throwable {
Method method = invocation . getMethod ( ) ;
Object target = invocation . getThis ( ) ;
Class < ? > targetClass = ( target ! = null ? target . getClass ( ) : method . getDeclaringClass ( ) ) ;
if ( target = = null & & invocation instanceof ProxyMethodInvocation methodInvocation ) {
// Support concurrency throttling for AOP proxy without a target
target = methodInvocation . getProxy ( ) ;
Object instance = invocation . getThis ( ) ;
Class < ? > targetClass = ( instance ! = null ? instance . getClass ( ) : method . getDeclaringClass ( ) ) ;
if ( invocation instanceof ProxyMethodInvocation methodInvocation ) {
// Apply concurrency throttling at the AOP proxy level (independent of target instance)
instance = methodInvocation . getProxy ( ) ;
}
Assert . state ( target ! = null , "Target must not be null " ) ;
Assert . state ( instance ! = null , "Unique instance required - use a ProxyMethodInvocation " ) ;
// Build unique ConcurrencyThrottleCache instance per target object
ConcurrencyThrottleCache cache = this . cac hePerInstance. computeIfAbsent ( target ,
k - > new ConcurrencyThrottleCache ( ) ) ;
// Build unique ConcurrencyThrottleHolder instance per target object
ConcurrencyThrottleHolder holder = this . hold er PerInstance . computeIfAbsent ( instance ,
k - > new ConcurrencyThrottleHolder ( ) ) ;
// Determine method-specific interceptor instance with isolated concurrency count
MethodInterceptor interceptor = cac he. methodInterceptors . get ( method ) ;
MethodInterceptor interceptor = hold er . methodInterceptors . get ( method ) ;
if ( interceptor = = null ) {
synchronized ( cac he) {
interceptor = cac he. methodInterceptors . get ( method ) ;
synchronized ( hold er ) {
interceptor = hold er . methodInterceptors . get ( method ) ;
if ( interceptor = = null ) {
boolean perMethod = false ;
ConcurrencyLimit annotation = AnnotatedElementUtils . getMergedAnnotation ( method , ConcurrencyLimit . class ) ;
@ -104,7 +104,7 @@ public class ConcurrencyLimitBeanPostProcessor extends AbstractBeanFactoryAwareA
@@ -104,7 +104,7 @@ public class ConcurrencyLimitBeanPostProcessor extends AbstractBeanFactoryAwareA
perMethod = true ;
}
else {
interceptor = cac he. classInterceptor ;
interceptor = hold er . classInterceptor ;
if ( interceptor = = null ) {
annotation = AnnotatedElementUtils . getMergedAnnotation ( targetClass , ConcurrencyLimit . class ) ;
}
@ -117,10 +117,10 @@ public class ConcurrencyLimitBeanPostProcessor extends AbstractBeanFactoryAwareA
@@ -117,10 +117,10 @@ public class ConcurrencyLimitBeanPostProcessor extends AbstractBeanFactoryAwareA
}
interceptor = new ConcurrencyThrottleInterceptor ( concurrencyLimit ) ;
if ( ! perMethod ) {
cac he. classInterceptor = interceptor ;
hold er . classInterceptor = interceptor ;
}
}
cac he. methodInterceptors . put ( method , interceptor ) ;
hold er . methodInterceptors . put ( method , interceptor ) ;
}
}
}
@ -141,7 +141,7 @@ public class ConcurrencyLimitBeanPostProcessor extends AbstractBeanFactoryAwareA
@@ -141,7 +141,7 @@ public class ConcurrencyLimitBeanPostProcessor extends AbstractBeanFactoryAwareA
}
private static class ConcurrencyThrottleCache {
private static class ConcurrencyThrottleHolder {
final Map < Method , MethodInterceptor > methodInterceptors = new ConcurrentHashMap < > ( ) ;