Java 为什么Spring-Around通知可以通过目标方法吞并或停止异常thown的传播?

Java 为什么Spring-Around通知可以通过目标方法吞并或停止异常thown的传播?,java,spring,spring-mvc,aop,spring-aop,Java,Spring,Spring Mvc,Aop,Spring Aop,我正在学习Spring Core认证,根据我的学习材料,我对这个问题有以下疑问: 关于通知类型和类型,以下哪项陈述是不正确的 异常处理 如果之前的通知引发异常,则不会调用目标方法 Around通知可以通过目标方法吞并或停止异常的传播 返回后的通知类型可以通过目标方法吞并或停止异常的传播 现在我知道上一个问题的正确答案是最后一个(我有答案),但为什么 所以它问我什么陈述是不正确的,这意味着前两个陈述是正确的 我试图通过一些具体的例子来分析前3个案例,但我并不认为我的推理是正确的 1) 在建议之

我正在学习Spring Core认证,根据我的学习材料,我对这个问题有以下疑问:

关于通知类型和类型,以下哪项陈述是不正确的 异常处理

  • 如果之前的通知引发异常,则不会调用目标方法

  • Around通知可以通过目标方法吞并或停止异常的传播

  • 返回后的通知类型可以通过目标方法吞并或停止异常的传播

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

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

我试图通过一些具体的例子来分析前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("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;
}
阅读官方文件后,我发现:

环绕建议:环绕连接点(如方法)的建议 调用。这是最有力的建议。围绕建议 可以在方法调用前后执行自定义行为。信息技术 还负责选择是否继续到连接点 或者通过返回其自己的方法来缩短建议方法的执行 返回值或引发异常

因此,在我看来,Around advice用于在jointpoint执行之前和之后剪切方法执行。我们可以使用它来控制建议的方法是否执行。我们还可以检查返回值并对其进行更改。这是最有力的建议,需要正确应用

因此,在前面的示例中,我认为它执行了两次:第一次是在执行getName()方法之前,第二次是在执行getName()方法之后

但是,究竟是什么呢

value = proceedingJoinPoint.proceed();
我认为这是连接点前后执行的分界点,在这种情况下,我认为procedure()方法表示必须执行getName()方法,其结果将被放入value字段。这是对的还是我遗漏了什么

回到原来的立场,我可以这么说

一个周围的建议可以吞咽或阻止病毒的传播 目标方法引发的异常


为什么我能说这是真的?具体的意思是什么?

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

从:

Around通知是使用@Around注释声明的。advice方法的第一个参数必须是ProceedingJoinPoint类型。在通知体中,对ProceedingJoinPoint调用continue()会导致底层方法执行。也可以通过传入对象[]来调用procedure方法-数组中的值将在方法执行时用作参数

因此,具体来说:
value=proceedingJoinPoint.procedure()
导致调用底层方法,并将其返回值指定给

Around通知可以通过目标方法吞并或停止异常的传播

这是通过以下方式实现的:

try {
   proceedingJoinPoint.proceed();
} catch (Throwable e) {
    // ignore or handle
}
因此,在前面的示例中,我认为它执行了两次:执行getName()方法之前的第一次,执行getName()方法之后的第二次

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


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

那么(与我的原始示例相关)你的意思是当我处理JoinPoint.Procedure()时会执行employeeAroundAdvice()方法,如果它抛出异常,我可以捕获它并处理或忽略它吗?当你调用
Procedure()
时,
Employee.getName()调用了
方法,如果您将此调用包装在一个try catch中,您可以处理或忽略它,是的。@beerbajay如果
Employee.getName()
正在捕获异常,我在
Employee.getName()
的catch块中有某种恢复机制,我们有关于
继续()的建议
使用try-catch..首先在哪里捕获?我的恢复机制会在insi中执行吗