当前位置: 首页 > 知识库问答 >
问题:

通知从具体非泛型类中的泛型抽象类继承的方法

扶珂
2023-03-14

例如,我有以下接口

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
    }
}

我想建议所有将字符串转换为任何内容的方法。我创建了以下方面

@Aspect
@Component
public class ConverterAspect {

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

这是行不通的。Spring不会为StringToIntegerConverter类创建代理。然而,如果我从抽象类重写convert(stringinput)方法,它将开始工作,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(字符串输入)方法?

共有1个答案

强化
2023-03-14

AbstractIntegerConverter中,方法签名不是公共整数转换(字符串输入),而是公共整数转换(T输入),因此切入点**..*。转换器。转换(字符串)不匹配。改为使用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))

看到了吗<代码>转换(对象),而不是转换(字符串),因此不匹配。

旁白:这是一个有趣的问题,不像大多数AspectJ或SpringAOP问题那么无聊。所以谢谢你<代码>:-)

更新:

至于您的后续问题,以下是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;
}

看到没?签名是转换(对象),我的方面的日志输出也显示了这一点。

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;
}

并且在具体的转换器类中没有转换(String)转换(无论)方法。

你现在相信我了吗?

 类似资料:
  • 问题内容: 我有以下界面: 我在下面有抽象类(没有提到方法插入): 我有具体的课程: 最后,SpecificEntryBean定义为: 我有以下错误: 类型SpecificEntry必须实现继承的抽象方法SingleRecordInterface.insert(AbstractEntryBean) 考虑到SpecificEntryBean扩展了AbstractEntryBean,所以我不明白此错误

  • 它是关于java中具有两种泛型类型(一种用于返回类型,另一种用于形式参数)的泛型方法以及如何实现它。我想我在图片中缺少一些东西来让它工作。 事情是这样的... 这是工作 : 这不起作用: java编译器告诉我: 好吧,就是这样。提前感谢大家!希望它能在未来帮助别人! P、 D:这不是枚举类型的问题。它发生在类和层次结构之间。所以别怪Enum了,我试过了,但没用。 对于泛型参数 我们可以做一个一般规

  • 我有一个典型的问题,什么是更好的,我认为答案总是视情况而定,但我还是想澄清一下。所以有两种方法: 逻辑是: 我知道由于类型擦除,方法签名存在冲突,所以我的问题不是“为什么我不能同时拥有这两个方法?”,而是“你会选择哪种方法?”。

  • 我有2个抽象的类操纵泛型和一个工厂与泛型。父级独立于trips对象和因式分解代码。儿子只基于trips。 Eclipse上的AbstractTripBasedPurchaseExtractor第9行出现错误:Bound mismatch:类型TRIP_PURCHASE不是bounded参数的有效替代品 类型的 此处:extends AbstractPurchaseExtractor“ 在son类上

  • 在java中,是否可以使用通配符定义抽象方法,但在实现中使用具体类型 eg: 在这样的抽象类中定义抽象方法 实现如下抽象方法,其中CorporateServer扩展了用户:

  • 在JLS 8第8.4.8.1节中,有一条声明: 在某些参数化下,泛型超类C中的具体方法可以与该类中的抽象方法具有相同的签名。在这种情况下,具体方法是继承的,而抽象方法不是。然后应将继承的方法视为覆盖其来自C的抽象对等体。 有人能为泛型类提供这种参数化的例子吗?我不能。