Reputation: 189
I have a (newbie) question regarding Spring framework, Aspect Orientated Programming and AspectJ.
Is there a way to find out which method caused call to "beforeAdvice" and "afterAdvice" ?
For example , in the example below , can I find out if Dog.bark() or Dog.sleep() caused call to "beforeAdvice" and "afterAdvice" ?
I have attached the console output below the source code.
Thanks for your time and help,
James
Dog.java
package com.tutorialspoint;
public class Dog
{
public void bark()
{
System.out.println("Dog.bark()");
}
public void sleep()
{
System.out.println("Dog.sleep()");
}
}
DogMonitor.java
package com.tutorialspoint;
public class DogMonitor
{
public void beforeAdvice()
{
System.out.println("DogMonitor.beforeAdvice() -- but was it bark or sleep ?");
}
public void afterAdvice()
{
System.out.println("DogMonitor.afterAdvice() -- but was it bark or sleep ?");
}
public void afterReturningAdvice(Object retVal)
{
System.out.println("DogMonitor.afterReturningAdvice(): " + retVal.toString());
}
public void AfterThrowingAdvice(IllegalArgumentException ex)
{
System.out.println("DogMonitor.AfterThrowingAdvice(): " + ex.toString());
}
}
MainApp.java
package com.tutorialspoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp
{
public static void main(String[] args)
{
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
Dog dog = (Dog) context.getBean("dog");
dog.bark();
dog.sleep();
}
}
Beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<aop:config>
<aop:aspect id="dogMonitorAspect" ref="dogMonitorBean">
<aop:pointcut id="selectAll" expression="execution(* com.tutorialspoint.Dog.*(..))"/>
<aop:before pointcut-ref="selectAll" method="beforeAdvice"/>
<aop:after pointcut-ref="selectAll" method="afterAdvice"/>
</aop:aspect>
</aop:config>
<!-- Definition for dog bean -->
<bean id="dog" class="com.tutorialspoint.Dog"/>
<!-- Definition for dogMonitor bean -->
<bean id="dogMonitorBean" class="com.tutorialspoint.DogMonitor"/>
</beans>
Console output
DogMonitor.beforeAdvice() -- but was it bark or sleep ?
Dog.bark()
DogMonitor.afterAdvice() -- but was it bark or sleep ?
DogMonitor.beforeAdvice() -- but was it bark or sleep ?
Dog.sleep()
DogMonitor.afterAdvice() -- but was it bark or sleep ?
Upvotes: 1
Views: 2618
Reputation: 598
I had the same problem. I was hoping I could get a getSource
method from the JoinPoint
but there isn't. I had to look into the stack instead. First I used Thread.dumpStack()
to get a sense of what the stack contains. I don't need to go through the entire stack so I created a subset. From the stack contents, I'm interested in the 15-20 range (this depends on you)
StackTraceElement[] subset = Arrays.copyOfRange(Thread.currentThread().getStackTrace(), 15, 20);
Then I printed only what I want
String mypackage = "abc.xwy";
for (int i = 0; i < subset.length; i++) {
StackTraceElement element = subset[i];
if (element.getClassName().contains(mypackage) || element.getMethodName().equals(methodName)) {
System.out.println(element);
}
}
}
Upvotes: 1
Reputation: 10652
Try adding a JoinPoint
as a parameter to your Aspect methods:
public void beforeAdvice(JoinPoint jp) {
// This will print out "bark"
System.out.println( p.getSignature().getName );
}
In Spring, this JoinPoint will always have a MethodSignature as a Signature (since spring can only access methods that way), so you can then do (if you want detailed information about the method, more than what the default signature interface tells you)...
MethodSignature signature = (MethodSignature)jp.getSignature();
Method method = signature.getMethod();
And for an Around Aspect, you can use a ProceedingJoinPoint
.
Upvotes: 2
Reputation: 137064
Each method can take a JoinPoint
as parameter. This object contains all the information about the interception that happened (which method, which class, etc.). For example, the getSignature()
method returns the signature of the intercepted method. We can use it to retrieve the name of the method like this:
public void beforeAdvice(JoinPoint joinPoint) {
System.out.println("DogMonitor.beforeAdvice()");
System.out.println("I just intercepted method " + joinPoint.getSignature().getName());
}
Upvotes: 0
Reputation: 897
You could pull the stack from a new Throwable (that you don't throw). Like so:
StackTraceElement[] stack = new Throwable().getStackTrace();
String methodName = stack[1].getMethodName();
Upvotes: 1