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

View File

@@ -24,6 +24,7 @@ import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@@ -34,6 +35,8 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper; 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.DestructionAwareBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.config.Scope; import org.springframework.beans.factory.config.Scope;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
import org.springframework.core.AttributeAccessor; import org.springframework.core.AttributeAccessor;
import org.springframework.core.DecoratingClassLoader; import org.springframework.core.DecoratingClassLoader;
import org.springframework.core.NamedThreadLocal; 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. */ /** String resolvers to apply e.g. to annotation attribute values. */
private final List<StringValueResolver> embeddedValueResolvers = new CopyOnWriteArrayList<>(); private final List<StringValueResolver> embeddedValueResolvers = new CopyOnWriteArrayList<>();
/** BeanPostProcessors to apply in createBean. */ /** BeanPostProcessors to apply. */
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>(); private final List<BeanPostProcessor> beanPostProcessors = new BeanPostProcessorCacheAwareList();
/** Indicates whether any InstantiationAwareBeanPostProcessors have been registered. */ /** Cache of pre-filtered post-processors. */
private volatile boolean hasInstantiationAwareBeanPostProcessors; @Nullable
private volatile BeanPostProcessorCache beanPostProcessorCache;
/** Indicates whether any DestructionAwareBeanPostProcessors have been registered. */
private volatile boolean hasDestructionAwareBeanPostProcessors;
/** Map from scope identifier String to corresponding Scope. */ /** Map from scope identifier String to corresponding Scope. */
private final Map<String, Scope> scopes = new LinkedHashMap<>(8); 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"); Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
// Remove from old position, if any // Remove from old position, if any
this.beanPostProcessors.remove(beanPostProcessor); 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 // Add to end of list
this.beanPostProcessors.add(beanPostProcessor); 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 @Override
public int getBeanPostProcessorCount() { public int getBeanPostProcessorCount() {
return this.beanPostProcessors.size(); return this.beanPostProcessors.size();
@@ -946,14 +952,42 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
return this.beanPostProcessors; 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 * 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 #addBeanPostProcessor
* @see org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor * @see org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor
*/ */
protected boolean hasInstantiationAwareBeanPostProcessors() { 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 * @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor
*/ */
protected boolean hasDestructionAwareBeanPostProcessors() { protected boolean hasDestructionAwareBeanPostProcessors() {
return this.hasDestructionAwareBeanPostProcessors; return !getBeanPostProcessorCache().destructionAware.isEmpty();
} }
@Override @Override
@@ -1031,10 +1065,6 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
this.customEditors.putAll(otherAbstractFactory.customEditors); this.customEditors.putAll(otherAbstractFactory.customEditors);
this.typeConverter = otherAbstractFactory.typeConverter; this.typeConverter = otherAbstractFactory.typeConverter;
this.beanPostProcessors.addAll(otherAbstractFactory.beanPostProcessors); this.beanPostProcessors.addAll(otherAbstractFactory.beanPostProcessors);
this.hasInstantiationAwareBeanPostProcessors = this.hasInstantiationAwareBeanPostProcessors ||
otherAbstractFactory.hasInstantiationAwareBeanPostProcessors;
this.hasDestructionAwareBeanPostProcessors = this.hasDestructionAwareBeanPostProcessors ||
otherAbstractFactory.hasDestructionAwareBeanPostProcessors;
this.scopes.putAll(otherAbstractFactory.scopes); this.scopes.putAll(otherAbstractFactory.scopes);
this.securityContextProvider = otherAbstractFactory.securityContextProvider; this.securityContextProvider = otherAbstractFactory.securityContextProvider;
} }
@@ -1158,7 +1188,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
* @param mbd the merged bean definition * @param mbd the merged bean definition
*/ */
protected void destroyBean(String beanName, Object bean, RootBeanDefinition mbd) { 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 @Override
@@ -1844,9 +1875,9 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
* @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor * @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor
*/ */
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) { protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
return (bean.getClass() != NullBean.class && return (bean.getClass() != NullBean.class && (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) ||
(DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() && (hasDestructionAwareBeanPostProcessors() && DisposableBeanAdapter.hasApplicableProcessors(
DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors())))); bean, getBeanPostProcessorCache().destructionAware))));
} }
/** /**
@@ -1868,8 +1899,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
// Register a DisposableBean implementation that performs all destruction // Register a DisposableBean implementation that performs all destruction
// work for the given bean: DestructionAwareBeanPostProcessors, // work for the given bean: DestructionAwareBeanPostProcessors,
// DisposableBean interface, custom destroy method. // DisposableBean interface, custom destroy method.
registerDisposableBean(beanName, registerDisposableBean(beanName, new DisposableBeanAdapter(
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc)); bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
} }
else { else {
// A bean with a custom scope... // A bean with a custom scope...
@@ -1877,8 +1908,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
if (scope == null) { if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'"); throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
} }
scope.registerDestructionCallback(beanName, scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc)); 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) protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException; 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.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder; 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.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor; import org.springframework.beans.factory.config.DependencyDescriptor;
@@ -1045,10 +1044,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
destroySingleton(beanName); destroySingleton(beanName);
// Notify all post-processors that the specified bean definition has been reset. // Notify all post-processors that the specified bean definition has been reset.
for (BeanPostProcessor processor : getBeanPostProcessors()) { for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
if (processor instanceof MergedBeanDefinitionPostProcessor) { processor.resetBeanDefinition(beanName);
((MergedBeanDefinitionPostProcessor) processor).resetBeanDefinition(beanName);
}
} }
// Reset all bean definitions that have the given bean as parent (recursively). // 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"); * 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.
@@ -32,7 +32,6 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor; import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@@ -87,7 +86,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
private transient Method destroyMethod; private transient Method destroyMethod;
@Nullable @Nullable
private List<DestructionAwareBeanPostProcessor> beanPostProcessors; private final List<DestructionAwareBeanPostProcessor> beanPostProcessors;
/** /**
@@ -99,7 +98,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
* (potentially DestructionAwareBeanPostProcessor), if any * (potentially DestructionAwareBeanPostProcessor), if any
*/ */
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition, 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"); Assert.notNull(bean, "Disposable bean must not be null");
this.bean = bean; this.bean = bean;
@@ -142,7 +141,9 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
* @param postProcessors the List of BeanPostProcessors * @param postProcessors the List of BeanPostProcessors
* (potentially DestructionAwareBeanPostProcessor), if any * (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"); Assert.notNull(bean, "Disposable bean must not be null");
this.bean = bean; this.bean = bean;
this.beanName = bean.getClass().getName(); this.beanName = bean.getClass().getName();
@@ -213,16 +214,15 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
* @return the filtered List of DestructionAwareBeanPostProcessors * @return the filtered List of DestructionAwareBeanPostProcessors
*/ */
@Nullable @Nullable
private List<DestructionAwareBeanPostProcessor> filterPostProcessors(List<BeanPostProcessor> processors, Object bean) { private List<DestructionAwareBeanPostProcessor> filterPostProcessors(
List<DestructionAwareBeanPostProcessor> processors, Object bean) {
List<DestructionAwareBeanPostProcessor> filteredPostProcessors = null; List<DestructionAwareBeanPostProcessor> filteredPostProcessors = null;
if (!CollectionUtils.isEmpty(processors)) { if (!CollectionUtils.isEmpty(processors)) {
filteredPostProcessors = new ArrayList<>(processors.size()); filteredPostProcessors = new ArrayList<>(processors.size());
for (BeanPostProcessor processor : processors) { for (DestructionAwareBeanPostProcessor processor : processors) {
if (processor instanceof DestructionAwareBeanPostProcessor) { if (processor.requiresDestruction(bean)) {
DestructionAwareBeanPostProcessor dabpp = (DestructionAwareBeanPostProcessor) processor; filteredPostProcessors.add(processor);
if (dabpp.requiresDestruction(bean)) {
filteredPostProcessors.add(dabpp);
}
} }
} }
} }
@@ -397,14 +397,11 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
* @param bean the bean instance * @param bean the bean instance
* @param postProcessors the post-processor candidates * @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)) { if (!CollectionUtils.isEmpty(postProcessors)) {
for (BeanPostProcessor processor : postProcessors) { for (DestructionAwareBeanPostProcessor processor : postProcessors) {
if (processor instanceof DestructionAwareBeanPostProcessor) { if (processor.requiresDestruction(bean)) {
DestructionAwareBeanPostProcessor dabpp = (DestructionAwareBeanPostProcessor) processor; return true;
if (dabpp.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.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 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.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory;
@@ -298,8 +299,14 @@ final class PostProcessorRegistrationDelegate {
private static void registerBeanPostProcessors( private static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) { ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
for (BeanPostProcessor postProcessor : postProcessors) { if (beanFactory instanceof AbstractBeanFactory) {
beanFactory.addBeanPostProcessor(postProcessor); // Bulk addition is more efficient against our CopyOnWriteArrayList there
((AbstractBeanFactory) beanFactory).addBeanPostProcessors(postProcessors);
}
else {
for (BeanPostProcessor postProcessor : postProcessors) {
beanFactory.addBeanPostProcessor(postProcessor);
}
} }
} }