当前位置: 首页 > 知识库问答 >
问题:

围绕外部库重写方法的AOP?

越风史
2023-03-14

我正在为以下问题寻找一个切实可行的解决方案:

  • 外部库提供组件作为基类。
  • 通过扩展这些基类生成自定义组件。
  • 当实现引发未处理的异常时,基类将中断。
  • 基类源代码不可用。只有二进制jar。

有人知道如何用AspectJ做这个吗?

共有1个答案

谭泳
2023-03-14

假设外部库类/接口位于某个包中,如org.external.library或其任何子包中,您可以将这些类/接口用AspectJ语法表示为org.external.library..*+..表示“包括子包”,*表示“所有类”,+表示“包括子类”。现在追加.*(..),就可以获得所有方法,而不管这些类的名称和参数的数量如何。

现在,例如,切入点

execution(!static * org.external.library..*+.*(..))

拦截任何库子类中的所有非静态方法,而不考虑返回类型。

库类/接口:

package org.external.library;

public abstract class AbstractBase {
    public abstract String getText();
    public abstract int getNumber();
    public abstract void doSomething();
}
package org.external.library;

public interface Service {
    void start();
    void stop();
    boolean isRunning();
}

不扩展任何库类的类:

正如您所看到的,出于演示目的,该类在50%的情况下随机抛出运行时异常。我们希望它们不会被我们的方面处理。

package de.scrum_master.app;

import java.util.Random;

public class MyOwnClass {
    private static final Random RANDOM = new Random();

    public String getGreeting(String recipient) {
        if (RANDOM.nextBoolean())
            throw new RuntimeException("cannot get greeting for '" + recipient + "'");
        return "Hello " + recipient + "!";
    }
}
package de.scrum_master.app;

import java.util.Random;

import org.external.library.Service;

public class FooService implements Service {
    private static final Random RANDOM = new Random();
    private boolean isRunning;

    @Override
    public void start() {
        if (RANDOM.nextBoolean())
            throw new RuntimeException("cannot start");
        isRunning = true;
    }

    @Override
    public void stop() {
        if (RANDOM.nextBoolean())
            throw new RuntimeException("cannot stop");
        isRunning = false;
    }

    @Override
    public boolean isRunning() {
        return isRunning;
    }

    public void pause() {
        if (RANDOM.nextBoolean())
            throw new RuntimeException("cannot pause");
        isRunning = false;
    }

    public void resume() {
        if (RANDOM.nextBoolean())
            throw new RuntimeException("cannot resume");
        isRunning = true;
    }
}
package de.scrum_master.app;

import java.util.Random;

import org.external.library.AbstractBase;

public class Application extends AbstractBase {
    private static final Random RANDOM = new Random();

    @Override
    public String getText() {
        if (RANDOM.nextBoolean())
            throw new RuntimeException("cannot get text");
        return "Hello world!";
    }

    @Override
    public int getNumber() {
        if (RANDOM.nextBoolean())
            throw new RuntimeException("cannot get number");
        return RANDOM.nextInt(10);
    }

    @Override
    public void doSomething() {
        if (RANDOM.nextBoolean())
            throw new RuntimeException("cannot do something");
    }

    public void doSomethingElse() {
        if (RANDOM.nextBoolean())
            throw new RuntimeException("cannot do something else");
    }

    public static void main(String[] args) {
        Application application = new Application();
        FooService fooService = new FooService();
        MyOwnClass myOwnClass = new MyOwnClass();
        for (int i = 0; i < 5; i++) {
            application.getText();
            application.getNumber();
            application.doSomething();
            application.doSomethingElse();
            fooService.start();
            fooService.pause();
            fooService.isRunning();
            fooService.resume();
            fooService.isRunning();
            fooService.stop();
            try {
                myOwnClass.getGreeting("world");
                myOwnClass.getGreeting("guys");
            }
            catch (Exception e) {
                System.out.println("Uncaught by aspect: " + e);
            }
        }
    }
}
package de.scrum_master.aspect;

public aspect ErrorHandler {
    Object around() : execution(!static * org.external.library..*+.*(..)) {
        try {
            return proceed();
        }
        catch (Exception e) {
            System.out.println(thisJoinPoint + " -> " + e);
            return null;
        }
    }
}

由于代码中的随机化,每次运行应用程序时,输出看起来都有点不同:

