Cache target type per bean definition and allow for specifying it in advance
Issue: SPR-10335
This commit is contained in:
parent
6a043e3ea1
commit
c986a1efc1
|
@ -572,17 +572,22 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Class predictBeanType(String beanName, RootBeanDefinition mbd, Class... typesToMatch) {
|
||||
Class beanClass = (mbd.getFactoryMethodName() != null ?
|
||||
getTypeForFactoryMethod(beanName, mbd, typesToMatch) :
|
||||
resolveBeanClass(mbd, beanName, typesToMatch));
|
||||
protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class... typesToMatch) {
|
||||
Class<?> targetType = mbd.getTargetType();
|
||||
if (targetType == null) {
|
||||
targetType = (mbd.getFactoryMethodName() != null ? getTypeForFactoryMethod(beanName, mbd, typesToMatch) :
|
||||
resolveBeanClass(mbd, beanName, typesToMatch));
|
||||
if (ObjectUtils.isEmpty(typesToMatch) || getTempClassLoader() == null) {
|
||||
mbd.setTargetType(targetType);
|
||||
}
|
||||
}
|
||||
// Apply SmartInstantiationAwareBeanPostProcessors to predict the
|
||||
// eventual type after a before-instantiation shortcut.
|
||||
if (beanClass != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
|
||||
if (targetType != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
|
||||
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
||||
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
|
||||
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
|
||||
Class predicted = ibp.predictBeanType(beanClass, beanName);
|
||||
Class predicted = ibp.predictBeanType(targetType, beanName);
|
||||
if (predicted != null && (typesToMatch.length != 1 || !FactoryBean.class.equals(typesToMatch[0]) ||
|
||||
FactoryBean.class.isAssignableFrom(predicted))) {
|
||||
return predicted;
|
||||
|
@ -590,7 +595,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
|||
}
|
||||
}
|
||||
}
|
||||
return beanClass;
|
||||
return targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -607,8 +612,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
|||
* @return the type for the bean if determinable, or {@code null} else
|
||||
* @see #createBean
|
||||
*/
|
||||
protected Class getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class[] typesToMatch) {
|
||||
Class factoryClass;
|
||||
protected Class<?> getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class[] typesToMatch) {
|
||||
Class<?> factoryClass;
|
||||
boolean isStatic = true;
|
||||
|
||||
String factoryBeanName = mbd.getFactoryBeanName();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -61,8 +61,12 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
|||
|
||||
boolean allowCaching = true;
|
||||
|
||||
private volatile Class<?> targetType;
|
||||
|
||||
boolean isFactoryMethodUnique = false;
|
||||
|
||||
final Object constructorArgumentLock = new Object();
|
||||
|
||||
/** Package-visible field for caching the resolved constructor or factory method */
|
||||
Object resolvedConstructorOrFactoryMethod;
|
||||
|
||||
|
@ -75,15 +79,13 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
|||
/** Package-visible field for caching partly prepared constructor arguments */
|
||||
Object[] preparedConstructorArguments;
|
||||
|
||||
final Object constructorArgumentLock = new Object();
|
||||
|
||||
/** Package-visible field that indicates a before-instantiation post-processor having kicked in */
|
||||
volatile Boolean beforeInstantiationResolved;
|
||||
final Object postProcessingLock = new Object();
|
||||
|
||||
/** Package-visible field that indicates MergedBeanDefinitionPostProcessor having been applied */
|
||||
boolean postProcessed = false;
|
||||
|
||||
final Object postProcessingLock = new Object();
|
||||
/** Package-visible field that indicates a before-instantiation post-processor having kicked in */
|
||||
volatile Boolean beforeInstantiationResolved;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -236,6 +238,8 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
|||
if (original instanceof RootBeanDefinition) {
|
||||
RootBeanDefinition originalRbd = (RootBeanDefinition) original;
|
||||
this.decoratedDefinition = originalRbd.decoratedDefinition;
|
||||
this.allowCaching = originalRbd.allowCaching;
|
||||
this.targetType = originalRbd.targetType;
|
||||
this.isFactoryMethodUnique = originalRbd.isFactoryMethodUnique;
|
||||
}
|
||||
}
|
||||
|
@ -251,6 +255,21 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the target type of this bean definition, if known in advance.
|
||||
*/
|
||||
public void setTargetType(Class<?> targetType) {
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the target type of this bean definition, if known
|
||||
* (either specified in advance or resolved on first instantiation).
|
||||
*/
|
||||
public Class<?> getTargetType() {
|
||||
return this.targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a factory method name that refers to a non-overloaded method.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue