FlexyPool如何同时支持连接代理和装饰器
代理人
FlexyPool監視連接池使用情況,因此需要攔截連接關閉方法調用。
為了簡單起見,第一個版本為此目的依賴動態代理:
代理調用的速度可能比裝飾器慢,裝飾器使用直接調用來調用目標方法。
由于所有連接池仍然使用代理,因此添加另一個代理層只會增加更多的呼叫時間開銷,因此現在FlexyPool也支持連接裝飾器。
裝飾工
ConnectionDecorator包裝基礎數據庫連接,將所有調用委派給實際的對象實例。 就像它的代理服務器代理一樣,只有close方法可以執行任何額外的邏輯:
public class ConnectionDecorator implements Connection {private final Connection target;private final ConnectionCallback callback;public ConnectionDecorator(Connection target, ConnectionCallback callback) {this.target = target;this.callback = callback;}public Connection getTarget() {return target;}public ConnectionCallback getCallback() {return callback;}@Overridepublic Statement createStatement() throws SQLException {return target.createStatement();}@Overridepublic void close() throws SQLException {callback.close();target.close();}/*** More methods omitted for brevity sake*/public void setSchema(String schema) throws SQLException {ReflectionUtils.invoke(target,ReflectionUtils.getMethod(target, "setSchema", String.class),schema);}public String getSchema() throws SQLException {return ReflectionUtils.invoke(target,ReflectionUtils.getMethod(target, "getSchema"));}public void abort(Executor executor) throws SQLException {ReflectionUtils.invoke(target,ReflectionUtils.getMethod(target, "abort", Executor.class),executor);}public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {ReflectionUtils.invoke(target,ReflectionUtils.getMethod(target, "setNetworkTimeout", Executor.class, int.class),executor, milliseconds);}public int getNetworkTimeout() throws SQLException {return (Integer) ReflectionUtils.invoke(target,ReflectionUtils.getMethod(target, "getNetworkTimeout"));} }您可能已經注意到,某些方法使用Java Reflection而不是直接方法調用:
- abort()
- getSchema()
- setSchema()
- getNetworkTimeout()
- setNetworkTimeout()
這些方法已添加到Java 1.7中,使用Java 1.6編譯項目時,直接調用將失敗。 因為Java 1.6是大多數FlexyPool模塊的最低要求,所以這些方法通過Java反射調用轉發傳入的方法調用。 省略這些方法不是可選的,因為在1.7 JVM上, Connection裝飾器將沒有這些方法,并且將引發類裝入錯誤。
在至少使用Java 1.7的項目中,FlexyPool還提供了Java7ConnectionDecorator :
public class Java7ConnectionDecorator extends ConnectionDecorator {public Java7ConnectionDecorator(Connection target, ConnectionCallback callback) {super(target, callback);}@Overridepublic void setSchema(String schema) throws SQLException {getTarget().setSchema(schema);}@Overridepublic String getSchema() throws SQLException {return getTarget().getSchema();}@Overridepublic void abort(Executor executor) throws SQLException {getTarget().abort(executor);}@Overridepublic void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {getTarget().setNetworkTimeout(executor, milliseconds);}@Overridepublic int getNetworkTimeout() throws SQLException {return getTarget().getNetworkTimeout();} }此類不是核心庫的一部分,包含在單獨的Java 1.7兼容模塊中。 要使用它,您需要添加以下Maven依賴項:
<dependency><groupId>com.vladmihalcea.flexy-pool</groupId><artifactId>flexy-pool-core-java7</artifactId><version>${flexy-pool.version}</version> </dependency>服務發現機制
從一開始,FlexyPool就為配置ConnectionProxyFactory實例提供了支持,因此切換到裝飾器不需要任何繁瑣的代碼重構。
在1.2.4發行版之前,默認的連接提供程序是JdkConnectionProxyFactory ,它使用動態代理。
從1.2.4開始,FlexyPool使用連接裝飾器作為默認的連接攔截機制。
實際的裝飾器版本在運行時解析,并且加載機制由以下組件構成:
實際的連接裝飾器工廠通過以下方法解決:
public ConnectionDecoratorFactory resolve() {int loadingIndex = Integer.MIN_VALUE;ConnectionDecoratorFactory connectionDecoratorFactory = null;Iterator<ConnectionDecoratorFactoryService> connectionDecoratorFactoryServiceIterator = serviceLoader.iterator();while (connectionDecoratorFactoryServiceIterator.hasNext()) {try {ConnectionDecoratorFactoryService connectionDecoratorFactoryService = connectionDecoratorFactoryServiceIterator.next();int currentLoadingIndex = connectionDecoratorFactoryService.loadingIndex();if (currentLoadingIndex > loadingIndex) {ConnectionDecoratorFactory currentConnectionDecoratorFactory = connectionDecoratorFactoryService.load();if (currentConnectionDecoratorFactory != null) {connectionDecoratorFactory = currentConnectionDecoratorFactory;loadingIndex = currentLoadingIndex;}}} catch (LinkageError e) {LOGGER.info("Couldn't load ConnectionDecoratorFactoryService on the current JVM", e);}}if (connectionDecoratorFactory != null) {return connectionDecoratorFactory;}throw new IllegalStateException("No ConnectionDecoratorFactory could be loaded!"); }就像MetricsFactory一樣 ,每個連接裝飾器工廠都有一個關聯的服務提供者 。 可以在運行時加載多個此類服務提供程序(默認的Java 1.6連接修飾器服務或Java 1.7之一)。 根據索引(最新的Java版本優先)和當前的JVM JDBC版本支持(在Java 1.6運行時環境中無法解析Java 1.7連接裝飾器)進行選擇。
結論
裝飾器比代理器承擔更多的配置開銷,但是如果您想減少最后的性能下降,則值得考慮直接方法調用的優勢。
翻譯自: https://www.javacodegeeks.com/2015/08/how-does-flexypool-support-both-connection-proxies-and-decorators.html
總結
以上是生活随笔為你收集整理的FlexyPool如何同时支持连接代理和装饰器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 步履瞒珊什么意思 步履瞒珊的意思
- 下一篇: 直播间的翡翠为啥便宜 直播间的翡翠便宜原