【问题标题】:Aspect fails with ClassCastException trying to pointcut Tomcat DataSource getConnectionAspect 失败,ClassCastException 试图切入 Tomcat DataSource getConnection
【发布时间】:2017-02-02 11:16:50
【问题描述】:

我需要对从 Tomcat JDBC 池借用的每个连接执行几个初始化语句。我无法使用 JDBCInterceptors,因为池与不需要所述初始化的其他应用程序共享。

我正在使用 Spring Boot 1.4.4,部署在 Tomcat 8.5.11 上,它在 context.xml 中有一个 ResourceLink 到 server.xml 中的一个 Resource,它针对 Oracle 11g 数据库定义了 DataSource。我正在通过 JNDI 访问数据源。

根据这个答案https://stackoverflow.com/a/38746398 我想使用 Spring AOP 来实现我的目标。

如果直接在 context.xml 中定义 DataSource,我创建的 Aspect 可以完美运行,但如果通过 ResourceLink 引用到 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 定义:

<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 中定义完全相同的 DataSource,它会完美运行。

有什么线索吗?

非常感谢。

【问题讨论】:

    标签: java spring-boot spring-aop tomcat8 tomcat-jdbc


    【解决方案1】:

    最终问题不是 AOP 相关,而是依赖冲突。

    该项目基于 Spring Boot 1.4.4.RELEASE。在我的build.gradle 中,我有以下依赖:

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

    作为初学者,这只是获得更多所需依赖项的快速方法。提供的部门之一是:

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

    提供:

    org.apache.tomcat:tomcat-jdbc:8.5.11
    

    结果我的战争包最终包含tomcat-jdbc-8.5.11.jar

    Tomcat 8.5.11 服务器也包含相同的库,tomcat-jdbc.jar

    由于池是 server.xml 定义的,池使用的库是 tomcat-jdbc.jar,但我的应用程序在其 WEB-INF/libs 目录中包含 tomcat-jdbc-8.5.11.jar,使用 tomcat-jdbc-8.5.11.jar,导致 ClassCastException。如果池是在context.xml 中定义的,我没有时间去挖掘更多并找到它工作的真正原因,但我想这只是一个jar 加载优先级的情况。

    修复:使用以下 gradle 增强功能从 war 包中排除 tomcat-jdbc-8.5.11.jar(只需将其包含在您的 build.gradle 配置部分中):

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

    希望这对其他人有帮助!

    【讨论】:

      猜你喜欢
      • 2016-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-14
      • 2012-12-08
      • 1970-01-01
      相关资源
      最近更新 更多