2017-02-02 4 views
0

Tomcat JDBCプールからの借用した接続ごとに、いくつかの初期化ステートメントを実行する必要があります。プールはinitilizationを必要としない他のアプリケーションと共有されるため、JDBCInterceptorsを使用することはできません。ClassCastExceptionでAspectが失敗し、Tomcat DataSourceをポイントカットしようとしました。getConnection

私は、Oracle 11gデータベースに対してDataSourceを定義するserver.xmlのリソースにcontext.xmlのResourceLinkを持つTomcat 8.5.11に展開するSpring Boot 1.4.4を使用しています。私はJNDI経由でDataSourceにアクセスしています。

この回答によるとhttps://stackoverflow.com/a/38746398私は目標を達成するためにSpring AOPを使いたいと思っていました。

私が作成しているとDataSourceはcontext.xmlに直接定義されている場合は完璧に動作しますが、server.xmlで同じ定義にリソースリンクを介して参照場合にClassCastExceptionで失敗アスペクトは、例外が

です

java.lang.ClassCastException: org.apache.tomcat.jdbc.pool.DataSource cannot be cast to org.apache.tomcat.jdbc.pool.DataSourceProxy 
at org.apache.tomcat.jdbc.pool.DataSourceProxy$$FastClassBySpringCGLIB$$26808f96.invoke(<generated>) 
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) 
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:721) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 
at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:52) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656) 
at org.apache.tomcat.jdbc.pool.DataSource$$EnhancerBySpringCGLIB$$17f85659.getConnection(<generated>) 

マイアスペクトクラス:

import org.aspectj.lang.annotation.*; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.stereotype.Component; 

@Aspect 
@Component 
public class DataSourceAspect { 

    private static final Logger LOG = LoggerFactory.getLogger(DataSourceAspect.class); 

    @AfterReturning(pointcut = "execution(* org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection())") 
    public void afterConnectionEstablished() { 
     LOG.info("Borrowed connection from the pool. Initializing..."); 
    } 
} 

のcontext.xmlでのリソースリンクの定義:

<ResourceLink name="jdbc/us_j2eeCoreDS" 
    global="jdbc/us_j2eeCoreDS" 
    type="javax.sql.DataSource"/> 

server.xmlのデータソースの定義は、(民間の値を変更):

<Resource name="jdbc/us_j2eeCoreDS" type="javax.sql.DataSource" 
     global="jdbc/us_j2eeCoreDS" 
     factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
     driverClassName="oracle.jdbc.OracleDriver" 
     username="xxx" password="xxx" 
     initialSize="1" 
     minIdle="1" 
     maxIdle="4" maxWaitMillis="5000" 
     maxActive="40" 
     removeAbandonedOnBorrow="true" removeAbandonedTimeout="300" 
     testWhileIdle="true" 
     validationQuery="SELECT 1 FROM DUAL" 
     timeBetweenEvictionRunsMillis="60000" 
     url="jdbc:oracle:thin:@host:port:SID"/> 

私はのcontext.xmlでまったく同じデータソースを定義する場合、それは完璧に動作しますが、前に言ったように。

ヒント?

ありがとうございます。

答えて

0

最終的に問題はAOP関連ではなく、依存関係の競合です。

このプロジェクトは、Spring Boot 1.4.4.RELEASEに基づいています。私のbuild.gradleで、私は次の依存関係ました:スターターなので

compile("org.springframework.boot:spring-boot-starter-data-jpa") 

を、それがより多く必要な依存関係を取得するだけの簡単な方法です。提供DEPSの一つは次のとおりです。

org.apache.tomcat:tomcat-jdbc:8.5.11 

をだから、私の戦争パッケージはtomcat-jdbc-8.5.11.jarを含む終わっ結局のところ:提供

org.springframework.boot:spring-boot-starter-jdbc:1.4.4.RELEASE 

Tomcat 8.5.11サーバーにも同じライブラリが含まれています。tomcat-jdbc.jar。プールが定義されてserver.xmlだったので、プールが使用するライブラリがそのWEB-INF/libsディレクトリ内tomcat-jdbc-8.5.11.jarを持つ、tomcat-jdbc.jarが、私のアプリケーションだった

は、ClassCastExceptionが発生につながる、tomcat-jdbc-8.5.11.jarを使用しました。私はプールをcontext.xmlで定義した場合にもっとうまく掘り下げて実際の理由を見つけ出す時間がなかったが、それはちょうどjarローディング優先順位のケースだと思う。

修正:(ちょうどあなたのbuild.gradle構成セクションに含める)以下のGradle enchanmentを使用して、戦争のパッケージからtomcat-jdbc-8.5.11.jarを除外する:

configurations { 
    runtime.exclude module: 'tomcat-jdbc' 
} 

・ホープこれは誰かに役立ちます!

関連する問題