Skip to content

Commit c986a1e

Browse files
committed
Cache target type per bean definition and allow for specifying it in advance
Issue: SPR-10335
1 parent 6a043e3 commit c986a1e

File tree

2 files changed

+39
-15
lines changed

2 files changed

+39
-15
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -572,25 +572,30 @@ else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
572572
}
573573

574574
@Override
575-
protected Class predictBeanType(String beanName, RootBeanDefinition mbd, Class... typesToMatch) {
576-
Class beanClass = (mbd.getFactoryMethodName() != null ?
577-
getTypeForFactoryMethod(beanName, mbd, typesToMatch) :
578-
resolveBeanClass(mbd, beanName, typesToMatch));
575+
protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class... typesToMatch) {
576+
Class<?> targetType = mbd.getTargetType();
577+
if (targetType == null) {
578+
targetType = (mbd.getFactoryMethodName() != null ? getTypeForFactoryMethod(beanName, mbd, typesToMatch) :
579+
resolveBeanClass(mbd, beanName, typesToMatch));
580+
if (ObjectUtils.isEmpty(typesToMatch) || getTempClassLoader() == null) {
581+
mbd.setTargetType(targetType);
582+
}
583+
}
579584
// Apply SmartInstantiationAwareBeanPostProcessors to predict the
580585
// eventual type after a before-instantiation shortcut.
581-
if (beanClass != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
586+
if (targetType != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
582587
for (BeanPostProcessor bp : getBeanPostProcessors()) {
583588
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
584589
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
585-
Class predicted = ibp.predictBeanType(beanClass, beanName);
590+
Class predicted = ibp.predictBeanType(targetType, beanName);
586591
if (predicted != null && (typesToMatch.length != 1 || !FactoryBean.class.equals(typesToMatch[0]) ||
587592
FactoryBean.class.isAssignableFrom(predicted))) {
588593
return predicted;
589594
}
590595
}
591596
}
592597
}
593-
return beanClass;
598+
return targetType;
594599
}
595600

596601
/**
@@ -607,8 +612,8 @@ protected Class predictBeanType(String beanName, RootBeanDefinition mbd, Class..
607612
* @return the type for the bean if determinable, or {@code null} else
608613
* @see #createBean
609614
*/
610-
protected Class getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class[] typesToMatch) {
611-
Class factoryClass;
615+
protected Class<?> getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class[] typesToMatch) {
616+
Class<?> factoryClass;
612617
boolean isStatic = true;
613618

614619
String factoryBeanName = mbd.getFactoryBeanName();

spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 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.
@@ -61,8 +61,12 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
6161

6262
boolean allowCaching = true;
6363

64+
private volatile Class<?> targetType;
65+
6466
boolean isFactoryMethodUnique = false;
6567

68+
final Object constructorArgumentLock = new Object();
69+
6670
/** Package-visible field for caching the resolved constructor or factory method */
6771
Object resolvedConstructorOrFactoryMethod;
6872

@@ -75,15 +79,13 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
7579
/** Package-visible field for caching partly prepared constructor arguments */
7680
Object[] preparedConstructorArguments;
7781

78-
final Object constructorArgumentLock = new Object();
79-
80-
/** Package-visible field that indicates a before-instantiation post-processor having kicked in */
81-
volatile Boolean beforeInstantiationResolved;
82+
final Object postProcessingLock = new Object();
8283

8384
/** Package-visible field that indicates MergedBeanDefinitionPostProcessor having been applied */
8485
boolean postProcessed = false;
8586

86-
final Object postProcessingLock = new Object();
87+
/** Package-visible field that indicates a before-instantiation post-processor having kicked in */
88+
volatile Boolean beforeInstantiationResolved;
8789

8890

8991
/**
@@ -236,6 +238,8 @@ public RootBeanDefinition(RootBeanDefinition original) {
236238
if (original instanceof RootBeanDefinition) {
237239
RootBeanDefinition originalRbd = (RootBeanDefinition) original;
238240
this.decoratedDefinition = originalRbd.decoratedDefinition;
241+
this.allowCaching = originalRbd.allowCaching;
242+
this.targetType = originalRbd.targetType;
239243
this.isFactoryMethodUnique = originalRbd.isFactoryMethodUnique;
240244
}
241245
}
@@ -251,6 +255,21 @@ public void setParentName(String parentName) {
251255
}
252256
}
253257

258+
/**
259+
* Specify the target type of this bean definition, if known in advance.
260+
*/
261+
public void setTargetType(Class<?> targetType) {
262+
this.targetType = targetType;
263+
}
264+
265+
/**
266+
* Return the target type of this bean definition, if known
267+
* (either specified in advance or resolved on first instantiation).
268+
*/
269+
public Class<?> getTargetType() {
270+
return this.targetType;
271+
}
272+
254273
/**
255274
* Specify a factory method name that refers to a non-overloaded method.
256275
*/

0 commit comments

Comments
 (0)