为什么Spring Around建议可以吞下或停止目标方法抛出的异常的传播?

时间:2015-04-13 14:05:31

标签: java spring spring-mvc aop spring-aop

我正在攻读Spring Core认证,对于基于我的学习材料的这个问题,我有以下疑问:

  

以下哪些建议类型和建议不符合   异常处理?

     
      
  • 如果之前建议引发异常,则不会调用目标方法。

  •   
  • 围绕建议可以吞下或停止目标方法所引发的异常的传播。

  •   
  • AfterReturning 建议类型可以吞噬或停止目标方法所引发的异常的传播。

  •   

现在我知道上一个问题的正确答案是最后一个(我有答案),但为什么?

所以它问我什么样的陈述不正确所以这意味着前两个陈述是真的。

我试图分析之前的3个案例做一些具体的例子,但我并不认为我的推理是正确的。

1)建议之前

我可以这样:

@Aspect
public class PropertyChangeTracker {
    private Logger logger = Logger.getLogger(getClass());

    @Before(“execution(void check*(*))”)
    public void trackCheck() {
        logger.info(“Property about to check…”);
   }
}

因此,每次执行 checkSomething(oneArgument)方法时,都会执行已实现的建议(在.log文件中创建日志行)。如果在执行此方法期间抛出异常,则不会执行建议。

我认为这很清楚

2) AROUND ADVICE ,我知道这是周围建议

的序列图

enter image description here

我有以下这种建议的例子:

@Around("execution(* com.journaldev.spring.model.Employee.getName())")
public Object employeeAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
    System.out.println("Before invoking getName() method");
    Object value = null;
    try {
        value = proceedingJoinPoint.proceed();
    } catch (Throwable e) {
        e.printStackTrace();
    }
    System.out.println("After invoking getName() method. Return value="+value);
    return value;
}

阅读我发现的官方文档:

  

围绕建议:围绕连接点(例如方法)的建议   调用。这是最有力的建议。围绕建议   可以在方法调用之前和之后执行自定义行为。它   还负责选择是否继续加入点   或者通过返回自己的方法来快速建议的方法执行   返回值或抛出异常。

所以在我看来,周围建议用于在联合点执行之前和之后切断方法执行。我们可以用它来控制建议的方法是否会执行。我们还可以检查返回的值并进行更改。这是最有力的建议,需要正确应用。

所以在上一个例子中,我认为它执行了两次:第一个执行 getName()方法之前,第二个执行 getName()< / strong>方法已执行。

究竟是什么呢?
value = proceedingJoinPoint.proceed();

我认为它是联合点之前和之后的执行之间的分界点,在这种情况下我认为 proceed()方法说 getName()方法,并将其结果放入字段。是对的还是我错过了什么?

所以回到原来的陈述我可以说

  

围绕建议可以吞下或停止传播   目标方法所引发的异常。

为什么我能说这是真的?什么是繁琐的意思?

2 个答案:

答案 0 :(得分:6)

  

所以在前面的例子中我认为它执行了两次:第一个执行getName()方法之前执行,第二个执行getName()方法之后执行。

如果我理解你的想法,那你错了。该建议只被调用一次,其中的代码负责调用实际的建议方法getName()。这就是proceedingJoinPoint.proceed()所做的。

一个典型的场景 - 你拦截方法调用,执行一些检查,调用方法(或不,可能取决于检查的结果),并返回结果。在您发布的示例中,proceed()try - catch块包围,这意味着您可以捕获getName()抛出的异常并随意执行任何操作。这就解释了为什么你问题中的第二句是真的。

答案 1 :(得分:5)

使用@Around就像编写自己的代码并调用方法一样,除了您使用proceedingJoinPoint.proceed()之外。与普通方法调用一样,您可以选择不执行它(将其包装在条件中)或捕获它抛出的错误(将调用包装在try块中)。

来自spring documentation

  

使用@Around注释声明around建议。 advice方法的第一个参数必须是ProceedingJoinPoint类型。在通知的主体内,在ProceedingJoinPoint上调用proceed()会导致执行基础方法。 proceed方法也可以被称为传入Object [] - 数组中的值将在进行时用作方法执行的参数。

因此,具体来说:value = proceedingJoinPoint.proceed();会导致调用基础方法,并将其返回值分配给value

  

周围的建议可以吞噬或停止目标方法所引发的异常的传播。

这可以通过以下方式实现:

try {
   proceedingJoinPoint.proceed();
} catch (Exception e) {
    // ignore or handle
}