Skip to content

Commit

Permalink
No external locking for singleton advice/aspect beans
Browse files Browse the repository at this point in the history
Issue: SPR-14324
  • Loading branch information
jhoeller committed Oct 28, 2016
1 parent 72e1f7e commit 5ac5ec1
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,19 @@ public AspectMetadata getAspectMetadata() {

@Override
public Object getAspectCreationMutex() {
return (this.beanFactory instanceof ConfigurableBeanFactory ?
((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex() : this);
if (this.beanFactory != null) {
if (this.beanFactory.isSingleton(name)) {
// Rely on singleton semantics provided by the factory -> no local lock.
return null;
}
else if (this.beanFactory instanceof ConfigurableBeanFactory) {
// No singleton guarantees from the factory -> let's lock locally but
// reuse the factory's singleton lock, just in case a lazy dependency
// of our advice bean happens to trigger the singleton lock implicitly...
return ((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex();
}
}
return this;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,15 @@ public LazySingletonAspectInstanceFactoryDecorator(MetadataAwareAspectInstanceFa
@Override
public Object getAspectInstance() {
if (this.materialized == null) {
synchronized (this.maaif.getAspectCreationMutex()) {
if (this.materialized == null) {
this.materialized = this.maaif.getAspectInstance();
Object mutex = this.maaif.getAspectCreationMutex();
if (mutex == null) {
this.materialized = this.maaif.getAspectInstance();
}
else {
synchronized (mutex) {
if (this.materialized == null) {
this.materialized = this.maaif.getAspectInstance();
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public interface MetadataAwareAspectInstanceFactory extends AspectInstanceFactor

/**
* Return the best possible creation mutex for this factory.
* @return the mutex object (never {@code null})
* @return the mutex object (may be {@code null} for no mutex to use)
* @since 4.3
*/
Object getAspectCreationMutex();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcu

private BeanFactory beanFactory;

private transient Advice advice;
private transient volatile Advice advice;

private transient volatile Object adviceMonitor = new Object();

Expand Down Expand Up @@ -98,12 +98,28 @@ public void setAdvice(Advice advice) {

@Override
public Advice getAdvice() {
synchronized (this.adviceMonitor) {
if (this.advice == null && this.adviceBeanName != null) {
Assert.state(this.beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'");
this.advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
Advice advice = this.advice;
if (advice != null || this.adviceBeanName == null) {
return advice;
}

Assert.state(this.beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'");
if (this.beanFactory.isSingleton(this.adviceBeanName)) {
// Rely on singleton semantics provided by the factory.
advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
this.advice = advice;
return advice;
}
else {
// No singleton guarantees from the factory -> let's lock locally but
// reuse the factory's singleton lock, just in case a lazy dependency
// of our advice bean happens to trigger the singleton lock implicitly...
synchronized (this.adviceMonitor) {
if (this.advice == null) {
this.advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
}
return this.advice;
}
return this.advice;
}
}

Expand Down

0 comments on commit 5ac5ec1

Please sign in to comment.