From fa06faa3ec081119d56c29f3322829015474e97b Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 18 Sep 2018 23:32:14 +0200 Subject: [PATCH] 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 --- ...bstractBeanFactoryBasedTargetSourceCreator.java | 4 ++-- .../beans/factory/support/AbstractBeanFactory.java | 11 ++++++++--- .../support/ScriptFactoryPostProcessor.java | 14 ++++++++------ 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/target/AbstractBeanFactoryBasedTargetSourceCreator.java b/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/target/AbstractBeanFactoryBasedTargetSourceCreator.java index 3735ba06e7e..083b7aa9ae7 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/target/AbstractBeanFactoryBasedTargetSourceCreator.java +++ b/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"); * 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 it = internalBeanFactory.getBeanPostProcessors().iterator(); it.hasNext();) { if (it.next() instanceof AopInfrastructureBean) { - it.remove(); + it.remove(); // effectively deprecated: use List.removeIf on Java 8+ } } 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 57d7cdb1896..4ddde75736d 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 @@ -145,7 +145,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp private final List embeddedValueResolvers = new CopyOnWriteArrayList(); /** BeanPostProcessors to apply in createBean */ - private final List beanPostProcessors = new CopyOnWriteArrayList(); + private volatile List beanPostProcessors = new ArrayList(); /** 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 beanPostProcessors = new ArrayList(); + 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 diff --git a/spring-context/src/main/java/org/springframework/scripting/support/ScriptFactoryPostProcessor.java b/spring-context/src/main/java/org/springframework/scripting/support/ScriptFactoryPostProcessor.java index 3e572837390..0322398b350 100644 --- a/spring-context/src/main/java/org/springframework/scripting/support/ScriptFactoryPostProcessor.java +++ b/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"); * 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 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 {