Internal cache of pre-filtered BeanPostProcessors (for faster iteration)

Also includes bulk addition in PostProcessorRegistrationDelegate.

Closes gh-24681
Closes gh-24756
This commit is contained in:
Juergen Hoeller
2020-05-13 15:53:48 +02:00
parent 875e7f8630
commit a3c5625d4e
5 changed files with 232 additions and 107 deletions

View File

@@ -439,7 +439,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
@Override
public void destroyBean(Object existingBean) {
new DisposableBeanAdapter(existingBean, getBeanPostProcessors(), getAccessControlContext()).destroy();
new DisposableBeanAdapter(
existingBean, getBeanPostProcessorCache().destructionAware, getAccessControlContext()).destroy();
}
@@ -651,14 +652,11 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
// eventual type after a before-instantiation shortcut.
if (targetType != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
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 (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
Class<?> predicted = bp.predictBeanType(targetType, beanName);
if (predicted != null &&
(!matchingOnlyFactoryBean || FactoryBean.class.isAssignableFrom(predicted))) {
return predicted;
}
}
}
@@ -959,11 +957,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
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);
}
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
@@ -1088,11 +1083,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
* @see MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
*/
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
@@ -1135,13 +1127,10 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
*/
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
return null;
@@ -1280,13 +1269,10 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
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;
}
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
Constructor<?>[] ctors = bp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
}
@@ -1382,12 +1368,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
@@ -1416,21 +1399,18 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
pvs = pvsToUse;
}
pvs = pvsToUse;
}
}
if (needsDepCheck) {

View File

@@ -24,6 +24,7 @@ import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -34,6 +35,8 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
@@ -65,6 +68,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory;
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;
@@ -150,14 +154,12 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
/** String resolvers to apply e.g. to annotation attribute values. */
private final List<StringValueResolver> embeddedValueResolvers = new CopyOnWriteArrayList<>();
/** BeanPostProcessors to apply in createBean. */
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
/** BeanPostProcessors to apply. */
private final List<BeanPostProcessor> beanPostProcessors = new BeanPostProcessorCacheAwareList();
/** Indicates whether any InstantiationAwareBeanPostProcessors have been registered. */
private volatile boolean hasInstantiationAwareBeanPostProcessors;
/** Indicates whether any DestructionAwareBeanPostProcessors have been registered. */
private volatile boolean hasDestructionAwareBeanPostProcessors;
/** Cache of pre-filtered post-processors. */
@Nullable
private volatile BeanPostProcessorCache beanPostProcessorCache;
/** Map from scope identifier String to corresponding Scope. */
private final Map<String, Scope> scopes = new LinkedHashMap<>(8);
@@ -922,17 +924,21 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
// Remove from old position, if any
this.beanPostProcessors.remove(beanPostProcessor);
// Track whether it is instantiation/destruction aware
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true;
}
// Add to end of list
this.beanPostProcessors.add(beanPostProcessor);
}
/**
* Add new BeanPostProcessors that will get applied to beans created
* by this factory. To be invoked during factory configuration.
* @since 5.3
* @see #addBeanPostProcessor
*/
public void addBeanPostProcessors(Collection<? extends BeanPostProcessor> beanPostProcessors) {
this.beanPostProcessors.removeAll(beanPostProcessors);
this.beanPostProcessors.addAll(beanPostProcessors);
}
@Override
public int getBeanPostProcessorCount() {
return this.beanPostProcessors.size();
@@ -946,14 +952,42 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
return this.beanPostProcessors;
}
/**
* Return the internal cache of pre-filtered post-processors,
* freshly (re-)building it if necessary.
* @since 5.3
*/
BeanPostProcessorCache getBeanPostProcessorCache() {
BeanPostProcessorCache bpCache = this.beanPostProcessorCache;
if (bpCache == null) {
bpCache = new BeanPostProcessorCache();
for (BeanPostProcessor bp : this.beanPostProcessors) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
bpCache.instantiationAware.add((InstantiationAwareBeanPostProcessor) bp);
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
bpCache.smartInstantiationAware.add((SmartInstantiationAwareBeanPostProcessor) bp);
}
}
if (bp instanceof DestructionAwareBeanPostProcessor) {
bpCache.destructionAware.add((DestructionAwareBeanPostProcessor) bp);
}
if (bp instanceof MergedBeanDefinitionPostProcessor) {
bpCache.mergedDefinition.add((MergedBeanDefinitionPostProcessor) bp);
}
}
this.beanPostProcessorCache = bpCache;
}
return bpCache;
}
/**
* 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 !getBeanPostProcessorCache().instantiationAware.isEmpty();
}
/**
@@ -963,7 +997,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
* @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor
*/
protected boolean hasDestructionAwareBeanPostProcessors() {
return this.hasDestructionAwareBeanPostProcessors;
return !getBeanPostProcessorCache().destructionAware.isEmpty();
}
@Override
@@ -1031,10 +1065,6 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
this.customEditors.putAll(otherAbstractFactory.customEditors);
this.typeConverter = otherAbstractFactory.typeConverter;
this.beanPostProcessors.addAll(otherAbstractFactory.beanPostProcessors);
this.hasInstantiationAwareBeanPostProcessors = this.hasInstantiationAwareBeanPostProcessors ||
otherAbstractFactory.hasInstantiationAwareBeanPostProcessors;
this.hasDestructionAwareBeanPostProcessors = this.hasDestructionAwareBeanPostProcessors ||
otherAbstractFactory.hasDestructionAwareBeanPostProcessors;
this.scopes.putAll(otherAbstractFactory.scopes);
this.securityContextProvider = otherAbstractFactory.securityContextProvider;
}
@@ -1158,7 +1188,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
* @param mbd the merged bean definition
*/
protected void destroyBean(String beanName, Object bean, RootBeanDefinition mbd) {
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), getAccessControlContext()).destroy();
new DisposableBeanAdapter(
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, getAccessControlContext()).destroy();
}
@Override
@@ -1844,9 +1875,9 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
* @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor
*/
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
return (bean.getClass() != NullBean.class &&
(DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() &&
DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))));
return (bean.getClass() != NullBean.class && (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) ||
(hasDestructionAwareBeanPostProcessors() && DisposableBeanAdapter.hasApplicableProcessors(
bean, getBeanPostProcessorCache().destructionAware))));
}
/**
@@ -1868,8 +1899,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
// Register a DisposableBean implementation that performs all destruction
// work for the given bean: DestructionAwareBeanPostProcessors,
// DisposableBean interface, custom destroy method.
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
registerDisposableBean(beanName, new DisposableBeanAdapter(
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
}
else {
// A bean with a custom scope...
@@ -1877,8 +1908,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
}
}
}
@@ -1940,4 +1971,117 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException;
/**
* CopyOnWriteArrayList which resets the beanPostProcessorCache field on modification.
*
* @since 5.3
*/
private class BeanPostProcessorCacheAwareList extends CopyOnWriteArrayList<BeanPostProcessor> {
@Override
public BeanPostProcessor set(int index, BeanPostProcessor element) {
BeanPostProcessor result = super.set(index, element);
beanPostProcessorCache = null;
return result;
}
@Override
public boolean add(BeanPostProcessor o) {
boolean success = super.add(o);
beanPostProcessorCache = null;
return success;
}
@Override
public void add(int index, BeanPostProcessor element) {
super.add(index, element);
beanPostProcessorCache = null;
}
@Override
public BeanPostProcessor remove(int index) {
BeanPostProcessor result = super.remove(index);
beanPostProcessorCache = null;
return result;
}
@Override
public boolean remove(Object o) {
boolean success = super.remove(o);
if (success) {
beanPostProcessorCache = null;
}
return success;
}
@Override
public boolean removeAll(Collection<?> c) {
boolean success = super.removeAll(c);
if (success) {
beanPostProcessorCache = null;
}
return success;
}
@Override
public boolean retainAll(Collection<?> c) {
boolean success = super.retainAll(c);
if (success) {
beanPostProcessorCache = null;
}
return success;
}
@Override
public boolean addAll(Collection<? extends BeanPostProcessor> c) {
boolean success = super.addAll(c);
if (success) {
beanPostProcessorCache = null;
}
return success;
}
@Override
public boolean addAll(int index, Collection<? extends BeanPostProcessor> c) {
boolean success = super.addAll(index, c);
if (success) {
beanPostProcessorCache = null;
}
return success;
}
@Override
public boolean removeIf(Predicate<? super BeanPostProcessor> filter) {
boolean success = super.removeIf(filter);
if (success) {
beanPostProcessorCache = null;
}
return success;
}
@Override
public void replaceAll(UnaryOperator<BeanPostProcessor> operator) {
super.replaceAll(operator);
beanPostProcessorCache = null;
}
};
/**
* Internal cache of pre-filtered post-processors.
*
* @since 5.3
*/
static class BeanPostProcessorCache {
final List<InstantiationAwareBeanPostProcessor> instantiationAware = new ArrayList<>();
final List<SmartInstantiationAwareBeanPostProcessor> smartInstantiationAware = new ArrayList<>();
final List<DestructionAwareBeanPostProcessor> destructionAware = new ArrayList<>();
final List<MergedBeanDefinitionPostProcessor> mergedDefinition = new ArrayList<>();
}
}

