【问题标题】:AspectJ Aspect under JBoss AS 7 throws Xlint:invalidAbsoluteTypeNameJBoss AS 7 下的 AspectJ Aspect 抛出 Xlint:invalidAbsoluteTypeName
【发布时间】:2012-12-18 23:17:29
【问题描述】:

我有一组使用 Maven 构建的 AspectJ 1.6.12 和 Spring 3.1.2.RELEASE 在 JBoss 6.1.0.Final 上正常工作的 WAR。我们想在不久的将来迁移到 JBoss AS 7,所以我从源代码编译了 JBoss 7.1.3.Final。

在遇到单个 WAR 文件问题后,我决定将应用程序重新打包为 EAR 文件,这样我们所有的代码都将放在一个可再分发、可部署的单元中。

我无法让我们的分析方面正常工作。这是一个非常简单的方面,包含在我们的 EAR/lib 目录中的 JAR 中,它对使用 @Timed 注释注释的任何方法进行计时:

package com.mycompany.toplayer.perf;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;


@Component
@Aspect
public class MethodTimerAdvice {
    private Logger log = LoggerFactory.getLogger(getClass());

    @SuppressWarnings("unchecked")
    @Around(value="execution(@com.mycompany.toplayer.perf.Timed * *(..))")
    public Object timeMethod(ProceedingJoinPoint pjp) throws Throwable
    {
        String methodName = pjp.getSignature().toShortString();
        long start = System.currentTimeMillis();

        Object ret = pjp.proceed();

        long end = System.currentTimeMillis();

        long total = end - start;

        long used_mem = Runtime.getRuntime().totalMemory()
                - Runtime.getRuntime().freeMemory();
        long mem_gb = used_mem / (1024 * 1024);     

        log.trace("{} | {} | {}M | {} | {} | {}", 
                new Object[] {start, total, 
                        mem_gb, 
                        Thread.currentThread().getId(), 
                        Thread.currentThread().getName(),   
                        methodName}
        );

        return ret;
    }
}

注意注解在同一个包中。
这是方面的相关Spring配置文件,同样非常简单:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:component-scan base-package="com.mycompany" />
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

EAR 中包含三个 WAR 文件,但现在只有一个使用这个方面,gdm-updater.WAR。当我尝试启动服务器时,出现如下错误:

