使用泛型类型作为切入点的返回类型

del*_*svb 3 java spring spring-aop spring-boot

我正在使用 Spring Boot 来设置 REST API。我将制作一堆@RestControllers 并希望在那些返回我调用的特定抽象类的子类型的方法上设置切入点Model。这些控制器看起来像这样:

@RestController
public class UserController {
    @RequestMapping(...)
    public Person getAllPeople() {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

我的Person课程看起来像这样:

public class Person extends Model {
    ...
}
Run Code Online (Sandbox Code Playgroud)

那么是否可以写出如下所示的建议:

@Aspect
@Component
public class ModelAspect {
    @AfterReturning(
        value = "execution(<T extends mypackages.Model> T mypackages.api.*.*(..))",
        returning = "model")
    public void doSomethingWithModel(Model model) {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,这是行不通的,因为该建议在语法上无效。在参考文档中,我只找到了有关泛型参数的信息,没有找到返回类型的信息(Spring AOP 参考)。我现在拥有的是这样的,但我认为像上面的例子这样的东西会更有效:

@Aspect
@Component
public class ModelAspect {
    @AfterReturning(
        value = "execution(* mypackages.api.*.*(..))",
        returning = "model")
    public void doSomething(Object model) {
        if (model instanceof Model)
            doSomethingWithModel((Model) model);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的下一个问题是,对于那些返回 a Collectionof supertypes of 的方法是否可能有同样的情况Model?因为参考文献指出参数类型不能是泛型Collection

alf*_*ope 5

您是否尝试过在界面后使用 + ?

@Aspect
@Component
public class ModelAspect {
    @AfterReturning(
        value = "execution(mypackages.Model+ mypackages.api.*.*(..))",
        returning = "model")
    public void doSomethingWithModel(Model model) {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以尝试不指定返回类型。根据文档,它将通过返回子句中使用的参数类型来解析:

Returning 子句还限制只匹配那些返回指定类型值的方法执行(在本例中为 Object,它将匹配任何返回值)。

@Aspect
@Component
public class ModelAspect {
    @AfterReturning(
        value = "execution(* mypackages.api.*.*(..))",
        returning = "model")
    public void doSomethingWithModel(Model model) {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

看看下面的链接。它也回答了你的第二个问题,关于通用集合。

Aspectj 匹配返回类型


出于好奇,我创建了一个项目来测试它,它直接开始为我工作。我只能认为你的切入点指向的路径是错误的。尝试使用:

@Aspect
@Component
public class ModelAspect {
    @AfterReturning(
        value = "execution(* mypackages.api..*(..))",
        returning = "model")
    public void doSomethingWithModel(Model model) {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以查看我的项目:spring-aspectj-interfaces 在那里您将看到切入点的不同值(当然,只有一个未注释),所有这些值都有效。