首页 > 解决方案 > Spring AOP 的 IllegalArgumentException

问题描述

此问题首次报告为Spring issue #24248

我正在使用 Spring AOP 构建一个应用程序,并且正在使用方面来修改我的一些业务对象。当我启动我的应用程序时,我得到以下堆栈跟踪(仅显示根):

java.lang.IllegalArgumentException: methods with same signature get() but incompatible return types: [interface main.DomainObjectInterfaceA, interface main.DomainObjectInterfaceB]
    at sun.misc.ProxyGenerator.checkReturnTypes(ProxyGenerator.java:712)
    at sun.misc.ProxyGenerator.generateClassFile(ProxyGenerator.java:461)
    at sun.misc.ProxyGenerator.generateProxyClass(ProxyGenerator.java:339)
    at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:639)
    at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:557)
    at java.lang.reflect.WeakCache$Factory.get(WeakCache.java:230)
    at java.lang.reflect.WeakCache.get(WeakCache.java:127)
    at java.lang.reflect.Proxy.getProxyClass0(Proxy.java:419)
    at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:719)
    at org.springframework.aop.framework.JdkDynamicAopProxy.getProxy(JdkDynamicAopProxy.java:123)
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:473)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:355)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:304)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:439)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1712)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:581)
    ... 10 more

我从我的应用程序中提取了一个最小的代码片段来重现这个堆栈跟踪。

kriegaex 的评论:我创建了一个MCVE并将其推送到GitHub存储库。

我的域模型由三个类组成:

package main;
public interface DomainObjectInterfaceA {
}
package main;
public interface DomainObjectInterfaceB{
}
package main;
public class DomainObjectImplementation implements DomainObjectInterfaceA, DomainObjectInterfaceB {

  private int fieldToModifyThroughAspect = 0;

  public int getFieldToModifyThroughAspect() {
    return fieldToModifyThroughAspect;
  }

  public void setFieldToModifyThroughAspect( int aFieldToModify ) {
    fieldToModifyThroughAspect = aFieldToModify;
  }
}

此外,我有以下两个 Spring 组件:

package main;
@Component
public class ComponentImplementation implements ComponentInterfaceA<DomainObjectImplementation>, ComponentInterfaceB<DomainObjectImplementation> {

  public DomainObjectImplementation get() {
    return new DomainObjectImplementation();
  }
}

package main;
@org.aspectj.lang.annotation.Aspect
@Component
public class Aspect {

  @Pointcut( "execution(public DomainObjectImplementation main.ComponentImplementation.*(..))" )
  public void anyPublicOperation() {
  }

  @AfterReturning( pointcut = "anyPublicOperation()", returning = "aObject" )
  public Object get( Object aObject ) {
    DomainObjectImplementation returningObject = ( DomainObjectImplementation ) aObject;
    returningObject.setFieldToModifyThroughAspect( 5);
    return returningObject;
  }

}

重现问题的关键部分是以下两个通用接口,它们由以下人员实现ComponentImplementation

package main;
public interface ComponentInterfaceA<T extends DomainObjectInterfaceA> {

  T get();

}
package main;
public interface ComponentInterfaceB<T extends DomainObjectInterfaceB> {

  T get();

}

以上两个接口共享一个签名相同但泛型类型不同的方法。ComponentImplementation使用满足这两个通用参数的类来实现这两个接口。

最后两个必需的类当然是下面声明的Main类和Spring配置类:

package main;
@Configuration
@EnableAspectJAutoProxy
@ComponentScan( basePackageClasses = Config.class )
public class Config {
}

package main;
public class Main {

  public static void main( String[] args ) {

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( Config.class );
    ComponentImplementation bean = context.getBean( ComponentImplementation.class );
    DomainObjectImplementation domainObject = bean.get();

    System.err.println("Aspect modified get method = " + ( domainObject.getFieldToModifyThroughAspect() == 5));
  }

}

我也尝试使用 进行配置EnableAspectJAutoProxyproxyTargetClass = true但随后抛出相同的异常,堆栈跟踪略有不同(即 JDK 代理与 Cglib)

完整的依赖列表:

  <dependencies>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>5.0.7.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.0.7.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>5.0.7.RELEASE</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.5</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/aspectj/aspectjrt -->
    <dependency>
      <groupId>aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.5.4</version>
    </dependency>


  </dependencies>

标签: springinheritanceproxyspring-aopillegalargumentexception

解决方案


推荐阅读