I have answered similar questions several times, e.g. here:
Your case is a bit simpler because you just want to extract a parameter and not its annotation. So along the lines of those other two answers you would use a pointcut like this:
@Before("execution(* *(.., com.hadi.student.Student, ..))")
and then extract the argument in your advice via iterating over thisJoinPoint.getArgs()
and checking for the right parameter type. This is slower and uglier than directly binding a method argument to an advice parameter via args()
, but your only option for parameters in arbitrary positions because args(.., Student, ..)
will yield an "ambiguous argument binding" error. This is because both AspectJ and Spring AOP cannot decide what should happen if there is more than one Student
argument in your method. Which one should they choose?
Here is an MCVE in AspectJ (no Spring required, but works the same way there):
Helper class and driver application:
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"));
}
}
Aspect:
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);
}
}
}
Console log:
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]