AspectJ——切入点语法之捕获异常处理上的连接点

Posted KLeonard

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AspectJ——切入点语法之捕获异常处理上的连接点相关的知识,希望对你有一定的参考价值。

捕获异常处理上的连接点

在Java中抛出异常时,会将其向上传递给调用链,直到它被try/catch块中的catch语句处理,或者它到达Java运行库并在控制台上引发一条出错的消息。如果捕获到Java异常,就会把该异常作为一个对象传递给相应的catch语句,在其中处理该异常。

使用切面可以捕获异常的处理,其应用的场景可以是:除了catch块的正常异常处理行为之外,使用切面还需要做某些事情;或者干脆使用切面代替catch块的正常行为。

0.捕获特定异常的处理

假设你想捕获程序对特定异常的处理。AspectJ提供了handler(异常类)切入点来实现这一功能。它的语法是:

pointcut [切入点名字](参数列表): handler(异常类);

需要注意的几点是:

  • hander(异常类)捕获的连接点是catch语句。也就是在程序捕捉异常的地方捕获连接点,而不是在引发异常的地方。
  • 此处的异常类为Throwable及其子类。
  • handler(异常类)只能使用before()指定前置通知,不支持其他形式的通知。
  • 此处的异常类也可以使用通配符,用于选择不同类上的一系列连接点。

下表表示了异常类使用通配符的示例:

带有通配符的异常类描述
mypackage..*捕获mypackage包及其子包中的类的连接点
MyClass+捕获MyClass类及其任何子类中的连接点

我们在Test5包下做一个简单的测试。

首先我们自定义异常MyException,使其继承自Exception,内容可以为空。

package Test5;

public class MyException extends Exception 

接着,我们创建业务类Service,并在其中定义test方法,在该方法中,我们抛出自定义的MyException异常,并且使用try/catch语句来捕获。

package Test5;

public class Service 
    private String name;

    public Service(String name) 
        this.name = name;
    

    public void test()
        try 
            throw new MyException();
         catch (MyException e) 
            System.out.println("MyException Catch 处理语句...");
        
    

    @Override
    public String toString() 
        return "Service" +
                "name='" + name + '\\'' +
                '';
    

接着,我们定义主方法来测试,如下Main类。

package Test5;

public class Main 
    public static void main(String[] args) 
        Service service = new Service("Gavin");
        service.test();
    

如果此时不添加切面,其运行效果是这样的:

接着我们添加HandlerAspect切面。如下:

package Test5;

public aspect HandlerAspect 
    pointcut handlerPointcut(): handler(MyException);

    before(): handlerPointcut()
        System.out.println("MyException 切面处理...");
        System.out.println("Signature: " + thisJoinPoint.getSignature());
        System.out.println("Source Line: " + thisJoinPoint.getSourceLocation());
    

可以看到,我们在切面中定义了切入点,名字为handlerPointcut,使用handler(MyException)切入点语法,该切入点捕获对MyException异常的处理。我们对该切入点织入了前置通知,在通知中,我们打印了连接点的Signature和连接点在源代码中的位置。

此时的运行结果如下:

通过上面的介绍,我们知道handler(异常类)也可以使用通配符,所以下述写法对于本示例来说也是可以的:

pointcut handlerPointcut(): handler(Exception+);

或者:

pointcut handlerPointcut(): handler(Test5..*);

1.捕获异常对象

在捕获方法调用连接点时,我们可以使用args原生切入点来捕获方法传入的参数,同样的,在捕获异常处理连接点时,我们也可以通过使用args原生切入点来捕获异常对象。

比如,在上例中,我们可以在切面中获取MyException异常对象。此时,要对切面做如下的修改:

package Test5;

public aspect HandlerAspect 
    pointcut handlerPointcut(MyException e): handler(MyException) && args(e);

    before(MyException e): handlerPointcut(e)
        System.out.println("MyException 切面处理...");
        System.out.println("Signature: " + thisJoinPoint.getSignature());
        System.out.println("Source Line: " + thisJoinPoint.getSourceLocation());

        e.printStackTrace();
    

如代码所示,我们在切入点添加参数MyException e,并通过args(e)获取了该异常对象。在通知中,我们使用e.printStackTrace()打印出了异常信息。

运行结果如下:

2.捕获处理异常的对象

同样的,我们可以结合使用handler(异常类)this原生切入点,来获取处理异常的对象。

我们在上例的基础上添加this原生切入点,如下:

package Test5;

public aspect HandlerAspect 
    pointcut handlerPointcut(MyException e, Service service): handler(MyException) && args(e) && this(service);

    before(MyException e, Service service): handlerPointcut(e, service)
        System.out.println("MyException 切面处理...");
        System.out.println("Signature: " + thisJoinPoint.getSignature());
        System.out.println("Source Line: " + thisJoinPoint.getSourceLocation());

        System.out.println(service);
        e.printStackTrace();
    

在该切面中,我们不仅获取了MyException异常对象,也获取了处理异常的对象。

运行结果如下:

以上是关于AspectJ——切入点语法之捕获异常处理上的连接点的主要内容,如果未能解决你的问题,请参考以下文章

AspectJ——切入点语法之捕获属性上的连接点

AspectJ——切入点语法之捕获方法上的连接点

AspectJ——切入点语法之捕获类和对象构造上的连接点

AspectJ——切入点语法之捕获类和对象构造上的连接点

AspectJ——切入点语法之cflow与cflowbelow

AspectJ——切入点语法之cflow与cflowbelow