Skip to content

Improve performance of AbstractAutowireCapableBeanFactory#predictBeanType #24681

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2020 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.
Expand Down Expand Up @@ -150,6 +150,8 @@ protected DefaultListableBeanFactory buildInternalBeanFactory(ConfigurableBeanFa
// since those are only meant to apply to beans defined in the original factory.
internalBeanFactory.getBeanPostProcessors().removeIf(beanPostProcessor ->
beanPostProcessor instanceof AopInfrastructureBean);
internalBeanFactory.getSmartBeanPostProcessors().removeIf(beanPostProcessor ->
beanPostProcessor instanceof AopInfrastructureBean);

return internalBeanFactory;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 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.
Expand Down Expand Up @@ -649,16 +649,14 @@ protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Clas
Class<?> targetType = determineTargetType(beanName, mbd, typesToMatch);
// Apply SmartInstantiationAwareBeanPostProcessors to predict the
// eventual type after a before-instantiation shortcut.
if (targetType != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
if (targetType != null && !mbd.isSynthetic() && hasSmartInstantiationAwareBeanPostProcessors()) {
boolean matchingOnlyFactoryBean = typesToMatch.length == 1 && typesToMatch[0] == FactoryBean.class;
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
Class<?> predicted = ibp.predictBeanType(targetType, beanName);
if (predicted != null &&
(!matchingOnlyFactoryBean || FactoryBean.class.isAssignableFrom(predicted))) {
return predicted;
}
for (BeanPostProcessor bp : getSmartBeanPostProcessors()) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
Class<?> predicted = ibp.predictBeanType(targetType, beanName);
if (predicted != null &&
(!matchingOnlyFactoryBean || FactoryBean.class.isAssignableFrom(predicted))) {
return predicted;
}
}
}
Expand Down Expand Up @@ -958,12 +956,10 @@ protected Class<?> getTypeForFactoryBean(String beanName, RootBeanDefinition mbd
*/
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
if (!mbd.isSynthetic() && hasSmartInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getSmartBeanPostProcessors()) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
Expand Down Expand Up @@ -1279,14 +1275,12 @@ protected Object getObjectForBeanInstance(
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
throws BeansException {

if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
if (beanClass != null && hasSmartInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getSmartBeanPostProcessors()) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.config.Scope;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
import org.springframework.core.AttributeAccessor;
import org.springframework.core.DecoratingClassLoader;
import org.springframework.core.NamedThreadLocal;
Expand Down Expand Up @@ -153,9 +154,15 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
/** BeanPostProcessors to apply in createBean. */
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();

/** Smart BeanPostProcessors to apply when predicting bean types. */
private final List<BeanPostProcessor> smartBeanPostProcessors = new CopyOnWriteArrayList<>();

/** Indicates whether any InstantiationAwareBeanPostProcessors have been registered. */
private volatile boolean hasInstantiationAwareBeanPostProcessors;

/** Indicates whether any SmartInstantiationAwareBeanPostProcessor have been registered. */
private volatile boolean hasSmartInstantiationAwareBeanPostProcessors;

/** Indicates whether any DestructionAwareBeanPostProcessors have been registered. */
private volatile boolean hasDestructionAwareBeanPostProcessors;

Expand Down Expand Up @@ -923,6 +930,11 @@ public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof SmartInstantiationAwareBeanPostProcessor) {
this.smartBeanPostProcessors.remove(beanPostProcessor);
this.hasSmartInstantiationAwareBeanPostProcessors = true;
this.smartBeanPostProcessors.add(beanPostProcessor);
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true;
}
Expand All @@ -943,16 +955,34 @@ public List<BeanPostProcessor> getBeanPostProcessors() {
return this.beanPostProcessors;
}

/**
* Return the list of smart BeanPostProcessors that will get applied
* to beans created with this factory.
*/
public List<BeanPostProcessor> getSmartBeanPostProcessors() {
return this.smartBeanPostProcessors;
}

/**
* Return whether this factory holds a InstantiationAwareBeanPostProcessor
* that will get applied to singleton beans on shutdown.
* that will get applied to singleton beans on creation.
* @see #addBeanPostProcessor
* @see org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor
*/
protected boolean hasInstantiationAwareBeanPostProcessors() {
return this.hasInstantiationAwareBeanPostProcessors;
}

/**
* Return whether this factory holds a SmartInstantiationAwareBeanPostProcessor
* that will get applied to singleton beans on creation.
* @see #addBeanPostProcessor
* @see org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor
*/
protected boolean hasSmartInstantiationAwareBeanPostProcessors() {
return this.hasSmartInstantiationAwareBeanPostProcessors;
}

/**
* Return whether this factory holds a DestructionAwareBeanPostProcessor
* that will get applied to singleton beans on shutdown.
Expand Down Expand Up @@ -1028,8 +1058,11 @@ public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
this.customEditors.putAll(otherAbstractFactory.customEditors);
this.typeConverter = otherAbstractFactory.typeConverter;
this.beanPostProcessors.addAll(otherAbstractFactory.beanPostProcessors);
this.smartBeanPostProcessors.addAll(otherAbstractFactory.smartBeanPostProcessors);
this.hasInstantiationAwareBeanPostProcessors = this.hasInstantiationAwareBeanPostProcessors ||
otherAbstractFactory.hasInstantiationAwareBeanPostProcessors;
this.hasSmartInstantiationAwareBeanPostProcessors = this.hasSmartInstantiationAwareBeanPostProcessors ||
otherAbstractFactory.hasSmartInstantiationAwareBeanPostProcessors;
this.hasDestructionAwareBeanPostProcessors = this.hasDestructionAwareBeanPostProcessors ||
otherAbstractFactory.hasDestructionAwareBeanPostProcessors;
this.scopes.putAll(otherAbstractFactory.scopes);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2020 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.
Expand Down Expand Up @@ -234,6 +234,8 @@ public void setBeanFactory(BeanFactory beanFactory) {
// since those are only meant to apply to beans defined in the original factory.
this.scriptBeanFactory.getBeanPostProcessors().removeIf(beanPostProcessor ->
beanPostProcessor instanceof AopInfrastructureBean);
this.scriptBeanFactory.getSmartBeanPostProcessors().removeIf(beanPostProcessor ->
beanPostProcessor instanceof AopInfrastructureBean);
}

@Override
Expand Down