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 b8431437fa3..8b0f4c68cb0 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 @@ -134,7 +134,17 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg boolean smart = (factory instanceof SmartFactoryBean); Object object = (!smart ? this.factoryBeanObjectCache.get(beanName) : null); if (object == null) { - object = doGetObjectFromFactoryBean(factory, requiredType, beanName); + if (locked) { + // The common case: within general singleton lock. + object = doGetObjectFromFactoryBean(factory, requiredType, beanName); + } + else { + // Fall back to local synchronization on the given FactoryBean instance, + // as a defensive measure for non-thread-safe FactoryBean implementations. + synchronized (factory) { + object = doGetObjectFromFactoryBean(factory, requiredType, beanName); + } + } // Only post-process and store if not put there already during getObject() call above // (for example, because of circular reference processing triggered by custom getBean calls) Object alreadyThere = (!smart ? this.factoryBeanObjectCache.get(beanName) : null); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/JdbcTransactionObjectSupport.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/JdbcTransactionObjectSupport.java index b80cb1414e5..e7330deeaf5 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/JdbcTransactionObjectSupport.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/JdbcTransactionObjectSupport.java @@ -182,6 +182,10 @@ public abstract class JdbcTransactionObjectSupport implements SavepointManager, // typically on Oracle - ignore } catch (SQLException ex) { + if ("3B001".equals(ex.getSQLState())) { + // Savepoint already released (HSQLDB, PostgreSQL, DB2) - ignore + return; + } // ignore Microsoft SQLServerException: This operation is not supported. String msg = ex.getMessage(); if (msg == null || !msg.contains("not supported")) {