diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index 3c8eeacf2c1..00adea84c9c 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.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. @@ -908,12 +908,16 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac if (bw != null) { return (FactoryBean) bw.getWrappedInstance(); } + Object beanInstance = getSingleton(beanName, false); + if (beanInstance instanceof FactoryBean) { + return (FactoryBean) beanInstance; + } if (isSingletonCurrentlyInCreation(beanName) || (mbd.getFactoryBeanName() != null && isSingletonCurrentlyInCreation(mbd.getFactoryBeanName()))) { return null; } - Object instance = null; + Object instance; try { // Mark this bean as currently in creation, even if just partially. beforeSingletonCreation(beanName); @@ -1484,15 +1488,13 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac return; } + if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) { + ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext()); + } + MutablePropertyValues mpvs = null; List original; - if (System.getSecurityManager() != null) { - if (bw instanceof BeanWrapperImpl) { - ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext()); - } - } - if (pvs instanceof MutablePropertyValues) { mpvs = (MutablePropertyValues) pvs; if (mpvs.isConverted()) { @@ -1628,7 +1630,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } - if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } @@ -1780,8 +1781,21 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac */ @Override protected void removeSingleton(String beanName) { - super.removeSingleton(beanName); - this.factoryBeanInstanceCache.remove(beanName); + synchronized (getSingletonMutex()) { + super.removeSingleton(beanName); + this.factoryBeanInstanceCache.remove(beanName); + } + } + + /** + * Overridden to clear FactoryBean instance cache as well. + */ + @Override + protected void clearSingletonCache() { + synchronized (getSingletonMutex()) { + super.clearSingletonCache(); + this.factoryBeanInstanceCache.clear(); + } } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java index 59528785528..c40dc7bac41 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java @@ -386,15 +386,8 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements * @see #registerDependentBean */ public void registerContainedBean(String containedBeanName, String containingBeanName) { - // A quick check for an existing entry upfront, avoiding synchronization... - Set containedBeans = this.containedBeanMap.get(containingBeanName); - if (containedBeans != null && containedBeans.contains(containedBeanName)) { - return; - } - - // No entry yet -> fully synchronized manipulation of the containedBeans Set synchronized (this.containedBeanMap) { - containedBeans = this.containedBeanMap.get(containingBeanName); + Set containedBeans = this.containedBeanMap.get(containingBeanName); if (containedBeans == null) { containedBeans = new LinkedHashSet(8); this.containedBeanMap.put(containingBeanName, containedBeans); @@ -411,16 +404,10 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements * @param dependentBeanName the name of the dependent bean */ public void registerDependentBean(String beanName, String dependentBeanName) { - // A quick check for an existing entry upfront, avoiding synchronization... String canonicalName = canonicalName(beanName); - Set dependentBeans = this.dependentBeanMap.get(canonicalName); - if (dependentBeans != null && dependentBeans.contains(dependentBeanName)) { - return; - } - // No entry yet -> fully synchronized manipulation of the dependentBeans Set synchronized (this.dependentBeanMap) { - dependentBeans = this.dependentBeanMap.get(canonicalName); + Set dependentBeans = this.dependentBeanMap.get(canonicalName); if (dependentBeans == null) { dependentBeans = new LinkedHashSet(8); this.dependentBeanMap.put(canonicalName, dependentBeans); @@ -445,7 +432,9 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements * @since 4.0 */ protected boolean isDependent(String beanName, String dependentBeanName) { - return isDependent(beanName, dependentBeanName, null); + synchronized (this.dependentBeanMap) { + return isDependent(beanName, dependentBeanName, null); + } } private boolean isDependent(String beanName, String dependentBeanName, Set alreadySeen) { @@ -490,7 +479,9 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements if (dependentBeans == null) { return new String[0]; } - return StringUtils.toStringArray(dependentBeans); + synchronized (this.dependentBeanMap) { + return StringUtils.toStringArray(dependentBeans); + } } /** @@ -504,7 +495,9 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements if (dependenciesForBean == null) { return new String[0]; } - return StringUtils.toStringArray(dependenciesForBean); + synchronized (this.dependenciesForBeanMap) { + return StringUtils.toStringArray(dependenciesForBean); + } } public void destroySingletons() { @@ -527,6 +520,14 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements this.dependentBeanMap.clear(); this.dependenciesForBeanMap.clear(); + clearSingletonCache(); + } + + /** + * Clear all cached singleton instances in this registry. + * @since 4.3.15 + */ + protected void clearSingletonCache() { synchronized (this.singletonObjects) { this.singletonObjects.clear(); this.singletonFactories.clear(); @@ -562,7 +563,11 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements */ protected void destroyBean(String beanName, DisposableBean bean) { // Trigger destruction of dependent beans first... - Set dependencies = this.dependentBeanMap.remove(beanName); + Set dependencies; + synchronized (this.dependentBeanMap) { + // Within full synchronization in order to guarantee a disconnected Set + dependencies = this.dependentBeanMap.remove(beanName); + } if (dependencies != null) { if (logger.isDebugEnabled()) { logger.debug("Retrieved dependent beans for bean '" + beanName + "': " + dependencies); @@ -583,7 +588,11 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements } // Trigger destruction of contained beans... - Set containedBeans = this.containedBeanMap.remove(beanName); + Set containedBeans; + synchronized (this.containedBeanMap) { + // Within full synchronization in order to guarantee a disconnected Set + containedBeans = this.containedBeanMap.remove(beanName); + } if (containedBeans != null) { for (String containedBeanName : containedBeans) { destroySingleton(containedBeanName); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/FactoryBeanRegistrySupport.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/FactoryBeanRegistrySupport.java index 1170486beef..b2177c70511 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/FactoryBeanRegistrySupport.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/FactoryBeanRegistrySupport.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. @@ -117,7 +117,9 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg "Post-processing of FactoryBean's singleton object failed", ex); } } - this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT)); + if (containsSingleton(beanName)) { + this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT)); + } } } return (object != NULL_OBJECT ? object : null); @@ -218,17 +220,21 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg */ @Override protected void removeSingleton(String beanName) { - super.removeSingleton(beanName); - this.factoryBeanObjectCache.remove(beanName); + synchronized (getSingletonMutex()) { + super.removeSingleton(beanName); + this.factoryBeanObjectCache.remove(beanName); + } } /** * Overridden to clear the FactoryBean object cache as well. */ @Override - public void destroySingletons() { - super.destroySingletons(); - this.factoryBeanObjectCache.clear(); + protected void clearSingletonCache() { + synchronized (getSingletonMutex()) { + super.clearSingletonCache(); + this.factoryBeanObjectCache.clear(); + } } /** diff --git a/spring-context/src/main/java/org/springframework/context/support/DefaultLifecycleProcessor.java b/spring-context/src/main/java/org/springframework/context/support/DefaultLifecycleProcessor.java index 0b7761a8506..99e130a75c9 100644 --- a/spring-context/src/main/java/org/springframework/context/support/DefaultLifecycleProcessor.java +++ b/spring-context/src/main/java/org/springframework/context/support/DefaultLifecycleProcessor.java @@ -159,7 +159,7 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor */ private void doStart(Map lifecycleBeans, String beanName, boolean autoStartupOnly) { Lifecycle bean = lifecycleBeans.remove(beanName); - if (bean != null && !this.equals(bean)) { + if (bean != null && bean != this) { String[] dependenciesForBean = this.beanFactory.getDependenciesForBean(beanName); for (String dependency : dependenciesForBean) { doStart(lifecycleBeans, dependency, autoStartupOnly);