建议从具体非泛型类中的泛型抽象类继承方法

问题描述 投票:2回答:1

例如,我有以下界面

public interface Converter<I, O> {
    public O convert(I input);
}

实现此接口的抽象类

public abstract class AbstractIntegerConverter<T> implements Converter<T, Integer> {

    public Integer convert(T input) {
        // convert anything to int
    }

    public abstract Integer defaultValue();
}

并具体实施

@Component
public class StringToIntegerConverter extends AbstractIntegerConverter<String> {

    @Override
    public Integer defaultValue() {
        // implementation
    }
}

我想建议所有将String转换为任何东西的方法。我创建了以下方面

@Aspect
@Component
public class ConverterAspect {

    @Around("execution(* *..*.Converter+.convert(String))")
    public Object adviceStringConverter(ProceedingJoinPoint joinPoint) throws Throwable {
        // logic
    }
}

这不起作用。 Spring不会为StringToIntegerConverter类创建代理。但是,如果我从抽象类重写convert(String input)方法,它就会开始工作,Spring会成功为StringToIntegerConverter创建代理并执行所有需要的逻辑。

@Component
public class StringToIntegerConverter extends AbstractIntegerConverter<String> {

    @Override
    public Integer convert(String input) {
        return super.convert(input);
    }

    @Override
    public Integer defaultValue() {
        // implementation
    }
}

为什么会这样?有没有办法定义切入点,所以我不需要覆盖convert(String input)方法?

java spring aop spring-aop
1个回答
0
投票

AbstractIntegerConverter方法签名不是public Integer convert(String input)而是public Integer convert(T input),因此你的切入点* *..*.Converter+.convert(String)不匹配。改为使用Object*并通过args()验证运行时类型,而不是使用编译时签名:

@Around("execution(* *..Converter+.convert(*)) && args(input)")
public Object adviceStringConverter(ProceedingJoinPoint joinPoint, String input) throws Throwable {
    System.out.println(joinPoint);
    return joinPoint.proceed();
}

使用我添加的日志行,您将在控制台上看到如下内容:

execution(Integer de.scrum_master.app.AbstractIntegerConverter.convert(Object))

看到? convert(Object),而不是convert(String),因此不匹配。

P.S。:这是一个有趣的问题,不像大多数AspectJ或Spring AOP那样乏味。所以,谢谢你。 :-)


更新:

至于你的后续问题,这里是javap -s打印(方面停用):

javap -s AbstractIntegerConverter.class

Compiled from "AbstractIntegerConverter.java"
public abstract class de.scrum_master.app.AbstractIntegerConverter<T> implements de.scrum_master.app.Converter<T, java.lang.Integer> {
  public de.scrum_master.app.AbstractIntegerConverter();
    descriptor: ()V

  public java.lang.Integer convert(T);
    descriptor: (Ljava/lang/Object;)Ljava/lang/Integer;

  public abstract java.lang.Integer defaultValue();
    descriptor: ()Ljava/lang/Integer;

  public java.lang.Object convert(java.lang.Object);
    descriptor: (Ljava/lang/Object;)Ljava/lang/Object;
}

看到?签名是convert(Object),因为我的方面的日志输出也显示。

javap -s StringToIntegerConverter.class

Compiled from "StringToIntegerConverter.java"
public class de.scrum_master.app.StringToIntegerConverter extends de.scrum_master.app.AbstractIntegerConverter<java.lang.String> {
  public de.scrum_master.app.StringToIntegerConverter();
    descriptor: ()V

  public java.lang.Integer defaultValue();
    descriptor: ()Ljava/lang/Integer;
}

并且在混凝土转换器类中没有convert(String)convert(whatever)方法。

你现在相信我吗?

© www.soinside.com 2019 - 2024. All rights reserved.