【问题标题】:Spring AOP argsSpring AOP 参数
【发布时间】:2018-01-23 09:53:46
【问题描述】:


我对 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。所以问题是如何创建一个切入点,该切入点将在输入参数中的任何学生情况下执行。
我不能使用下面的代码,它会抛出 runtimeException:
@Before("args(..,com.hadi.student.Student,..)")

我使代码易于理解,实际上我的 Poincut 比这大得多。所以请用args的方式回答。

【问题讨论】:

    标签: java spring-aop


    【解决方案1】:

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

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

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

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

    这是 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]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-14
      • 1970-01-01
      相关资源
      最近更新 更多