From c61aae526568fbf8f4c1a5c139d346e619bce3fa Mon Sep 17 00:00:00 2001 From: lmagyar Date: Thu, 22 Mar 2018 21:09:47 +0100 Subject: [PATCH] FactoryBeanRegistrySupport atomicity issues Issue: SPR-16625 --- .../support/FactoryBeanRegistrySupport.java | 73 ++++++++++--------- 1 file changed, 39 insertions(+), 34 deletions(-) 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 e12080fffdd0..e56b32e34072 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. @@ -96,43 +96,44 @@ protected Object getCachedObjectForFactoryBean(String beanName) { protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) { if (factory.isSingleton() && containsSingleton(beanName)) { synchronized (getSingletonMutex()) { - Object object = this.factoryBeanObjectCache.get(beanName); - if (object == null) { - object = doGetObjectFromFactoryBean(factory, beanName); - // Only post-process and store if not put there already during getObject() call above - // (e.g. because of circular reference processing triggered by custom getBean calls) - Object alreadyThere = this.factoryBeanObjectCache.get(beanName); - if (alreadyThere != null) { - object = alreadyThere; - } - else { - if (shouldPostProcess) { - try { - object = postProcessObjectFromFactoryBean(object, beanName); - } - catch (Throwable ex) { - throw new BeanCreationException(beanName, - "Post-processing of FactoryBean's singleton object failed", ex); + if(containsSingleton(beanName)) { + Object object = this.factoryBeanObjectCache.get(beanName); + if (object == null) { + object = doGetObjectFromFactoryBean(factory, beanName); + // Only post-process and store if not put there already during getObject() call above + // (e.g. because of circular reference processing triggered by custom getBean calls) + Object alreadyThere = this.factoryBeanObjectCache.get(beanName); + if (alreadyThere != null) { + object = alreadyThere; + } + else { + if (shouldPostProcess) { + try { + object = postProcessObjectFromFactoryBean(object, beanName); + } + catch (Throwable ex) { + throw new BeanCreationException(beanName, + "Post-processing of FactoryBean's singleton object failed", ex); + } } + this.factoryBeanObjectCache.put(beanName, object); } - this.factoryBeanObjectCache.put(beanName, object); } + return object; } - return object; } } - else { - Object object = doGetObjectFromFactoryBean(factory, beanName); - if (shouldPostProcess) { - try { - object = postProcessObjectFromFactoryBean(object, beanName); - } - catch (Throwable ex) { - throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex); - } + + Object object = doGetObjectFromFactoryBean(factory, beanName); + if (shouldPostProcess) { + try { + object = postProcessObjectFromFactoryBean(object, beanName); + } + catch (Throwable ex) { + throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex); } - return object; } + return object; } /** @@ -214,8 +215,10 @@ protected FactoryBean getFactoryBean(String beanName, Object beanInstance) th */ @Override protected void removeSingleton(String beanName) { - super.removeSingleton(beanName); - this.factoryBeanObjectCache.remove(beanName); + synchronized (getSingletonMutex()) { + super.removeSingleton(beanName); + this.factoryBeanObjectCache.remove(beanName); + } } /** @@ -223,8 +226,10 @@ protected void removeSingleton(String beanName) { */ @Override public void destroySingletons() { - super.destroySingletons(); - this.factoryBeanObjectCache.clear(); + synchronized (getSingletonMutex()) { + super.destroySingletons(); + this.factoryBeanObjectCache.clear(); + } } /**