Spring AOP - 从catch块调用建议 [英] Spring AOP - Invoking advice from catch block

查看:118
本文介绍了Spring AOP - 从catch块调用建议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目的:每次执行业务逻辑时发生异常,都会向管理员发送电子邮件。

Purpose: Send an email to admin every time an exception occurs while executing business logic.

直到现在我遇到了抛出建议这很好并且得到了从目标方法引发异常时执行。

Till now I have come across "throwing advice" which is fine and gets executed when an exception is raised from the target method.

这对我来说效果不错但我必须在设置请求属性和下一页方面做一些额外的处理。我认为通过使这些对象保持静态来与目标类共享对象并不是一个好主意。代码场景如下所示:

This could have worked well for me but I have to do some additional processing in terms of setting request attribute and next page. I don't think it would be a good idea to share the objects from target class with advice by making those objects static. The code scenario is shown below:

try{
   //normal processing
} catch (AuthenticationException ae) {
   ae.printStackTrace();
   req.setAttribute("msg", ae.getMessage());

   //execute advice at this point

   return loginPage;
}

请。看看我想要执行建议并相应地建议解决方案。

Pls. see the point where I want to execute the advice and suggest solution accordingly.

最好的问候

推荐答案

我知道你要避免使用完整的AspectJ而不是Spring AOP。 (顺便说一句,我想知道为什么很多人都如此害怕它。)无论如何,在AspectJ中通过处理程序()切入点。但有一个限制:它仅适用于之前的()建议,而不是之后的()周围()。这是由于编译器的限制。查看异常处理程序的JVM字节代码,您将看到无法检测处理程序块的结尾。无论如何,因为这个概念与原始问题有关,所以我想在这里展示它是如何完成的。我创建了一个小驱动程序应用程序和一个非常简单的方面:

I know you want to avoid full AspectJ as opposed to Spring AOP. (BTW, I wonder why many people are so afraid of it.) Anyway, in AspectJ is is really easy to intercept exception handler execution (=catch blocks) by means of the handler() pointcut. There is one limitation though: It only works with before() advice, not after() or around(). This is due to compiler limitations. Look at JVM byte code of exception handlers and you will see that there is no way to detect the end of a handler block. Anyway, because the concept is related to the original question, I want to show here how it is done. I have created a little driver application and a very simple aspect:

import java.util.Random;
import javax.naming.AuthenticationException;

public class Application {
    public static void main(String[] args) {
        Application app = new Application();
        System.out.println(app.foo(1, "two", 3d));
        System.out.println(app.bar("one", 2d, 3));
        System.out.println(app.zot(1d, 2, "three"));
    }

    public String foo(int i, String string, double d) {
        try {
            if (new Random().nextBoolean())
                throw new AuthenticationException("wrong password");
        }
        catch (AuthenticationException e) {
            return "return value from catch block";
        }
        return "normal return value";
    }

    public String bar(String string, double d, int i) {
        try {
            if (new Random().nextBoolean())
                throw new IllegalArgumentException("I don't like your arguments");
        }
        catch (IllegalArgumentException e) {
            return "return value from catch block";
        }
        return "normal return value";
    }

    public String zot(double d, int i, String string) {
        try {
            int n = 2/0;
        }
        catch (Throwable t) {
            return "return value from catch block";
        }
        return "normal return value";
    }
}

如您所见,方法 foo bar 根据ca中的随机值抛出异常。 50%的情况,而 zot 总是抛出除零异常。所以输出会因运行而不同。

As you can see, methods foo and bar throw exceptions based on random values in ca. 50% of all cases, whereas zot always throws a division by zero exception. So the output will differ from run to run.

那么如果所有异常都被静默吞没而不记录,我们如何才能知道发生了什么?像这样:

So how do we find out what is going on if all exceptions are silently swallowed and not logged? Like so:

import java.util.logging.Logger;

public aspect ExceptionLoggingAspect {
    final Logger log = Logger.getLogger(ExceptionLoggingAspect.class.getName());

    before(Throwable t) : handler(Throwable+) && args(t) {
        log.warning(thisJoinPointStaticPart + "  ->  " + t);
    }
}

这非常简单优雅,适用于整个应用程序。这是一些测试输出:

This is really simple and elegant and works throughout your application. Here is some test output:

Apr 6, 2013 12:15:43 PM ExceptionLoggingAspect ajc$before$ExceptionLoggingAspect$1$3d90b181
WARNING: handler(catch(AuthenticationException))  ->  javax.naming.AuthenticationException: wrong password
return value from catch block
Apr 6, 2013 12:15:43 PM ExceptionLoggingAspect ajc$before$ExceptionLoggingAspect$1$3d90b181
WARNING: handler(catch(IllegalArgumentException))  ->  java.lang.IllegalArgumentException: I don't like your arguments
return value from catch block
Apr 6, 2013 12:15:43 PM ExceptionLoggingAspect ajc$before$ExceptionLoggingAspect$1$3d90b181
WARNING: handler(catch(Throwable))  ->  java.lang.ArithmeticException: / by zero
return value from catch block

在建议中你可以做更多,例如访问这个并读取/更新一些属性,以及堡垒。

In the advice you can do more, e.g. access this and read/update some properties and so fort.

这篇关于Spring AOP - 从catch块调用建议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