From fb492cd45257bde7299c23fbb1ec9315281977b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=81=A5=E5=85=A8?= Date: Wed, 18 Mar 2026 18:17:42 +0800 Subject: [PATCH 1/2] =?UTF-8?q?perf:=20=E8=A7=A3=E5=86=B3druid=E6=97=B6?= =?UTF-8?q?=E9=A9=B1=E5=8A=A8=E4=B8=BA=E7=A9=BA=E7=9A=84=E6=83=85=E5=86=B5?= =?UTF-8?q?=20=E5=B9=B6=E4=BC=98=E5=8C=96=E7=9B=B8=E5=85=B3=E9=A9=B1?= =?UTF-8?q?=E5=8A=A8=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jdbc/AuthorizationJdbcDriver.java | 101 ++++++++++++++++-- 1 file changed, 90 insertions(+), 11 deletions(-) diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/AuthorizationJdbcDriver.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/AuthorizationJdbcDriver.java index 93045795..d7c5acb0 100644 --- a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/AuthorizationJdbcDriver.java +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/AuthorizationJdbcDriver.java @@ -6,52 +6,131 @@ import java.sql.*; import java.util.Enumeration; import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Logger; public class AuthorizationJdbcDriver implements Driver { - private Driver driver; + /** + * Cache driver by URL to avoid repeated traversal. + * Thread-safe since multiple connections may be created concurrently. + */ + private final ConcurrentHashMap driverCache = new ConcurrentHashMap<>(); + + /** + * Cached reference to any non-self driver (for methods without URL). + */ + private volatile Driver anyDriverCache; @Override public Connection connect(String url, Properties info) throws SQLException { - return new ConnectionProxy(driver.connect(url, info)); + Driver targetDriver = getTargetDriver(url); + if (targetDriver == null) { + return null; + } + return new ConnectionProxy(targetDriver.connect(url, info)); } @Override public boolean acceptsURL(String url) throws SQLException { + return getTargetDriver(url) != null; + } + + /** + * Get target driver for the given URL. + * Uses cached result if available, otherwise finds and caches. + */ + private Driver getTargetDriver(String url) throws SQLException { + // Fast path: check cache first + Driver cached = driverCache.get(url); + if (cached != null) { + return cached; + } + + // Cache miss: find and cache + Driver found = findDriver(url); + if (found != null) { + driverCache.putIfAbsent(url, found); + } + return found; + } + + /** + * Find the target driver that accepts the URL from DriverManager. + */ + private Driver findDriver(String url) throws SQLException { Enumeration drivers = DriverManager.getDrivers(); while (drivers.hasMoreElements()) { Driver driver = drivers.nextElement(); - if (driver.acceptsURL(url)) { - this.driver = driver; - return true; + if (driver != this && driver.acceptsURL(url)) { + return driver; } } - return false; + return null; } @Override public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { - return driver.getPropertyInfo(url, info); + Driver driver = getTargetDriver(url); + if (driver != null) { + return driver.getPropertyInfo(url, info); + } + return new DriverPropertyInfo[0]; } @Override public int getMajorVersion() { - return driver.getMajorVersion(); + return getAnyDriver().getMajorVersion(); } @Override public int getMinorVersion() { - return driver.getMinorVersion(); + return getAnyDriver().getMinorVersion(); } @Override public boolean jdbcCompliant() { - return driver.jdbcCompliant(); + Driver driver = getAnyDriver(); + return driver != null && driver.jdbcCompliant(); } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { - return driver.getParentLogger(); + return getAnyDriver().getParentLogger(); + } + + /** + * Get any registered driver other than this one. + * Caches the first found result since driver set doesn't change at runtime. + */ + private Driver getAnyDriver() { + // Double-checked locking for lazy initialization + Driver cached = anyDriverCache; + if (cached != null) { + return cached; + } + synchronized (this) { + cached = anyDriverCache; + if (cached != null) { + return cached; + } + anyDriverCache = findAnyDriver(); + return anyDriverCache; + } + } + + /** + * Find any registered driver other than this one. + * Used for methods that don't have URL available. + */ + private Driver findAnyDriver() { + Enumeration drivers = DriverManager.getDrivers(); + while (drivers.hasMoreElements()) { + Driver driver = drivers.nextElement(); + if (driver != this) { + return driver; + } + } + throw new IllegalStateException("No JDBC driver found"); } } From aa34d2484c0d9cdd8c81df63d1098c3da0f63204 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=81=A5=E5=85=A8?= Date: Wed, 18 Mar 2026 18:17:42 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix=EF=BC=9A=E4=BD=BF=E7=94=A8druid=20?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E6=B1=A0=E6=97=B6=EF=BC=8CDriver=20=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E7=A9=BA=E6=8C=87=E9=92=88=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20=20#185?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jdbc/AuthorizationJdbcDriver.java | 101 ++++++++++++++++-- 1 file changed, 90 insertions(+), 11 deletions(-) diff --git a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/AuthorizationJdbcDriver.java b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/AuthorizationJdbcDriver.java index 93045795..d7c5acb0 100644 --- a/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/AuthorizationJdbcDriver.java +++ b/springboot-starter-data-authorization/src/main/java/com/codingapi/springboot/authorization/jdbc/AuthorizationJdbcDriver.java @@ -6,52 +6,131 @@ import java.sql.*; import java.util.Enumeration; import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Logger; public class AuthorizationJdbcDriver implements Driver { - private Driver driver; + /** + * Cache driver by URL to avoid repeated traversal. + * Thread-safe since multiple connections may be created concurrently. + */ + private final ConcurrentHashMap driverCache = new ConcurrentHashMap<>(); + + /** + * Cached reference to any non-self driver (for methods without URL). + */ + private volatile Driver anyDriverCache; @Override public Connection connect(String url, Properties info) throws SQLException { - return new ConnectionProxy(driver.connect(url, info)); + Driver targetDriver = getTargetDriver(url); + if (targetDriver == null) { + return null; + } + return new ConnectionProxy(targetDriver.connect(url, info)); } @Override public boolean acceptsURL(String url) throws SQLException { + return getTargetDriver(url) != null; + } + + /** + * Get target driver for the given URL. + * Uses cached result if available, otherwise finds and caches. + */ + private Driver getTargetDriver(String url) throws SQLException { + // Fast path: check cache first + Driver cached = driverCache.get(url); + if (cached != null) { + return cached; + } + + // Cache miss: find and cache + Driver found = findDriver(url); + if (found != null) { + driverCache.putIfAbsent(url, found); + } + return found; + } + + /** + * Find the target driver that accepts the URL from DriverManager. + */ + private Driver findDriver(String url) throws SQLException { Enumeration drivers = DriverManager.getDrivers(); while (drivers.hasMoreElements()) { Driver driver = drivers.nextElement(); - if (driver.acceptsURL(url)) { - this.driver = driver; - return true; + if (driver != this && driver.acceptsURL(url)) { + return driver; } } - return false; + return null; } @Override public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { - return driver.getPropertyInfo(url, info); + Driver driver = getTargetDriver(url); + if (driver != null) { + return driver.getPropertyInfo(url, info); + } + return new DriverPropertyInfo[0]; } @Override public int getMajorVersion() { - return driver.getMajorVersion(); + return getAnyDriver().getMajorVersion(); } @Override public int getMinorVersion() { - return driver.getMinorVersion(); + return getAnyDriver().getMinorVersion(); } @Override public boolean jdbcCompliant() { - return driver.jdbcCompliant(); + Driver driver = getAnyDriver(); + return driver != null && driver.jdbcCompliant(); } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { - return driver.getParentLogger(); + return getAnyDriver().getParentLogger(); + } + + /** + * Get any registered driver other than this one. + * Caches the first found result since driver set doesn't change at runtime. + */ + private Driver getAnyDriver() { + // Double-checked locking for lazy initialization + Driver cached = anyDriverCache; + if (cached != null) { + return cached; + } + synchronized (this) { + cached = anyDriverCache; + if (cached != null) { + return cached; + } + anyDriverCache = findAnyDriver(); + return anyDriverCache; + } + } + + /** + * Find any registered driver other than this one. + * Used for methods that don't have URL available. + */ + private Driver findAnyDriver() { + Enumeration drivers = DriverManager.getDrivers(); + while (drivers.hasMoreElements()) { + Driver driver = drivers.nextElement(); + if (driver != this) { + return driver; + } + } + throw new IllegalStateException("No JDBC driver found"); } }