execution(int de.scrum_master.app.Application.getNumber()) -> java.lang.RuntimeException: cannot get number
execution(void de.scrum_master.app.Application.doSomething()) -> java.lang.RuntimeException: cannot do something
execution(void de.scrum_master.app.Application.doSomethingElse()) -> java.lang.RuntimeException: cannot do something else
execution(void de.scrum_master.app.FooService.start()) -> java.lang.RuntimeException: cannot start
execution(void de.scrum_master.app.FooService.pause()) -> java.lang.RuntimeException: cannot pause
execution(void de.scrum_master.app.FooService.resume()) -> java.lang.RuntimeException: cannot resume
execution(void de.scrum_master.app.FooService.stop()) -> java.lang.RuntimeException: cannot stop
Uncaught by aspect: java.lang.RuntimeException: cannot get greeting for 'world'
execution(String de.scrum_master.app.Application.getText()) -> java.lang.RuntimeException: cannot get text
execution(int de.scrum_master.app.Application.getNumber()) -> java.lang.RuntimeException: cannot get number
execution(void de.scrum_master.app.Application.doSomething()) -> java.lang.RuntimeException: cannot do something
execution(void de.scrum_master.app.FooService.start()) -> java.lang.RuntimeException: cannot start
execution(void de.scrum_master.app.FooService.pause()) -> java.lang.RuntimeException: cannot pause
execution(void de.scrum_master.app.FooService.stop()) -> java.lang.RuntimeException: cannot stop
Uncaught by aspect: java.lang.RuntimeException: cannot get greeting for 'guys'
execution(void de.scrum_master.app.Application.doSomething()) -> java.lang.RuntimeException: cannot do something
execution(void de.scrum_master.app.FooService.start()) -> java.lang.RuntimeException: cannot start
execution(void de.scrum_master.app.FooService.pause()) -> java.lang.RuntimeException: cannot pause
Uncaught by aspect: java.lang.RuntimeException: cannot get greeting for 'guys'
execution(void de.scrum_master.app.Application.doSomethingElse()) -> java.lang.RuntimeException: cannot do something else
execution(void de.scrum_master.app.FooService.resume()) -> java.lang.RuntimeException: cannot resume
execution(void de.scrum_master.app.FooService.stop()) -> java.lang.RuntimeException: cannot stop
Uncaught by aspect: java.lang.RuntimeException: cannot get greeting for 'world'
execution(String de.scrum_master.app.Application.getText()) -> java.lang.RuntimeException: cannot get text
execution(int de.scrum_master.app.Application.getNumber()) -> java.lang.RuntimeException: cannot get number
execution(void de.scrum_master.app.Application.doSomething()) -> java.lang.RuntimeException: cannot do something
execution(void de.scrum_master.app.Application.doSomethingElse()) -> java.lang.RuntimeException: cannot do something else
execution(void de.scrum_master.app.FooService.start()) -> java.lang.RuntimeException: cannot start
execution(void de.scrum_master.app.FooService.pause()) -> java.lang.RuntimeException: cannot pause
execution(void de.scrum_master.app.FooService.stop()) -> java.lang.RuntimeException: cannot stop
 类似资料:
  • 我想抑制特定异常的堆栈跟踪:org。每件事。json。模式。验证异常。 这个特殊的异常在我们的应用程序中引发了很多,我想限制性能的影响。 我试着用我自己的扩展: 但是当我抓住了抑制验证时,验证异常就消失了。有没有办法实现我想做的?

  • 所以我试图实现类似于Kotlin协程的东西在Java 目前,我试图拦截方法时,一个方法调用Waitable.waitFor()调用和所有的方法主体后,Waitable.waitFor()应调度 但在我当前的代码中,它只拦截方法调用,之后的方法体不包括在内 所以我想知道我的切入点表达式代码是错的吗?或者有什么更好的方法来实现这一点?

  • 我正在使用IBM Watson服务,并通过maven依赖项导入了该库。 我认为一切都很顺利,因为所有的类都显示在外部库部分: 实例化类很好,但如果我尝试使用这些类中的方法,Intellij说“无法解析符号‘methodname’”。 我已经尝试了无效缓存操作,并尝试了其他可以在互联网上找到的技巧,但没有任何效果。。。我做错了什么?我是否必须勾选任何选项,以便Intellij找到方法?

  • 有什么建议吗?它不工作在模拟器或当我在我的手机上运行它。

  • subA类是A类的子类。我试图重写一个方法,但不知怎的,它不允许我重写它。为什么会这样?是因为参数中的参数吗? 读取错误消息: 名称冲突:subA中的add(E#1)和A中的add(E#2)具有相同的擦除,但两者都不重写另一个,其中E#1、E#2是类型变量: E#1扩展了subA类中声明的对象 E#2扩展了A类中声明的对象 超类A: 子类subA:

  • 我试图实现的是重写此方法: 公共布尔onKeyPreIme(int-keyCode,KeyEvent事件) 该方法位于SearchView中。搜索自动完成类http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.0_r1/android/support/v7/widget/Se