Separate factory method cache for introspection purposes

Issue: SPR-17358
Issue: SPR-8891
This commit is contained in:
Juergen Hoeller 2018-10-12 22:53:50 +02:00
parent 658c7f99d7
commit 309e70a48e
5 changed files with 13 additions and 17 deletions

View File

@ -775,6 +775,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
}
}
mbd.factoryMethodToIntrospect = uniqueCandidate;
if (commonType == null) {
return null;
}

View File

@ -337,9 +337,7 @@ class ConstructorResolver {
}
}
}
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
}
mbd.factoryMethodToIntrospect = uniqueCandidate;
}
/**
@ -448,6 +446,7 @@ class ConstructorResolver {
if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Method uniqueCandidate = candidateList.get(0);
if (uniqueCandidate.getParameterCount() == 0) {
mbd.factoryMethodToIntrospect = uniqueCandidate;
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
@ -598,6 +597,7 @@ class ConstructorResolver {
}
if (explicitArgs == null && argsHolderToUse != null) {
mbd.factoryMethodToIntrospect = factoryMethodToUse;
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
}

View File

@ -755,14 +755,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
String beanDefinitionName = BeanFactoryUtils.transformedBeanName(beanName);
resolveBeanClass(mbd, beanDefinitionName);
if (mbd.isFactoryMethodUnique) {
boolean resolve;
synchronized (mbd.constructorArgumentLock) {
resolve = (mbd.resolvedConstructorOrFactoryMethod == null);
}
if (resolve) {
new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd);
}
if (mbd.isFactoryMethodUnique && mbd.factoryMethodToIntrospect == null) {
new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd);
}
return resolver.isAutowireCandidate(
new BeanDefinitionHolder(mbd, beanName, getAliases(beanDefinitionName)), descriptor);

View File

@ -75,6 +75,10 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
@Nullable
volatile ResolvableType factoryMethodReturnType;
/** Package-visible field for caching a unique factory method candidate for introspection. */
@Nullable
volatile Method factoryMethodToIntrospect;
/** Common lock for the four constructor fields below. */
final Object constructorArgumentLock = new Object();
@ -370,10 +374,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
*/
@Nullable
public Method getResolvedFactoryMethod() {
synchronized (this.constructorArgumentLock) {
Executable candidate = this.resolvedConstructorOrFactoryMethod;
return (candidate instanceof Method ? (Method) candidate : null);
}
return this.factoryMethodToIntrospect;
}
public void registerExternallyManagedConfigMember(Member configMember) {

View File

@ -83,8 +83,8 @@ public class BeanMethodQualificationTests {
new AnnotationConfigApplicationContext(CustomConfig.class, CustomPojo.class);
assertFalse(ctx.getBeanFactory().containsSingleton("testBean1"));
assertFalse(ctx.getBeanFactory().containsSingleton("testBean2"));
// TODO: assertTrue(BeanFactoryAnnotationUtils.isQualifierMatch(value -> value.equals("boring"),
// "testBean2", ctx.getDefaultListableBeanFactory()));
assertTrue(BeanFactoryAnnotationUtils.isQualifierMatch(value -> value.equals("boring"),
"testBean2", ctx.getDefaultListableBeanFactory()));
CustomPojo pojo = ctx.getBean(CustomPojo.class);
assertThat(pojo.testBean.getName(), equalTo("interesting"));
TestBean testBean2 = BeanFactoryAnnotationUtils.qualifiedBeanOfType(