Spring , AOP , AspectJ :- 有没有办法找出哪个方法导致调用 "beforeAdvice" 和 "afterAdvice"
Spring , AOP , AspectJ :- is there a way to find out which method caused call to "beforeAdvice" and "afterAdvice"
我有一个关于 Spring 框架、面向方面编程和 AspectJ 的(新手)问题。
有没有办法找出哪个方法导致调用 "beforeAdvice" 和 "afterAdvice"?
例如,在下面的示例中,我能否找出 Dog.bark() 或 Dog.sleep() 是否导致对 "beforeAdvice" 和 "afterAdvice" 的调用?
我在源代码下面附上了控制台输出。
感谢您的宝贵时间和帮助,
詹姆斯
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>
控制台输出
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 ?
您可以从一个新的 Throwable(您不抛出)中提取堆栈。像这样:
StackTraceElement[] stack = new Throwable().getStackTrace();
String methodName = stack[1].getMethodName();
尝试将 JoinPoint
作为参数添加到您的 Aspect 方法中:
public void beforeAdvice(JoinPoint jp) {
// This will print out "bark"
System.out.println( p.getSignature().getName );
}
在 Spring 中,此 JoinPoint 将始终有一个 MethodSignature 作为签名(因为 spring 只能以这种方式访问方法),因此您可以这样做(如果您想了解有关方法,比默认签名界面告诉你的更多)...
MethodSignature signature = (MethodSignature)jp.getSignature();
Method method = signature.getMethod();
对于 Around Aspect,您可以使用 ProceedingJoinPoint
。
每个方法都可以带一个JoinPoint
as parameter. This object contains all the information about the interception that happened (which method, which class, etc.). For example, the getSignature()
方法returns拦截方法的签名。我们可以像这样使用它来检索方法的名称:
public void beforeAdvice(JoinPoint joinPoint) {
System.out.println("DogMonitor.beforeAdvice()");
System.out.println("I just intercepted method " + joinPoint.getSignature().getName());
}
我遇到了同样的问题。我希望我可以从 JoinPoint
中得到一个 getSource
方法,但没有。我不得不查看堆栈。首先,我使用 Thread.dumpStack()
来了解堆栈包含的内容。我不需要遍历整个堆栈,所以我创建了一个子集。从堆栈内容来看,我对 15-20 范围感兴趣(这取决于你)
StackTraceElement[] subset = Arrays.copyOfRange(Thread.currentThread().getStackTrace(), 15, 20);
然后我只打印了我想要的
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);
}
}
}
我有一个关于 Spring 框架、面向方面编程和 AspectJ 的(新手)问题。
有没有办法找出哪个方法导致调用 "beforeAdvice" 和 "afterAdvice"?
例如,在下面的示例中,我能否找出 Dog.bark() 或 Dog.sleep() 是否导致对 "beforeAdvice" 和 "afterAdvice" 的调用?
我在源代码下面附上了控制台输出。
感谢您的宝贵时间和帮助,
詹姆斯
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>
控制台输出
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 ?
您可以从一个新的 Throwable(您不抛出)中提取堆栈。像这样:
StackTraceElement[] stack = new Throwable().getStackTrace();
String methodName = stack[1].getMethodName();
尝试将 JoinPoint
作为参数添加到您的 Aspect 方法中:
public void beforeAdvice(JoinPoint jp) {
// This will print out "bark"
System.out.println( p.getSignature().getName );
}
在 Spring 中,此 JoinPoint 将始终有一个 MethodSignature 作为签名(因为 spring 只能以这种方式访问方法),因此您可以这样做(如果您想了解有关方法,比默认签名界面告诉你的更多)...
MethodSignature signature = (MethodSignature)jp.getSignature();
Method method = signature.getMethod();
对于 Around Aspect,您可以使用 ProceedingJoinPoint
。
每个方法都可以带一个JoinPoint
as parameter. This object contains all the information about the interception that happened (which method, which class, etc.). For example, the getSignature()
方法returns拦截方法的签名。我们可以像这样使用它来检索方法的名称:
public void beforeAdvice(JoinPoint joinPoint) {
System.out.println("DogMonitor.beforeAdvice()");
System.out.println("I just intercepted method " + joinPoint.getSignature().getName());
}
我遇到了同样的问题。我希望我可以从 JoinPoint
中得到一个 getSource
方法,但没有。我不得不查看堆栈。首先,我使用 Thread.dumpStack()
来了解堆栈包含的内容。我不需要遍历整个堆栈,所以我创建了一个子集。从堆栈内容来看,我对 15-20 范围感兴趣(这取决于你)
StackTraceElement[] subset = Arrays.copyOfRange(Thread.currentThread().getStackTrace(), 15, 20);
然后我只打印了我想要的
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);
}
}
}