Skip to content

Commit 56a4827

Browse files
committed
avoiding synchronization as far as possible (SPR-5668)
1 parent 7048689 commit 56a4827

File tree

4 files changed

+48
-64
lines changed

4 files changed

+48
-64
lines changed

org.springframework.aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java

Lines changed: 27 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2008 the original author or authors.
2+
* Copyright 2002-2009 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,17 +17,18 @@
1717
package org.springframework.aop.aspectj;
1818

1919
import java.lang.reflect.Method;
20-
import java.util.HashMap;
2120
import java.util.HashSet;
2221
import java.util.Map;
2322
import java.util.Set;
23+
import java.util.concurrent.ConcurrentHashMap;
2424

2525
import org.aopalliance.intercept.MethodInvocation;
2626
import org.apache.commons.logging.Log;
2727
import org.apache.commons.logging.LogFactory;
2828
import org.aspectj.weaver.BCException;
2929
import org.aspectj.weaver.patterns.NamePattern;
3030
import org.aspectj.weaver.reflect.ReflectionWorld;
31+
import org.aspectj.weaver.reflect.ShadowMatchImpl;
3132
import org.aspectj.weaver.tools.ContextBasedMatcher;
3233
import org.aspectj.weaver.tools.FuzzyBoolean;
3334
import org.aspectj.weaver.tools.JoinPointMatch;
@@ -92,7 +93,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
9293

9394
private static final Log logger = LogFactory.getLog(AspectJExpressionPointcut.class);
9495

95-
private final Map<Method, ShadowMatch> shadowMatchCache = new HashMap<Method, ShadowMatch>();
96+
private final Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap<Method, ShadowMatch>(32);
9697

9798
private PointcutParser pointcutParser;
9899

