Browse Source

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
pull/1984/merge
Juergen Hoeller 8 years ago
parent
commit
fa06faa3ec
  1. 4
      spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/target/AbstractBeanFactoryBasedTargetSourceCreator.java
  2. 11
      spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java
  3. 14
      spring-context/src/main/java/org/springframework/scripting/support/ScriptFactoryPostProcessor.java

4
spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/target/AbstractBeanFactoryBasedTargetSourceCreator.java

@ -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"); * 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.
@ -150,7 +150,7 @@ public abstract class AbstractBeanFactoryBasedTargetSourceCreator
// since those are only meant to apply to beans defined in the original factory. // since those are only meant to apply to beans defined in the original factory.
for (Iterator<BeanPostProcessor> it = internalBeanFactory.getBeanPostProcessors().iterator(); it.hasNext();) { for (Iterator<BeanPostProcessor> it = internalBeanFactory.getBeanPostProcessors().iterator(); it.hasNext();) {
if (it.next() instanceof AopInfrastructureBean) { if (it.next() instanceof AopInfrastructureBean) {
it.remove(); it.remove(); // effectively deprecated: use List.removeIf on Java 8+
} }
} }

11
spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java

@ -145,7 +145,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
private final List<StringValueResolver> embeddedValueResolvers = new CopyOnWriteArrayList<StringValueResolver>(); private final List<StringValueResolver> embeddedValueResolvers = new CopyOnWriteArrayList<StringValueResolver>();
/** BeanPostProcessors to apply in createBean */ /** 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 */ /** Indicates whether any InstantiationAwareBeanPostProcessors have been registered */
private volatile boolean hasInstantiationAwareBeanPostProcessors; private volatile boolean hasInstantiationAwareBeanPostProcessors;
@ -845,8 +845,12 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
@Override @Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) { public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null"); 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 // Remove from old position, if any
this.beanPostProcessors.remove(beanPostProcessor); beanPostProcessors.remove(beanPostProcessor);
// Track whether it is instantiation/destruction aware // Track whether it is instantiation/destruction aware
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) { if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true; this.hasInstantiationAwareBeanPostProcessors = true;
@ -855,7 +859,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
this.hasDestructionAwareBeanPostProcessors = true; this.hasDestructionAwareBeanPostProcessors = true;
} }
// Add to end of list // Add to end of list
this.beanPostProcessors.add(beanPostProcessor); beanPostProcessors.add(beanPostProcessor);
this.beanPostProcessors = beanPostProcessors;
} }
@Override @Override

14
spring-context/src/main/java/org/springframework/scripting/support/ScriptFactoryPostProcessor.java

@ -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"); * 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.
@ -136,8 +136,8 @@ import org.springframework.util.StringUtils;
* @author Mark Fisher * @author Mark Fisher
* @since 2.0 * @since 2.0
*/ */
public class ScriptFactoryPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements public class ScriptFactoryPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
BeanClassLoaderAware, BeanFactoryAware, ResourceLoaderAware, DisposableBean, Ordered { implements BeanClassLoaderAware, BeanFactoryAware, ResourceLoaderAware, DisposableBean, Ordered {
/** /**
* The {@link org.springframework.core.io.Resource}-style prefix that denotes * 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."; private static final String SCRIPTED_OBJECT_NAME_PREFIX = "scriptedObject.";
/** Logger available to subclasses */ /** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass()); 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. // since those are only meant to apply to beans defined in the original factory.
for (Iterator<BeanPostProcessor> it = this.scriptBeanFactory.getBeanPostProcessors().iterator(); it.hasNext();) { for (Iterator<BeanPostProcessor> it = this.scriptBeanFactory.getBeanPostProcessors().iterator(); it.hasNext();) {
if (it.next() instanceof AopInfrastructureBean) { 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; return Integer.MIN_VALUE;
} }
@Override @Override
public Class<?> predictBeanType(Class<?> beanClass, String beanName) { public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
// We only apply special treatment to ScriptFactory implementations here. // We only apply special treatment to ScriptFactory implementations here.
@ -274,8 +276,8 @@ public class ScriptFactoryPostProcessor extends InstantiationAwareBeanPostProces
if (ex instanceof BeanCreationException && if (ex instanceof BeanCreationException &&
((BeanCreationException) ex).getMostSpecificCause() instanceof BeanCurrentlyInCreationException) { ((BeanCreationException) ex).getMostSpecificCause() instanceof BeanCurrentlyInCreationException) {
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Could not determine scripted object type for bean '" + beanName + "': " logger.trace("Could not determine scripted object type for bean '" + beanName + "': " +
+ ex.getMessage()); ex.getMessage());
} }
} }
else { else {

Loading…
Cancel
Save