View File

@@ -68,7 +68,6 @@ import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
@@ -1045,10 +1044,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
destroySingleton(beanName);
// Notify all post-processors that the specified bean definition has been reset.
for (BeanPostProcessor processor : getBeanPostProcessors()) {
if (processor instanceof MergedBeanDefinitionPostProcessor) {
((MergedBeanDefinitionPostProcessor) processor).resetBeanDefinition(beanName);
}
for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
processor.resetBeanDefinition(beanName);
}
// Reset all bean definitions that have the given bean as parent (recursively).

View File

@@ -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.
@@ -32,7 +32,6 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -87,7 +86,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
private transient Method destroyMethod;
@Nullable
private List<DestructionAwareBeanPostProcessor> beanPostProcessors;
private final List<DestructionAwareBeanPostProcessor> beanPostProcessors;
/**
@@ -99,7 +98,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
* (potentially DestructionAwareBeanPostProcessor), if any
*/
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
List<BeanPostProcessor> postProcessors, @Nullable AccessControlContext acc) {
List<DestructionAwareBeanPostProcessor> postProcessors, @Nullable AccessControlContext acc) {
Assert.notNull(bean, "Disposable bean must not be null");
this.bean = bean;
@@ -142,7 +141,9 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
* @param postProcessors the List of BeanPostProcessors
* (potentially DestructionAwareBeanPostProcessor), if any
*/
public DisposableBeanAdapter(Object bean, List<BeanPostProcessor> postProcessors, AccessControlContext acc) {
public DisposableBeanAdapter(
Object bean, List<DestructionAwareBeanPostProcessor> postProcessors, AccessControlContext acc) {
Assert.notNull(bean, "Disposable bean must not be null");
this.bean = bean;
this.beanName = bean.getClass().getName();
@@ -213,16 +214,15 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
* @return the filtered List of DestructionAwareBeanPostProcessors
*/
@Nullable
private List<DestructionAwareBeanPostProcessor> filterPostProcessors(List<BeanPostProcessor> processors, Object bean) {
private List<DestructionAwareBeanPostProcessor> filterPostProcessors(
List<DestructionAwareBeanPostProcessor> processors, Object bean) {
List<DestructionAwareBeanPostProcessor> filteredPostProcessors = null;
if (!CollectionUtils.isEmpty(processors)) {
filteredPostProcessors = new ArrayList<>(processors.size());
for (BeanPostProcessor processor : processors) {
if (processor instanceof DestructionAwareBeanPostProcessor) {
DestructionAwareBeanPostProcessor dabpp = (DestructionAwareBeanPostProcessor) processor;
if (dabpp.requiresDestruction(bean)) {
filteredPostProcessors.add(dabpp);
}
for (DestructionAwareBeanPostProcessor processor : processors) {
if (processor.requiresDestruction(bean)) {
filteredPostProcessors.add(processor);
}
}
}
@@ -397,14 +397,11 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
* @param bean the bean instance
* @param postProcessors the post-processor candidates
*/
public static boolean hasApplicableProcessors(Object bean, List<BeanPostProcessor> postProcessors) {
public static boolean hasApplicableProcessors(Object bean, List<DestructionAwareBeanPostProcessor> postProcessors) {
if (!CollectionUtils.isEmpty(postProcessors)) {
for (BeanPostProcessor processor : postProcessors) {
if (processor instanceof DestructionAwareBeanPostProcessor) {
DestructionAwareBeanPostProcessor dabpp = (DestructionAwareBeanPostProcessor) processor;
if (dabpp.requiresDestruction(bean)) {
return true;
}
for (DestructionAwareBeanPostProcessor processor : postProcessors) {
if (processor.requiresDestruction(bean)) {
return true;
}
}
}

View File

@@ -30,6 +30,7 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
@@ -298,8 +299,14 @@ final class PostProcessorRegistrationDelegate {
private static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
for (BeanPostProcessor postProcessor : postProcessors) {
beanFactory.addBeanPostProcessor(postProcessor);
if (beanFactory instanceof AbstractBeanFactory) {
// Bulk addition is more efficient against our CopyOnWriteArrayList there
((AbstractBeanFactory) beanFactory).addBeanPostProcessors(postProcessors);
}
else {
for (BeanPostProcessor postProcessor : postProcessors) {
beanFactory.addBeanPostProcessor(postProcessor);
}
}
}