【问题标题】:Can I intercept null pointer exceptions in a method using Spring AOP?我可以在使用 Spring AOP 的方法中拦截空指针异常吗?
【发布时间】:2012-02-09 21:53:22
【问题描述】:

我们有一堆 pdf 报告类,在大量导入存档数据后,它们开始偶尔在数据位丢失时抛出空指针异常,例如thing.getOtherThing().getText(); 将没有 OtherThing 并且报告将失败。

在我看来,我们有几个选择

  1. 修复数据 - 不太清楚每种情况下的数据应该是什么,在某些情况下是人为判断的问题
  2. 将 try/catch 放在任何地方并重新抛出一个有用的异常以向用户冒泡 - 大量的工作和丑陋的代码,但对用户很有用
  3. 到处都放空检查 - 不用了,谢谢
  4. 处理 DAO 代码以在查询中执行合并/nvl 并在缺少的字段(或银行)中生成不适用的报告 - 好的,但没那么有用

或者……我们可以在这里用 AOP 做点什么吗?是否可以拦截某些类/方法中抛出的空指针?当这些被截获时,可以获得什么级别的信息?请记住,方法中的多个位置可能会抛出空指针:(

谢谢。

【问题讨论】:

  • AOP 就像魔法一样。关注此链接stackoverflow.com/questions/7637512/…
  • 注意——除非thing是一个spring bean,否则你需要使用aspectj compile-或load-time-weaving(不是Spring AOP代理)。不一定赞同你的解决方案,只是说。

标签: java spring spring-aop


【解决方案1】:

呃……这可能会很痛苦,但我真诚地建议你仔细检查你的代码并在任何合理的地方检查 null,为自己构建一个实用程序类,这样你就可以执行类似的操作

MyUtilityHelper.checkNotNull (toCheck, elegantMessage)

并让该方法抛出一些你可以获得更多信息的东西。

AOP 在这里真的不适用恕我直言,你不想使用应该用顺序逻辑完成的 AOP 东西,只是因为代码更适合顺序处理......当你想添加 AOP水平的功能层,例如安全性、日志记录...

【讨论】:

  • 易于添加,易于删除......而且我不是这样做的:)
  • 如何处理异常而不是水平功能?对我来说,特别是以描述的方式抛出 NPE 听起来很水平。
【解决方案2】:

AOP 可能会帮助您找到解决方案,但您需要在引发异常之前采取措施,因为异常会导致您丢失太多执行上下文。首先,当您编写 thing.getOtherThing.getText() 时,getOtherThing 是一个名称奇怪的字段或您不小心省略了括号的方法调用?如果是后者,可以使用Spring AOP拦截方法(提供thing其实是个bean)。如果没有,您将需要完整的 AspectJ,因为 Spring AOP 不进行字段访问拦截(因为它是如何实现的)。

这个想法是你使用@Around 来定义切入点并有这样的建议:

static final OtherThing THE_DEFAULT_VALUE = ...;

@Around("execution(* getOtherThing())")
public Object supplyDefault(ProceedingJoinPoint pjp) throws Throwable {
    Object result = pjp.proceed();
    if (result == null)
        result = THE_DEFAULT_VALUE;
    return result;
}

或者,使用 AspectJ(未经测试;我实际上没有将 AspectJ 用于任何事情):

aspect ADefaultOtherThing {
    static final OtherThing THE_DEFAULT_VALUE = ...;

    OtherThing around(): get(OtherThing getOtherThing) {
        OtherThing result = proceed();
        if (result == null)
            result = THE_DEFAULT_VALUE;
        return result;
    }
}

不过,我怀疑这是否是 AOP 的一个特别好的用途。当然,将这样的业务逻辑直接放在代码中会更好吗?保证一个字段永远不会是null 似乎是一个很好的不变量。

【讨论】:

  • 请记住,SpringAOP 示例用于方法调用,AspectJ 示例用于字段访问。
  • 我错误地省略了方法名称中的括号。
  • 然后使用 SpringAOP 的“around”通知就可以了。您只需要弄清楚这是否是一个好主意,或者业务对象是否应该明确地必须永远不返回 null。
  • 至于业务逻辑-现在是业务逻辑-新字段不能为空,但是已经导入了大量没有此要求的旧存档数据-我们需要拦截并通知用户。不过我怀疑我们会使用 AOP。
  • 另一方面,如果我们使用空检查,那么一旦数据被清理,我们的报告代码中就会有一堆无用的空检查。 AOP 会更容易删除。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-07
  • 1970-01-01
  • 2014-04-06
  • 2013-08-10
  • 1970-01-01
相关资源
最近更新 更多