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:
Juergen Hoeller
2018-09-18 23:32:14 +02:00
parent e94624d439
commit fa06faa3ec
3 changed files with 18 additions and 11 deletions

View File

@@ -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+
}
}

View File

@@ -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

View File

@@ -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 {