Warm tip: This article is reproduced from serverfault.com, please click

aop-如何使用Aspectj捕获和抑制Java类抛出的异常

(aop - How to catch and suppress an Exception Thrown from a Java Class using Aspectj)

发布于 2020-12-18 14:18:59

我想处理Circle.getArea()使用Aspectj方法抛出的异常

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

解决


    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文件。

Questioner
Janith Bandara
Viewed
11
dreamcrash 2020-12-18 22:55:38

你需要使用around 建议的,而不是

     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 咨询截取一个给定的连接点,并能注入新的行为,和而不是连接点proceed是一个特殊的功能,允许around 建议继续的执行joinpoint

从的类型的建议通过的AspectJ支持( beforeafteraround),该around 建议是唯一一个允许返回的值和/或使用proceed这样一来,around 建议就可以多次执行相同的联接点,或者根本不执行该联接点此外,你甚至可以在不同的上下文中执行拦截的连接点例如,更改方法参数的值)。

可以在此SO Thread上找到有关建议和进行工作的更多信息

我们的around 建议将拦截类中方法的所有执行连接点Circle,并相应地处理这些方法引发的异常。