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
|
@Override
|
||||||
protected Class predictBeanType(String beanName, RootBeanDefinition mbd, Class... typesToMatch) {
|
protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class... typesToMatch) {
|
||||||
Class beanClass = (mbd.getFactoryMethodName() != null ?
|
Class<?> targetType = mbd.getTargetType();
|
||||||
getTypeForFactoryMethod(beanName, mbd, typesToMatch) :
|
if (targetType == null) {
|
||||||
resolveBeanClass(mbd, beanName, typesToMatch));
|
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
|
// Apply SmartInstantiationAwareBeanPostProcessors to predict the
|
||||||
// eventual type after a before-instantiation shortcut.
|
// eventual type after a before-instantiation shortcut.
|
||||||
if (beanClass != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
|
if (targetType != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
|
||||||
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
||||||
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
|
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
|
||||||
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
|
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]) ||
|
if (predicted != null && (typesToMatch.length != 1 || !FactoryBean.class.equals(typesToMatch[0]) ||
|
||||||
FactoryBean.class.isAssignableFrom(predicted))) {
|
FactoryBean.class.isAssignableFrom(predicted))) {
|
||||||
return 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
|
* @return the type for the bean if determinable, or {@code null} else
|
||||||
* @see #createBean
|
* @see #createBean
|
||||||
*/
|
*/
|
||||||
protected Class getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class[] typesToMatch) {
|
protected Class<?> getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class[] typesToMatch) {
|
||||||
Class factoryClass;
|
Class<?> factoryClass;
|
||||||
boolean isStatic = true;
|
boolean isStatic = true;
|
||||||
|
|
||||||
String factoryBeanName = mbd.getFactoryBeanName();
|
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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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;
|
boolean allowCaching = true;
|
||||||
|
|
||||||
|
private volatile Class<?> targetType;
|
||||||
|
|
||||||
boolean isFactoryMethodUnique = false;
|
boolean isFactoryMethodUnique = false;
|
||||||
|
|
||||||
|
final Object constructorArgumentLock = new Object();
|
||||||
|
|
||||||
/** Package-visible field for caching the resolved constructor or factory method */
|
/** Package-visible field for caching the resolved constructor or factory method */
|
||||||
Object resolvedConstructorOrFactoryMethod;
|
Object resolvedConstructorOrFactoryMethod;
|
||||||
|
|
||||||
|
|
@ -75,15 +79,13 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||||
/** Package-visible field for caching partly prepared constructor arguments */
|
/** Package-visible field for caching partly prepared constructor arguments */
|
||||||
Object[] preparedConstructorArguments;
|
Object[] preparedConstructorArguments;
|
||||||
|
|
||||||
final Object constructorArgumentLock = new Object();
|
final Object postProcessingLock = new Object();
|
||||||
|
|
||||||
/** Package-visible field that indicates a before-instantiation post-processor having kicked in */
|
|
||||||
volatile Boolean beforeInstantiationResolved;
|
|
||||||
|
|
||||||
/** Package-visible field that indicates MergedBeanDefinitionPostProcessor having been applied */
|
/** Package-visible field that indicates MergedBeanDefinitionPostProcessor having been applied */
|
||||||
boolean postProcessed = false;
|
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) {
|
if (original instanceof RootBeanDefinition) {
|
||||||
RootBeanDefinition originalRbd = (RootBeanDefinition) original;
|
RootBeanDefinition originalRbd = (RootBeanDefinition) original;
|
||||||
this.decoratedDefinition = originalRbd.decoratedDefinition;
|
this.decoratedDefinition = originalRbd.decoratedDefinition;
|
||||||
|
this.allowCaching = originalRbd.allowCaching;
|
||||||
|
this.targetType = originalRbd.targetType;
|
||||||
this.isFactoryMethodUnique = originalRbd.isFactoryMethodUnique;
|
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.
|
* Specify a factory method name that refers to a non-overloaded method.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue