AspectJ:我可以中和“扔”吗? (用log替换)并继续该方法

发布于 2024-11-30 21:19:55 字数 478 浏览 1 评论 0原文

在下面的代码中,我想中和抛出并继续该方法 - 可以做到吗?

public class TestChild extends TestParent{

private String s; 

public void doit(String arg) throws Exception {

    if(arg == null) {
        Exception e  = new Exception("exception");

        throw e;
    }
    s=arg;
}

最终

结果应该是,在触发异常的情况下 (arg == null)

  1. throw e 被 Log(e) 替换
  2. s=arg 被执行

谢谢

PS:我可以“吞掉”异常或用另一个异常替换它但在所有情况下,该方法都不会继续,我的所有干预都是在损害发生时发生的(即抛出异常)

In below code I want to neutralize the throw and continue the method - Can it be done ?

public class TestChild extends TestParent{

private String s; 

public void doit(String arg) throws Exception {

    if(arg == null) {
        Exception e  = new Exception("exception");

        throw e;
    }
    s=arg;
}

}

The net result should be that, in case of the exception triggered (arg == null)

  1. throw e is replaced by Log(e)
  2. s=arg is executed

Thanks

PS : I can 'swallow' the exception or replace it with another exception but in all cases the method does not continue, all my interventions take place when the harm is done (ie the exception has been thrown)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冷月断魂刀 2024-12-07 21:19:55

我强烈怀疑是否存在通用解决方案。但对于您的特定代码和要求 1 和 2:

privileged public aspect SkipNullBlockAspect {


public pointcut needSkip(TestChild t1, String a1): execution(void TestChild.doit(String)) 
    && this(t1) && args(a1) ;


void around(TestChild t1, String a1): needSkip(t1, a1){             
    if(a1==null) //if argument is null - doing hack.
    {
        a1="";      //alter argument to skip if block.  
        proceed(t1, a1);

        t1.s=null;
        a1=null;    //restore argument
        System.out.println("Little hack.");
    }
    else
        proceed(t1, a1);    

}

}

I strongly doubt that general solution exists. But for your particular code and requirements 1 and 2:

privileged public aspect SkipNullBlockAspect {


public pointcut needSkip(TestChild t1, String a1): execution(void TestChild.doit(String)) 
    && this(t1) && args(a1) ;


void around(TestChild t1, String a1): needSkip(t1, a1){             
    if(a1==null) //if argument is null - doing hack.
    {
        a1="";      //alter argument to skip if block.  
        proceed(t1, a1);

        t1.s=null;
        a1=null;    //restore argument
        System.out.println("Little hack.");
    }
    else
        proceed(t1, a1);    

}

}

幸福%小乖 2024-12-07 21:19:55

我认为,在大多数情况下,您想要的通常没有意义,因为如果应用程序抛出异常,它就有理由这样做,并且该原因几乎总是包括不继续正常控制流的意图由于虚假数据可能导致后续错误而引发异常的方法。例如,如果您可以中和代码中的 throw,并且下一行代码将执行如下操作:

if(arg == null)
    throw new Exception("exception");

// We magically neutralise the exception and are here with arg == null

arg.someMethod();                         // NullPointerException
double x = 11.0 / Integer.parseInt(arg);  // NumberFormatException
anotherMethod(arg);                       // might throw exception if arg == null

您明白我的意思了吗?假设你可以,继续在这里控制流程,你会冒不可估量的风险。现在有什么替代方案?

  • 让我们假设您确切地知道null 值在这里不会造成任何损害。那么为什么不直接用 after() throwing 建议捕获异常呢?
  • 或者,如果 null 有害并且您知道这一点,为什么不拦截方法执行并覆盖参数以避免异常呢?
  • 推测性地假设方法内容对您来说是一个黑匣子,并且您试图在这里做一些黑客的事情,您可以使用 around() 建议并从那里调用 proceed() 使用不同的参数值(例如某些身份验证令牌或密码)多次,直到被调用的方法不再抛出异常。

正如您所看到的,有很多方法可以解决您的实际问题,具体取决于问题的具体内容以及您想要实现的目标。

说了这么多,现在让我们回到最初的技术问题,即不捕获,但实际上中和异常,即以某种方式避免它的存在根本就扔了。因为 AspectJ 语言不包含执行您想要的操作的技术手段(感谢上帝!),所以您可以查看其他可以以更底层的方式操作 Java 类文件的工具。我从未有效地使用过它们,但我很确定您可以使用 BCELJavassist

I think that generally what you want makes no sense most cases because if an application throws an exception it has a reason to do so, and that reason almost always includes the intention not to continue with the normal control flow of the method where the exception was thrown due to possible subsequent errors caused by bogus data. For example, what if you could neutralise the throw in your code and the next lines of code would do something like this:

if(arg == null)
    throw new Exception("exception");

// We magically neutralise the exception and are here with arg == null

arg.someMethod();                         // NullPointerException
double x = 11.0 / Integer.parseInt(arg);  // NumberFormatException
anotherMethod(arg);                       // might throw exception if arg == null

Do you get my point? You take incalculable risks by continuing control flow here, assuming you can at all. Now what are the alternatives?

  • Let us assume you know exactly that a value of null does not do any harm here. Then why not just catch the exception with an after() throwing advice?
  • Or if null is harmful and you know about it, why not intercept method execution and overwrite the parameter so as to avoid the exception to begin with?
  • Speculatively assuming that the method content is a black box to you and you are trying to do some hacky things here, you can use an around() advice and from there call proceed() multiple times with different argument values (e.g. some authentication token or password) until the called method does not throw an exception anymore.

As you see, there are many ways to solve your practical problem depending on what exactly the problem is and what you want to achieve.

Having said all this, now let us return to your initial technical question of not catching, but actually neutralising an exception, i.e. somehow avoiding its being thrown at all. Because the AspectJ language does not contain technical means to do what you want (thank God!), you can look at other tools which can manipulate Java class files in a more low-level fashion. I have never used them productively, but I am pretty sure that you can do what you want using BCEL or Javassist.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文