From a3c5625d4e1e2b5ca720b8e74797ee8bd30f54e4 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 13 May 2020 15:53:48 +0200 Subject: [PATCH] Internal cache of pre-filtered BeanPostProcessors (for faster iteration) Also includes bulk addition in PostProcessorRegistrationDelegate. Closes gh-24681 Closes gh-24756 --- .../AbstractAutowireCapableBeanFactory.java | 84 +++----- .../factory/support/AbstractBeanFactory.java | 202 +++++++++++++++--- .../support/DefaultListableBeanFactory.java | 7 +- .../support/DisposableBeanAdapter.java | 35 ++- .../PostProcessorRegistrationDelegate.java | 11 +- 5 files changed, 232 insertions(+), 107 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index be815c52c0..5ff1ef2656 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -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) { diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java index ad4c9c07a5..8d5d32de35 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java @@ -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 embeddedValueResolvers = new CopyOnWriteArrayList<>(); - /** BeanPostProcessors to apply in createBean. */ - private final List beanPostProcessors = new CopyOnWriteArrayList<>(); + /** BeanPostProcessors to apply. */ + private final List 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 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 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 { + + @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 c) { + boolean success = super.addAll(c); + if (success) { + beanPostProcessorCache = null; + } + return success; + } + + @Override + public boolean addAll(int index, Collection c) { + boolean success = super.addAll(index, c); + if (success) { + beanPostProcessorCache = null; + } + return success; + } + + @Override + public boolean removeIf(Predicate filter) { + boolean success = super.removeIf(filter); + if (success) { + beanPostProcessorCache = null; + } + return success; + } + + @Override + public void replaceAll(UnaryOperator operator) { + super.replaceAll(operator); + beanPostProcessorCache = null; + } + }; + + + /** + * Internal cache of pre-filtered post-processors. + * + * @since 5.3 + */ + static class BeanPostProcessorCache { + + final List instantiationAware = new ArrayList<>(); + + final List smartInstantiationAware = new ArrayList<>(); + + final List destructionAware = new ArrayList<>(); + + final List mergedDefinition = new ArrayList<>(); + } + } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java index 3bffd264e2..c6090bb493 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java @@ -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). diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java index c506958cf2..fb277b62b8 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java @@ -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 beanPostProcessors; + private final List beanPostProcessors; /** @@ -99,7 +98,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { * (potentially DestructionAwareBeanPostProcessor), if any */ public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition, - List postProcessors, @Nullable AccessControlContext acc) { + List 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 postProcessors, AccessControlContext acc) { + public DisposableBeanAdapter( + Object bean, List 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 filterPostProcessors(List processors, Object bean) { + private List filterPostProcessors( + List processors, Object bean) { + List 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 postProcessors) { + public static boolean hasApplicableProcessors(Object bean, List 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; } } } diff --git a/spring-context/src/main/java/org/springframework/context/support/PostProcessorRegistrationDelegate.java b/spring-context/src/main/java/org/springframework/context/support/PostProcessorRegistrationDelegate.java index d959e8de3c..0b070e4d72 100644 --- a/spring-context/src/main/java/org/springframework/context/support/PostProcessorRegistrationDelegate.java +++ b/spring-context/src/main/java/org/springframework/context/support/PostProcessorRegistrationDelegate.java @@ -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 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); + } } }