
是的你可以。您需要
handler()切入点:
package de.scrum_master.aspect;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;@Aspectpublic class LogAspect { @AfterThrowing(value = "execution(* *(..))", throwing = "e") public void log(JoinPoint thisJoinPoint, Throwable e) { System.out.println(thisJoinPoint + " -> " + e); } @Before("handler(*) && args(e)") public void logCaughtException(JoinPoint thisJoinPoint, Exception e) { System.out.println(thisJoinPoint + " -> " + e); }}假设类
Example在包中,则日志输出
de.scrum_master.app:
***** Calling method with catch block *****handler(catch(ArithmeticException)) -> java.lang.ArithmeticException: / by zeroCan not divide by zero***** Calling method without catch block *****execution(void de.scrum_master.app.Example.divideByZeroWithNoCatch()) -> java.lang.ArithmeticException: / by zeroexecution(void de.scrum_master.app.Example.main(String[])) -> java.lang.ArithmeticException: / by zeroException in thread "main" java.lang.ArithmeticException: / by zero at de.scrum_master.app.Example.divideByZeroWithNoCatch(Example.java:13) at de.scrum_master.app.Example.main(Example.java:21)
更新:
如果您想知道异常处理程序的位置,有一个简单的方法:使用封闭的连接点的静态部分。您还可以获得有关参数名称和类型等的信息。只需使用代码完成功能即可查看可用的方法。
@Before("handler(*) && args(e)")public void logCaughtException( JoinPoint thisJoinPoint, JoinPoint.EnclosingStaticPart thisEnclosingJoinPointStaticPart, Exception e) { // Exception handler System.out.println(thisJoinPoint.getSignature() + " -> " + e); // Method signature + parameter types/names MethodSignature methodSignature = (MethodSignature) thisEnclosingJoinPointStaticPart.getSignature(); System.out.println(" " + methodSignature); Class<?>[] paramTypes = methodSignature.getParameterTypes(); String[] paramNames = methodSignature.getParameterNames(); for (int i = 0; i < paramNames.length; i++) System.out.println(" " + paramTypes[i].getName() + " " + paramNames[i]); // Method annotations - attention, reflection! Method method = methodSignature.getMethod(); for (Annotation annotation: method.getAnnotations()) System.out.println(" " + annotation);}现在像这样更新代码:
package de.scrum_master.app;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;@Retention(RetentionPolicy.RUNTIME)public @interface MyAnnotation { int id(); String name(); String remark();}package de.scrum_master.app;public class Example { @MyAnnotation(id = 11, name = "John", remark = "my best friend") public void divideByZeroWithCatch(int dividend, String someText) { try { int a = 5 / 0; } catch (ArithmeticException e) { System.out.println("Can not divide by zero"); } } public void divideByZeroWithNoCatch() { int b = 5 / 0; } public static void main(String[] args) { Example e = new Example(); System.out.println("***** Calling method with catch block *****"); e.divideByZeroWithCatch(123, "Hello world!"); System.out.println("***** Calling method without catch block *****"); e.divideByZeroWithNoCatch(); }}然后控制台日志显示:
***** Calling method with catch block *****catch(ArithmeticException) -> java.lang.ArithmeticException: / by zero void de.scrum_master.app.Example.divideByZeroWithCatch(int, String) int dividend java.lang.String someText @de.scrum_master.app.MyAnnotation(id=11, name=John, remark=my best friend)Can not divide by zero***** Calling method without catch block *****execution(void de.scrum_master.app.Example.divideByZeroWithNoCatch()) -> java.lang.ArithmeticException: / by zeroexecution(void de.scrum_master.app.Example.main(String[])) -> java.lang.ArithmeticException: / by zeroException in thread "main" java.lang.ArithmeticException: / by zero at de.scrum_master.app.Example.divideByZeroWithNoCatch(Example.java:14) at de.scrum_master.app.Example.main(Example.java:22)
如果那对您足够好,那么您就很好。但是请注意,静态部分不是完整的连接点,因此您不能从那里访问参数值。为此,您必须进行手动记账。这可能很昂贵,并且可能会使您的应用程序变慢。但是,对于它的价值,我向您展示了如何做到:
package de.scrum_master.aspect;import java.lang.annotation.Annotation;import java.lang.reflect.Method;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.reflect.MethodSignature;@Aspectpublic class LogAspect { private ThreadLocal<JoinPoint> enclosingJoinPoint; @AfterThrowing(value = "execution(* *(..))", throwing = "e") public void log(JoinPoint thisJoinPoint, Throwable e) { System.out.println(thisJoinPoint + " -> " + e); } @Before("execution(* *(..)) && within(de.scrum_master.app..*)") public void recordJoinPoint(JoinPoint thisJoinPoint) { if (enclosingJoinPoint == null) enclosingJoinPoint = ThreadLocal.withInitial(() -> thisJoinPoint); else enclosingJoinPoint.set(thisJoinPoint); } @Before("handler(*) && args(e)") public void logCaughtException(JoinPoint thisJoinPoint, Exception e) { // Exception handler System.out.println(thisJoinPoint + " -> " + e); // Method signature + parameter types/names JoinPoint enclosingJP = enclosingJoinPoint.get(); MethodSignature methodSignature = (MethodSignature) enclosingJP.getSignature(); System.out.println(" " + methodSignature); Class<?>[] paramTypes = methodSignature.getParameterTypes(); String[] paramNames = methodSignature.getParameterNames(); Object[] paramValues = enclosingJP.getArgs(); for (int i = 0; i < paramNames.length; i++) System.out.println(" " + paramTypes[i].getName() + " " + paramNames[i] + " = " + paramValues[i]); // Target object upon which method is executed System.out.println(" " + enclosingJP.getTarget()); // Method annotations - attention, reflection! Method method = methodSignature.getMethod(); for (Annotation annotation: method.getAnnotations()) System.out.println(" " + annotation); }}为什么我们需要一个
ThreadLocal成员进行联接点簿记?好吧,因为显然,否则我们将在多线程应用程序中遇到问题。
现在控制台日志显示:
***** Calling method with catch block *****handler(catch(ArithmeticException)) -> java.lang.ArithmeticException: / by zero void de.scrum_master.app.Example.divideByZeroWithCatch(int, String) int dividend = 123 java.lang.String someText = Hello world! de.scrum_master.app.Example@4783da3f @de.scrum_master.app.MyAnnotation(id=11, name=John, remark=my best friend)Can not divide by zero***** Calling method without catch block *****execution(void de.scrum_master.app.Example.divideByZeroWithNoCatch()) -> java.lang.ArithmeticException: / by zeroexecution(void de.scrum_master.app.Example.main(String[])) -> java.lang.ArithmeticException: / by zeroException in thread "main" java.lang.ArithmeticException: / by zero at de.scrum_master.app.Example.divideByZeroWithNoCatch(Example.java:14) at de.scrum_master.app.Example.main(Example.java:22)
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)