如何使用 Aspectj 捕获和抑制 Java 类抛出的异常
Posted
技术标签:
【中文标题】如何使用 Aspectj 捕获和抑制 Java 类抛出的异常【英文标题】:How to catch and suppress an Exception Thrown from a Java Class using Aspectj 【发布时间】:2020-12-18 14:18:59 【问题描述】:我想使用 Aspectj 处理从 Circle.getArea()
方法抛出的异常。
Shape.java
package Shapes;
public class Circle
private double radius;
public Circle(double radius)
this.radius = radius;
public double getPerimeter()
return 2 * Math.PI * this.radius;
public double getArea()
return Math.PI * this.radius * this.radius;
Rectangle.java
package Shapes;
public class Rectangle
private double width, height;
public Rectangle(double width, double height)
this.width = width;
this.height = height;
public double getPerimeter()
return 2 * (this.width + this.height);
public double getArea()
return this.width * this.height;
Circle.java
package Shapes;
public class Circle
private double radius;
public Circle(double radius)
this.radius = radius;
public double getPerimeter()
return 2 * Math.PI * this.radius;
public double getArea()
throw new RuntimeException("Oops, I don't know how to calculate this :(");
Main.java
package Shapes;
public class Main
public static void main(String[] args)
try
Shape s;
s = (Shape) new Rectangle(2, 10);
System.out.println("The area of " + s + " is " + s.getArea());
s = (Shape) new Rectangle(-2, 10);
System.out.println("The perimeter of " + s +" is " + s.getPerimeter());
s = (Shape) new Circle(-2);
System.out.println("The perimeter of " + s +" is " + s.getPerimeter());
s = (Shape) new Circle(2);
System.out.println("The area of " + s + " is " + s.getArea());
catch(Exception e)
System.out.println("Error: " + e.getMessage());
解决.aj
package Shapes;
privileged public aspect Resolve
declare parents: Rectangle implements Shape;
declare parents: Circle implements Shape;
public String Rectangle.getName()
return "Rectangle";
public String Circle.getName()
return "Circle";
public String Rectangle.toString()
return this.getName()+"("+this.width+","+this.height+")";
public String Circle.toString()
return this.getName()+"("+this.radius+")";
after() throwing(RuntimeException e) : execution(* Circle.*())
handleException();
protected void handleException()
System.out.println("Error detected");
当前输出为:
The area of Rectangle(2.0,10.0) is 20.0
The perimeter of Rectangle(-2.0,10.0) is 16.0
The perimeter of Circle(-2.0) is -12.566370614359172
Error detected
Error: Oops, I don't know how to calculate this :(
我想避免打印“错误:糟糕,我不知道如何计算这个:(”,我需要在最后得到圆形对象的实际面积。 但是,我无法更改任何 .java 文件。所有更改都应使用 Resolve.aj 文件。
【问题讨论】:
【参考方案1】:你需要使用around
advice而不是after:
Object around () : execution(* Circle.*())
try
return proceed();
catch(Exception e)
handleException();
return null;
代码输出:
The area of Rectangle(2.0,10.0) is 20.0
The perimeter of Rectangle(-2.0,10.0) is 16.0
The perimeter of Circle(-2.0) is -12.566370614359172
Error detected
The area of Circle(2.0) is 0.0
为什么我们使用 around 建议而不是 after?
非常非正式地,around
advice 拦截给定的 joinpoint,并且可以注入新的行为之前 , after, 而不是那个joinpoint。 proceed
是一个特殊的功能,它允许around
建议继续执行joinpoint
。
根据 AspectJ 支持的 advice 类型(即 before
、after
和 around
),around
advice 是唯一允许返回 值和/或使用proceed
的方法。这使得around
advice 可以多次执行相同的joinpoint,或者根本不执行它。此外,您甚至可以使用不同的上下文执行截获的 joinpoint(例如,更改方法参数的值)。
有关建议和继续工作的更多信息,请访问this SO Thread。
我们的around
advice 将拦截Circle
类中方法的所有执行joinpoint,并相应地处理这些方法抛出的异常。
【讨论】:
以上是关于如何使用 Aspectj 捕获和抑制 Java 类抛出的异常的主要内容,如果未能解决你的问题,请参考以下文章