Skip to content

Commit e18e7ec

Browse files
committed
No external locking for singleton advice/aspect beans
Issue: SPR-14324 (cherry picked from commit 5ac5ec1)
1 parent 1c80d2a commit e18e7ec

File tree

4 files changed

+45
-12
lines changed

4 files changed

+45
-12
lines changed

spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectInstanceFactory.java

+13-2
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,19 @@ public AspectMetadata getAspectMetadata() {
9797

9898
@Override
9999
public Object getAspectCreationMutex() {
100-
return (this.beanFactory instanceof ConfigurableBeanFactory ?
101-
((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex() : this);
100+
if (this.beanFactory != null) {
101+
if (this.beanFactory.isSingleton(name)) {
102+
// Rely on singleton semantics provided by the factory -> no local lock.
103+
return null;
104+
}
105+
else if (this.beanFactory instanceof ConfigurableBeanFactory) {
106+
// No singleton guarantees from the factory -> let's lock locally but
107+
// reuse the factory's singleton lock, just in case a lazy dependency
108+
// of our advice bean happens to trigger the singleton lock implicitly...
109+
return ((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex();
110+
}
111+
}
112+
return this;
102113
}
103114

104115
/**

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

+9-3
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,15 @@ public LazySingletonAspectInstanceFactoryDecorator(MetadataAwareAspectInstanceFa
4848
@Override
4949
public Object getAspectInstance() {
5050
if (this.materialized == null) {
51-
synchronized (this.maaif.getAspectCreationMutex()) {
52-
if (this.materialized == null) {
53-
this.materialized = this.maaif.getAspectInstance();
51+
Object mutex = this.maaif.getAspectCreationMutex();
52+
if (mutex == null) {
53+
this.materialized = this.maaif.getAspectInstance();
54+
}
55+
else {
56+
synchronized (mutex) {
57+
if (this.materialized == null) {
58+
this.materialized = this.maaif.getAspectInstance();
59+
}
5460
}
5561
}
5662
}

spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/MetadataAwareAspectInstanceFactory.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public interface MetadataAwareAspectInstanceFactory extends AspectInstanceFactor
4141

4242
/**
4343
* Return the best possible creation mutex for this factory.
44-
* @return the mutex object (never {@code null})
44+
* @return the mutex object (may be {@code null} for no mutex to use)
4545
* @since 4.3
4646
*/
4747
Object getAspectCreationMutex();

spring-aop/src/main/java/org/springframework/aop/support/AbstractBeanFactoryPointcutAdvisor.java

+22-6
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcu
4646

4747
private BeanFactory beanFactory;
4848

49-
private transient Advice advice;
49+
private transient volatile Advice advice;
5050

5151
private transient volatile Object adviceMonitor = new Object();
5252

@@ -98,12 +98,28 @@ public void setAdvice(Advice advice) {
9898

9999
@Override
100100
public Advice getAdvice() {
101-
synchronized (this.adviceMonitor) {
102-
if (this.advice == null && this.adviceBeanName != null) {
103-
Assert.state(this.beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'");
104-
this.advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
101+
Advice advice = this.advice;
102+
if (advice != null || this.adviceBeanName == null) {
103+
return advice;
104+
}
105+
106+
Assert.state(this.beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'");
107+
if (this.beanFactory.isSingleton(this.adviceBeanName)) {
108+
// Rely on singleton semantics provided by the factory.
109+
advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
110+
this.advice = advice;
111+
return advice;
112+
}
113+
else {
114+
// No singleton guarantees from the factory -> let's lock locally but
115+
// reuse the factory's singleton lock, just in case a lazy dependency
116+
// of our advice bean happens to trigger the singleton lock implicitly...
117+
synchronized (this.adviceMonitor) {
118+
if (this.advice == null) {
119+
this.advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
120+
}
121+
return this.advice;
105122
}
106-
return this.advice;
107123
}
108124
}
109125

0 commit comments

Comments
 (0)