Caused by: java.lang.IllegalArgumentException: warning no match for this type name: Timed [Xlint:invalidAbsoluteTypeName]
    at org.aspectj.weaver.tools.PointcutParser.parsePointcutExpression(PointcutParser.java:301) [aspectjtools.jar:]
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.buildPointcutExpression(AspectJExpressionPointcut.java:207) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.getFallbackPointcutExpression(AspectJExpressionPointcut.java:358) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.getShadowMatch(AspectJExpressionPointcut.java:409) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.matches(AspectJExpressionPointcut.java:272) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:226) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:264) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:296) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(AbstractAdvisorAutoProxyCreator.java:117) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:87) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:68) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:359) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322) [spring-aop-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:407) [spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1598) [spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:162) [spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    ... 28 more

我也尝试将 AspectJ 作为一个模块包含在内,这里是 EAR 中包含的 jboss-deployment-structure.xml 文件。

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
  <deployment>
    <exclusions>
      <module name="org.hibernate" slot="main"/>
    </exclusions>
  </deployment>
  <sub-deployment name="gdm-updater-1.2.0-SNAPSHOT.war"> 
      <exclusions>
          <module name="org.hibernate" slot="main"/>
        </exclusions>
        <dependencies>
          <module name="org.aspectj.tools" slot="main" />
          <module name="org.aspectj.weaver" slot="main" />
        </dependencies>
  </sub-deployment>   
</jboss-deployment-structure>

我什至尝试在 gdm-updater.war 中使用 Maven AspectJ 编译器插件在 gdm-updater.war 的 pom.xml 中进行编译时编织:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.4</version>
    <configuration>
        <showWeaveInfo>true</showWeaveInfo>
        <source>${compiler.version}</source>
        <target>${compiler.version}</target>
        <Xlint>ignore</Xlint>
        <complianceLevel>${compiler.version}</complianceLevel>
        <encoding>UTF-8</encoding>
        <verbose>false</verbose>
        <aspectLibraries>
            <aspectLibrary>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
            </aspectLibrary>
        </aspectLibraries>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>compile</goal>
                <goal>test-compile</goal>
            </goals>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
    </dependencies>
</plugin>   

我什么都做不了。 我在网上搜索了答案并找到了几个链接,但似乎没有一个是相关的:

Has anyone run AspectJ with JBoss AS 7.1.1 final? - 不相关,因为我没有使用加载时编织

https://issues.jboss.org/browse/AS7-3681 - 不相关,因为我没有使用加载时编织或 AspectJ 作为 Java 代理

我考虑过加载时编织,但相关方面将很快扩展为包含“通用”jar 文件的其余部分中存在的一些功能,我无法将其分解为引导类路径。这意味着每次我们有一个新的方面,我们都必须重新配置服务器。

我做错了什么?

【问题讨论】:

    标签: jboss7.x aspectj spring-aop


    【解决方案1】:

    对我来说,在大多数情况下,这“行得通”。我有一个exampleprojects,我一直在用 JBoss AS7 测试没有加载时间编织的简单方面。

    对我不起作用的部分是,如果我指定了这样的对象:

    <jee:jndi-lookup id="dataSource" jndi-name="jboss/datasources/ExampleDS"/>
    

    这有问题,因为 JBoss 内部模块是使用 ModuleClassLoader 加载的,它只对特定模块可见。然而,Aspect-J 试图检查我的方面并失败了,因为那个特定的类加载器没有加载我的方面类。和explained here一样。

    解决方法是在 module.xml / jboss-deployment-structure.xml 中依赖 jdbc 内部:

    <jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
    <deployment>
      <dependencies>
        <module name="org.jboss.ironjacamar.jdbcadapters"/>
      </dependencies>
    </deployment>
    </jboss-deployment-structure>
    

    如果您使用调试器,您可以连接异常 java.lang.IllegalArgumentException 并检查它正在使用哪个类加载器以及它试图从调用堆栈加载哪个类。我就是这么做的。

    我发现的另一个解决方法是直接在代码中而不是在 Spring 上下文中进行 JNDI 查找。这也有效。

    我也在这个问题上打开了AS7-6305 / WFLY-826

    更新:问题已在 JBoss 端被拒绝。他们声称这是 AspectJ 的一个问题。我还打开了一个bug there,它还没有 cmets。

    【讨论】:

    • 我看到这个问题被拒绝了。感谢您至少尝试!
    • @Brad 没问题。我更新了答案以也参考 aspect-j 错误报告。
    【解决方案2】:

    我们最近在从 JBoss EAP 6.4.8 升级到 6.4.9 时遇到了类似的问题。

    我们的 JNDI 数据源的数据源实现似乎从 org.jboss.jca.adapters.jdbc.WrapperDataSource 更改为 org.jboss.as.connector.subsystems.datasources.WildFlyDataSource

    我们将以下部署依赖项添加到应用程序的 jboss-deployment-structure.xml 文件中,这已为我们解决了问题。

    <module name="org.jboss.as.connector" slot="main"/>
    

    此模块包含WildFlyDataSource 实现。像这个线程中的其他人一样,我们之前已经拥有 org.jboss.ironjacamar.jdbcadapters 依赖项。看起来org.jboss.as.connector 模块可以代替这个。

    正如@eis's answer 中所讨论的,该问题与 JNDI 数据源、AspectJ、Spring 和类加载有关。我能够捕捉到这一点的唯一方法是在本地运行 JBoss 并在 IllegalArgumentException 上放置一个断点。

    另一种解决方法是在 Spring 配置中使用 proxy-interface 代理您的数据源 - 例如

    <jee:jndi-lookup id="dataSource" jndi-name="some_jndi_name" proxy-interface="javax.sql.DataSource" />
    

    【讨论】:

      【解决方案3】:

      我在这里找到了至少部分解决方案...

      http://pushpendrasinghbaghel.blogspot.com/2013/01/spring-aop-and-jbossas-7.html

      问题似乎随时发生,需要通知加载核心 JBoss 模块的类加载器加载的内容...

      【讨论】:

        【解决方案4】:

        我遇到了同样的问题。我已经通过将 spring-aop 库的版本降级到 3.0.7.RELEASE 来解决它。当然这只是临时解决方案,我正在等待这个问题的真正原因。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-07-16
          • 2012-04-16
          • 1970-01-01
          • 2013-03-15
          • 2013-04-02
          • 2012-07-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多