Search code examples
javaspringaopaspectjspring-aop

Spring , AOP , AspectJ :- is there a way to find out which method caused call to "beforeAdvice" and "afterAdvice"


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 ?

Solution

  • 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.