Spring AOP的 - 从catch块调用意见(Spring AOP - Invoking ad

2019-07-21 20:49发布

用途:发送电子邮件至管理员每次在执行业务逻辑发生异常的时间。

到目前为止我所遇到的这是很好的,当异常是从目标方法提出了被执行“扔意见”。

这可能工作很适合我,但我必须做一些额外的处理设置请求属性和下页的条款。 我不认为这将是通过使这些对象的静态与建议分享目标类的对象是个好主意。 该代码方案如下所示:

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

   //execute advice at this point

   return loginPage;
}

PLS。 看到这一点,我想执行的建议,并提出相应的解决方案。

最好的祝福

Answer 1:

我知道你想避免完整的AspectJ,而不是Spring AOP的。 (顺便说一句,我不知道为什么很多人都这么害怕它。)总之,在AspectJ是真的很容易就可以截获异常处理程序执行(= catch块)由的方式handler()切入点。 有一个限制,但:它只能与工程before()的建议,而不是after()around() 这是由于编译器的限制。 看看异常处理程序的JVM字节代码,你会看到,有没有方法来检测处理程序块的结束。 无论如何,因为这个概念是与原来的问题,我想表明它是在这里怎么做。 我创建了一个小驱动程序的应用程序和一个非常简单的方面:

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";
    }
}

正如你所看到的,方法foobar基于在约随机值抛出异常 所有病例的50%,而zot总是零异常抛出一个部门。 所以输出将运行不同运行。

那么,我们如何找出到底是怎么回事,如果所有异常被默默吞咽并没有登录? 像这样:

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);
    }
}

这是非常简单和优雅,在整个应用程序的工作原理。 下面是一些测试的输出:

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

在建议你可以做更多,如访问this和读/更新一些属性等炮台。



Answer 2:

好了,通过在行动参考书像春天去后,我才知道,也没有办法,使我们可以在我们的Java代码中的任意点调用春建议。 春天在行动书建议看看AspectJ的对点切口精细控制。

为了避免增加AspectJ中,我遇到了以下解决方案,可以帮助别人,节省了宝贵的时间:

1)您希望只在发生异常时调用咨询方法使用一个环绕通知。 就像在我的情况,我想发生异常时发送电子邮件通知,我们走出catch块。 基本上,我想调用意见之前,做在catch块一些处理。

2)当使用环绕通知,就可以读出目标对象的成员变量的方法参数。 如果你想与建议分享一些数据,它也是方式之一。 在我的情况,我想约邮件主题和正文目标对象的详细信息。

代码周边的建议:

import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;

public class NotificationAdvice implements AfterReturningAdvice  {
    public void afterReturning(Object returnValue, Method method,
            Object[] args, Object target) throws Throwable {
            System.out.println(returnValue);
            System.out.println(method.getName());
            System.out.println(args[0]);
            System.out.println(((target)target).flag);
    }
}

请介绍这一做法的反馈/查询。



Answer 3:

AFAIK有对此没有切入点表达式...

你应该考虑配置您的记录,做你所需要的。 替换ae.printStackTrace(); 通过类似logger.warn(ae)打印踪迹控制台是相当不好的做法反正),并配置测井仪器的电子邮件发送追加程序,例如一个Log4j的或的logback的 SMTPAppender。 此外,为了让您的配置更容易,您可以使用业务专用记录器。

如果你真的想在这里使用方面,我认为你必须期待您的所有业务异常冒泡至少一种方法,以便使用afterThrowing建议。



Answer 4:

至于我的理解说,为什么在的AuthenticationException业务逻辑层抛出代码。如果真的要使用AOP的横切关注点至今保持URS的业务代码。 在你的情况下,你可以从企业拿出的AuthenticationException代码logic.Before进入商业逻辑运算应用aop.for例子

public class SecurityInterceptor extends HandlerInterceptorAdapter{



    //before the actual handler will be executed
    public boolean preHandle(HttpServletRequest request, 
        HttpServletResponse response, Object handler)
        throws Exception {


        // check here possible case for exception from request .If exception throw yours custom exception before executing business logic


    }

    //after the handler is executed
    public void postHandle(

        }
    }
}

自定义异常

public class Handler
        implements HandlerExceptionResolver
    {

        public Handler()
        {
        }

        public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
        {
            if(ex instanceof AuthenticationException))
            {
                 ModelAndView test = new ModelAndView("errorpage1jsppage");
return test;
            } else
            if(ex instanceof ErrorType2Exception))
            {
                 ModelAndView test1 = new ModelAndView("errorpage2jsppage");
return test1
            }
        }
    }


文章来源: Spring AOP - Invoking advice from catch block