Spring AOP 参数

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


我对 Spring AOP 有疑问。我想在切入点中获取 Student 的对象。但是我的 JoinPoints 可以以任何优先级拥有这个对象。
查看下面为两个不同的 JoinPoints 和我创建的切入点截取的代码:

public Student createStudent(String s, Student student) {...}
public Student updateStudent(Student student, String s) {...}

@Before("args(..,com.hadi.student.Student)") 
public void myAdvice(JoinPoint jp) {
    Student student = null;
    for (Object o : jp.getArgs()) {
        if (o instanceof Student) {
            student = (Student) o;
        }
    }
}

以上代码仅适用于第一个 JoinPoint。所以问题是如何创建一个切入点,该切入点将针对输入参数中 Student 的任何情况执行。
我无法使用下面的代码,它抛出 runtimeException:

@Before("args(..,com.hadi.student.Student,..)")

我把代码写得通俗易懂,其实我的Poincut比这个大很多。所以请用args方式回答。

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

我已经多次回答过类似的问题,例如这里:

你的案例有点简单,因为你只想提取一个参数而不是它的注释。因此,按照其他两个答案的思路,您将使用这样的切入点:

@Before("execution(* *(.., com.hadi.student.Student, ..))")

然后通过迭代

thisJoinPoint.getArgs()
并检查正确的参数类型来提取建议中的参数。这比通过
args()
直接将方法参数绑定到建议参数更慢和丑陋,但是您对任意位置参数的唯一选择,因为
args(.., Student, ..)
会产生“模糊参数绑定”错误。这是因为 AspectJ 和 Spring AOP 都无法决定如果您的方法中有多个
Student
参数应该发生什么。他们应该选择哪一个?

这是 AspectJ 中的一个 MCVE(不需要 Spring,但在那里的工作方式相同):

Helper类和驱动程序应用程序:

package de.scrum_master.app;

public class Student {
  private String name;

  public Student(String name) {
    this.name = name;
  }

  @Override
  public String toString() {
    return "Student [name=" + name + "]";
  }
}
package de.scrum_master.app;

public class Application {
  public void doSomething() {}

  public Student createStudent(String s, Student student) {
    return student;
  }

  public Student updateStudent(Student student, String s) {
    return student;
  }

  public void marryStudents(Student student1, Student student2) {}

  public static void main(String[] args) {
    Application application = new Application();
    application.doSomething();
    application.createStudent("x", new Student("John Doe"));
    application.updateStudent(new Student("Jane Doe"), "y");
    // What happens if we have multiple Student parameters?
    application.marryStudents(new Student("Jane"), new Student("John"));
  }
}

看点:

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

import de.scrum_master.app.Student;

@Aspect
public class MyAspect {
  @Before("execution(* *(.., de.scrum_master.app.Student, ..))")
  public void interceptMethodsWithStudentArgs(JoinPoint thisJoinPoint) throws Throwable {
    System.out.println(thisJoinPoint);
    for(Object arg : thisJoinPoint.getArgs()) {
      if (!(arg instanceof Student))
        continue;
      Student student = (Student) arg;
      System.out.println("  " + student);
    }
  }
}

控制台日志:

execution(Student de.scrum_master.app.Application.createStudent(String, Student))
  Student [name=John Doe]
execution(Student de.scrum_master.app.Application.updateStudent(Student, String))
  Student [name=Jane Doe]
execution(void de.scrum_master.app.Application.marryStudents(Student, Student))
  Student [name=Jane]
  Student [name=John]
© www.soinside.com 2019 - 2024. All rights reserved.