Skip to content

Commit b79260a

Browse files
committed
Fixed potential race condition in concurrent calling of autowired methods on a prototype bean
Autowired methods might have been skipped on subsequent creation of further bean instances due to the 'skip' flag set to false outside of the synchronized block, with another thread entering the block and setting the flag to true in the meantime. Issue: SPR-9806
1 parent 0f522cf commit b79260a

File tree

1 file changed

+32
-23
lines changed

1 file changed

+32
-23
lines changed

org.springframework.beans/src/main/java/org/springframework/beans/factory/annotation/InjectionMetadata.java

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2011 the original author or authors.
2+
* Copyright 2002-2012 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.
@@ -54,17 +54,22 @@ public class InjectionMetadata {
5454

5555

5656
public InjectionMetadata(Class targetClass, Collection<InjectedElement> elements) {
57-
this.injectedElements = Collections.synchronizedSet(new LinkedHashSet<InjectedElement>());
58-
for (InjectedElement element : elements) {
59-
if (logger.isDebugEnabled()) {
60-
logger.debug("Found injected element on class [" + targetClass.getName() + "]: " + element);
57+
if (!elements.isEmpty()) {
58+
this.injectedElements = Collections.synchronizedSet(new LinkedHashSet<InjectedElement>(elements.size()));
59+
for (InjectedElement element : elements) {
60+
if (logger.isDebugEnabled()) {
61+
logger.debug("Found injected element on class [" + targetClass.getName() + "]: " + element);
62+
}
63+
this.injectedElements.add(element);
6164
}
62-
this.injectedElements.add(element);
65+
}
66+
else {
67+
this.injectedElements = Collections.emptySet();
6368
}
6469
}
6570

6671
public void checkConfigMembers(RootBeanDefinition beanDefinition) {
67-
synchronized(this.injectedElements) {
72+
synchronized (this.injectedElements) {
6873
for (Iterator<InjectedElement> it = this.injectedElements.iterator(); it.hasNext();) {
6974
Member member = it.next().getMember();
7075
if (!beanDefinition.isExternallyManagedConfigMember(member)) {
@@ -170,26 +175,30 @@ protected void inject(Object target, String requestingBeanName, PropertyValues p
170175
* affected property as processed for other processors to ignore it.
171176
*/
172177
protected boolean checkPropertySkipping(PropertyValues pvs) {
173-
if (this.skip == null) {
174-
if (pvs != null) {
175-
synchronized (pvs) {
176-
if (this.skip == null) {
177-
if (this.pd != null) {
178-
if (pvs.contains(this.pd.getName())) {
179-
// Explicit value provided as part of the bean definition.
180-
this.skip = true;
181-
return true;
182-
}
183-
else if (pvs instanceof MutablePropertyValues) {
184-
((MutablePropertyValues) pvs).registerProcessedProperty(this.pd.getName());
185-
}
186-
}
187-
}
178+
if (this.skip != null) {
179+
return this.skip;
180+
}
181+
if (pvs == null) {
182+
this.skip = false;
183+
return false;
184+
}
185+
synchronized (pvs) {
186+
if (this.skip != null) {
187+
return this.skip;
188+
}
189+
if (this.pd != null) {
190+
if (pvs.contains(this.pd.getName())) {
191+
// Explicit value provided as part of the bean definition.
192+
this.skip = true;
193+
return true;
194+
}
195+
else if (pvs instanceof MutablePropertyValues) {
196+
((MutablePropertyValues) pvs).registerProcessedProperty(this.pd.getName());
188197
}
189198
}
190199
this.skip = false;
200+
return false;
191201
}
192-
return this.skip;
193202
}
194203

195204
/**

0 commit comments

Comments
 (0)