Use local copy set into volatile field instead of CopyOnWriteArrayList
Keep supporting legacy usage of Iterator.remove on getBeanPostProcessors result List in AbstractBeanFactoryBasedTargetSourceCreator and ScriptFactoryPostProcessor (and similarly designed integrations). Issue: SPR-17286
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -150,7 +150,7 @@ public abstract class AbstractBeanFactoryBasedTargetSourceCreator
|
||||
// since those are only meant to apply to beans defined in the original factory.
|
||||
for (Iterator<BeanPostProcessor> it = internalBeanFactory.getBeanPostProcessors().iterator(); it.hasNext();) {
|
||||
if (it.next() instanceof AopInfrastructureBean) {
|
||||
it.remove();
|
||||
it.remove(); // effectively deprecated: use List.removeIf on Java 8+
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
private final List<StringValueResolver> embeddedValueResolvers = new CopyOnWriteArrayList<StringValueResolver>();
|
||||
|
||||
/** BeanPostProcessors to apply in createBean */
|
||||
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<BeanPostProcessor>();
|
||||
private volatile List<BeanPostProcessor> beanPostProcessors = new ArrayList<BeanPostProcessor>();
|
||||
|
||||
/** Indicates whether any InstantiationAwareBeanPostProcessors have been registered */
|
||||
private volatile boolean hasInstantiationAwareBeanPostProcessors;
|
||||
@@ -845,8 +845,12 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
@Override
|
||||
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
|
||||
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
|
||||
// Local copy set into volatile field, as an alternative to CopyOnWriteArrayList
|
||||
// (which doesn't support Iterator.remove for our getBeanPostProcessors result List)
|
||||
List<BeanPostProcessor> beanPostProcessors = new ArrayList<BeanPostProcessor>();
|
||||
beanPostProcessors.addAll(this.beanPostProcessors);
|
||||
// Remove from old position, if any
|
||||
this.beanPostProcessors.remove(beanPostProcessor);
|
||||
beanPostProcessors.remove(beanPostProcessor);
|
||||
// Track whether it is instantiation/destruction aware
|
||||
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
|
||||
this.hasInstantiationAwareBeanPostProcessors = true;
|
||||
@@ -855,7 +859,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
this.hasDestructionAwareBeanPostProcessors = true;
|
||||
}
|
||||
// Add to end of list
|
||||
this.beanPostProcessors.add(beanPostProcessor);
|
||||
beanPostProcessors.add(beanPostProcessor);
|
||||
this.beanPostProcessors = beanPostProcessors;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -136,8 +136,8 @@ import org.springframework.util.StringUtils;
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ScriptFactoryPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements
|
||||
BeanClassLoaderAware, BeanFactoryAware, ResourceLoaderAware, DisposableBean, Ordered {
|
||||
public class ScriptFactoryPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
|
||||
implements BeanClassLoaderAware, BeanFactoryAware, ResourceLoaderAware, DisposableBean, Ordered {
|
||||
|
||||
/**
|
||||
* The {@link org.springframework.core.io.Resource}-style prefix that denotes
|
||||
@@ -160,6 +160,7 @@ public class ScriptFactoryPostProcessor extends InstantiationAwareBeanPostProces
|
||||
|
||||
private static final String SCRIPTED_OBJECT_NAME_PREFIX = "scriptedObject.";
|
||||
|
||||
|
||||
/** Logger available to subclasses */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
@@ -221,7 +222,7 @@ public class ScriptFactoryPostProcessor extends InstantiationAwareBeanPostProces
|
||||
// since those are only meant to apply to beans defined in the original factory.
|
||||
for (Iterator<BeanPostProcessor> it = this.scriptBeanFactory.getBeanPostProcessors().iterator(); it.hasNext();) {
|
||||
if (it.next() instanceof AopInfrastructureBean) {
|
||||
it.remove();
|
||||
it.remove(); // effectively deprecated: use List.removeIf on Java 8+
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -236,6 +237,7 @@ public class ScriptFactoryPostProcessor extends InstantiationAwareBeanPostProces
|
||||
return Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
|
||||
// We only apply special treatment to ScriptFactory implementations here.
|
||||
@@ -274,8 +276,8 @@ public class ScriptFactoryPostProcessor extends InstantiationAwareBeanPostProces
|
||||
if (ex instanceof BeanCreationException &&
|
||||
((BeanCreationException) ex).getMostSpecificCause() instanceof BeanCurrentlyInCreationException) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Could not determine scripted object type for bean '" + beanName + "': "
|
||||
+ ex.getMessage());
|
||||
logger.trace("Could not determine scripted object type for bean '" + beanName + "': " +
|
||||
ex.getMessage());
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
Reference in New Issue
Block a user