@@ -243,15 +244,7 @@ public boolean matches(Class targetClass) {
243244
public boolean matches(Method method, Class targetClass, boolean beanHasIntroductions) {
244245
checkReadyToMatch();
245246
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
246-
ShadowMatch shadowMatch = null;
247-
try {
248-
shadowMatch = getShadowMatch(targetMethod, method);
249-
}
250-
catch (ReflectionWorld.ReflectionWorldException ex) {
251-
// Could neither introspect the target class nor the proxy class ->
252-
// let's simply consider this method as non-matching.
253-
return false;
254-
}
247+
ShadowMatch shadowMatch = getShadowMatch(targetMethod, method);
255248

256249
// Special handling for this, target, @this, @target, @annotation
257250
// in Spring - we can optimize since we know we have exactly this class,
@@ -279,17 +272,8 @@ public boolean isRuntime() {
279272

280273
public boolean matches(Method method, Class targetClass, Object[] args) {
281274
checkReadyToMatch();
282-
ShadowMatch shadowMatch = null;
283-
ShadowMatch originalShadowMatch = null;
284-
try {
285-
shadowMatch = getShadowMatch(AopUtils.getMostSpecificMethod(method, targetClass), method);
286-
originalShadowMatch = getShadowMatch(method, method);
287-
}
288-
catch (ReflectionWorld.ReflectionWorldException ex) {
289-
// Could neither introspect the target class nor the proxy class ->
290-
// let's simply consider this method as non-matching.
291-
return false;
292-
}
275+
ShadowMatch shadowMatch = getShadowMatch(AopUtils.getMostSpecificMethod(method, targetClass), method);
276+
ShadowMatch originalShadowMatch = getShadowMatch(method, method);
293277

294278
// Bind Spring AOP proxy to AspectJ "this" and Spring AOP target to AspectJ target,
295279
// consistent with return of MethodInvocationProceedingJoinPoint
@@ -364,24 +348,31 @@ private void bindParameters(ProxyMethodInvocation invocation, JoinPointMatch jpm
364348
}
365349

366350
private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
367-
synchronized (this.shadowMatchCache) {
368-
ShadowMatch shadowMatch = this.shadowMatchCache.get(targetMethod);
369-
if (shadowMatch == null) {
370-
try {
371-
shadowMatch = this.pointcutExpression.matchesMethodExecution(targetMethod);
351+
ShadowMatch shadowMatch = this.shadowMatchCache.get(targetMethod);
352+
if (shadowMatch == null) {
353+
try {
354+
shadowMatch = this.pointcutExpression.matchesMethodExecution(targetMethod);
355+
}
356+
catch (ReflectionWorld.ReflectionWorldException ex) {
357+
// Failed to introspect target method, probably because it has been loaded
358+
// in a special ClassLoader. Let's try the original method instead...
359+
if (targetMethod == originalMethod) {
360+
shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);
372361
}
373-
catch (ReflectionWorld.ReflectionWorldException ex) {
374-
// Failed to introspect target method, probably because it has been loaded
375-
// in a special ClassLoader. Let's try the original method instead...
376-
if (targetMethod == originalMethod) {
377-
throw ex;
362+
else {
363+
try {
364+
shadowMatch = this.pointcutExpression.matchesMethodExecution(originalMethod);
365+
}
366+
catch (ReflectionWorld.ReflectionWorldException ex2) {
367+
// Could neither introspect the target class nor the proxy class ->
368+
// let's simply consider this method as non-matching.
369+
shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);
378370
}
379-
shadowMatch = this.pointcutExpression.matchesMethodExecution(originalMethod);
380371
}
381-
this.shadowMatchCache.put(targetMethod, shadowMatch);
382372
}
383-
return shadowMatch;
373+
this.shadowMatchCache.put(targetMethod, shadowMatch);
384374
}
375+
return shadowMatch;
385376
}
386377

387378

org.springframework.aop/src/main/java/org/springframework/aop/aspectj/annotation/LazySingletonAspectInstanceFactoryDecorator.java

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2007 the original author or authors.
2+
* Copyright 2002-2009 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,11 +16,10 @@
1616

1717
package org.springframework.aop.aspectj.annotation;
1818

19-
import org.springframework.core.Ordered;
2019
import org.springframework.util.Assert;
2120

2221
/**
23-
* Decorator to cause a MetadataAwareAspectInstanceFactory to instantiate only once.
22+
* Decorator to cause a {@link MetadataAwareAspectInstanceFactory} to instantiate only once.
2423
*
2524
* @author Rod Johnson
2625
* @author Juergen Hoeller
@@ -30,7 +29,7 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
3029

3130
private final MetadataAwareAspectInstanceFactory maaif;
3231

33-
private Object materialized;
32+
private volatile Object materialized;
3433

3534

3635
/**
@@ -42,30 +41,32 @@ public LazySingletonAspectInstanceFactoryDecorator(MetadataAwareAspectInstanceFa
4241
this.maaif = maaif;
4342
}
4443

44+
4545
public synchronized Object getAspectInstance() {
4646
if (this.materialized == null) {
47-
this.materialized = this.maaif.getAspectInstance();
47+
synchronized (this) {
48+
if (this.materialized == null) {
49+
this.materialized = this.maaif.getAspectInstance();
50+
}
51+
}
4852
}
4953
return this.materialized;
5054
}
5155

52-
public ClassLoader getAspectClassLoader() {
53-
return this.maaif.getAspectClassLoader();
54-
}
55-
5656
public boolean isMaterialized() {
5757
return (this.materialized != null);
5858
}
5959

60+
public ClassLoader getAspectClassLoader() {
61+
return this.maaif.getAspectClassLoader();
62+
}
63+
6064
public AspectMetadata getAspectMetadata() {
6165
return this.maaif.getAspectMetadata();
6266
}
6367

6468
public int getOrder() {
65-
if (this.maaif instanceof Ordered) {
66-
return ((Ordered) this.maaif).getOrder();
67-
}
68-
return Ordered.LOWEST_PRECEDENCE;
69+
return this.maaif.getOrder();
6970
}
7071

7172

org.springframework.aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2008 the original author or authors.
2+
* Copyright 2002-2009 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -489,9 +489,7 @@ public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, C
489489
* Invoked when advice has changed.
490490
*/
491491
protected void adviceChanged() {
492-
synchronized (this.methodCache) {
493-
this.methodCache.clear();
494-
}
492+
this.methodCache.clear();
495493
}
496494

497495
/**

org.springframework.aop/src/main/java/org/springframework/aop/support/IntroductionInfoSupport.java

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2008 the original author or authors.
2+
* Copyright 2002-2009 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,13 +21,11 @@
2121
import java.io.Serializable;
2222
import java.lang.reflect.Method;
2323
import java.util.HashSet;
24-
import java.util.IdentityHashMap;
2524
import java.util.Map;
2625
import java.util.Set;
26+
import java.util.concurrent.ConcurrentHashMap;
2727

2828
import org.aopalliance.intercept.MethodInvocation;
29-
import org.apache.commons.logging.Log;
30-
import org.apache.commons.logging.LogFactory;
3129

3230
import org.springframework.aop.IntroductionInfo;
3331
import org.springframework.util.ClassUtils;
@@ -44,11 +42,9 @@
4442
*/
4543
public class IntroductionInfoSupport implements IntroductionInfo, Serializable {
4644

47-
protected transient Log logger = LogFactory.getLog(getClass());
45+
protected final Set<Class> publishedInterfaces = new HashSet<Class>();
4846

49-
protected Set<Class> publishedInterfaces = new HashSet<Class>();
50-
51-
private transient Map<Method, Boolean> rememberedMethods = new IdentityHashMap<Method, Boolean>(32);
47+
private transient Map<Method, Boolean> rememberedMethods = new ConcurrentHashMap<Method, Boolean>(32);
5248

5349

5450
/**
@@ -119,10 +115,8 @@ protected final boolean isMethodOnIntroducedInterface(MethodInvocation mi) {
119115
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
120116
// Rely on default serialization; just initialize state after deserialization.
121117
ois.defaultReadObject();
122-
123118
// Initialize transient fields.
124-
this.logger = LogFactory.getLog(getClass());
125-
this.rememberedMethods = new IdentityHashMap<Method, Boolean>(32);
119+
this.rememberedMethods = new ConcurrentHashMap<Method, Boolean>(32);
126120
}
127121

128122
}

0 commit comments

Comments
 (0)