Avoid internal lifecycle synchronization in favor of lifecycle lock
Closes gh-32284
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 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.
|
||||
@@ -22,6 +22,8 @@ import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -73,8 +75,8 @@ public class SingleConnectionDataSource extends DriverManagerDataSource
|
||||
@Nullable
|
||||
private Connection connection;
|
||||
|
||||
/** Synchronization monitor for the shared Connection. */
|
||||
private final Object connectionMonitor = new Object();
|
||||
/** Lifecycle lock for the shared Connection. */
|
||||
private final Lock connectionLock = new ReentrantLock();
|
||||
|
||||
|
||||
/**
|
||||
@@ -181,7 +183,8 @@ public class SingleConnectionDataSource extends DriverManagerDataSource
|
||||
|
||||
@Override
|
||||
public Connection getConnection() throws SQLException {
|
||||
synchronized (this.connectionMonitor) {
|
||||
this.connectionLock.lock();
|
||||
try {
|
||||
if (this.connection == null) {
|
||||
// No underlying Connection -> lazy init via DriverManager.
|
||||
initConnection();
|
||||
@@ -193,6 +196,9 @@ public class SingleConnectionDataSource extends DriverManagerDataSource
|
||||
}
|
||||
return this.connection;
|
||||
}
|
||||
finally {
|
||||
this.connectionLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -216,9 +222,13 @@ public class SingleConnectionDataSource extends DriverManagerDataSource
|
||||
*/
|
||||
@Override
|
||||
public boolean shouldClose(Connection con) {
|
||||
synchronized (this.connectionMonitor) {
|
||||
this.connectionLock.lock();
|
||||
try {
|
||||
return (con != this.connection && con != this.target);
|
||||
}
|
||||
finally {
|
||||
this.connectionLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,11 +251,15 @@ public class SingleConnectionDataSource extends DriverManagerDataSource
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
synchronized (this.connectionMonitor) {
|
||||
this.connectionLock.lock();
|
||||
try {
|
||||
if (this.target != null) {
|
||||
closeConnection(this.target);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.connectionLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -256,7 +270,8 @@ public class SingleConnectionDataSource extends DriverManagerDataSource
|
||||
if (getUrl() == null) {
|
||||
throw new IllegalStateException("'url' property is required for lazily initializing a Connection");
|
||||
}
|
||||
synchronized (this.connectionMonitor) {
|
||||
this.connectionLock.lock();
|
||||
try {
|
||||
if (this.target != null) {
|
||||
closeConnection(this.target);
|
||||
}
|
||||
@@ -267,19 +282,26 @@ public class SingleConnectionDataSource extends DriverManagerDataSource
|
||||
}
|
||||
this.connection = (isSuppressClose() ? getCloseSuppressingConnectionProxy(this.target) : this.target);
|
||||
}
|
||||
finally {
|
||||
this.connectionLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the underlying shared Connection, to be reinitialized on next access.
|
||||
*/
|
||||
public void resetConnection() {
|
||||
synchronized (this.connectionMonitor) {
|
||||
this.connectionLock.lock();
|
||||
try {
|
||||
if (this.target != null) {
|
||||
closeConnection(this.target);
|
||||
}
|
||||
this.target = null;
|
||||
this.connection = null;
|
||||
}
|
||||
finally {
|
||||
this.connectionLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user