为什么“ Spring Around”建议可以吞噬或阻止目标方法抛出的异常的传播?] >

问题描述 投票:4回答:2

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

以下陈述中关于建议类型和异常处理?

  • 如果Before

    通知抛出异常,将不会调用目标方法。
  • Around

  • 建议可以吞噬或阻止目标方法抛出的异常的传播。
  • 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

,我知道这是Around建议的顺序图

<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS9pWWNSOS5qcGcifQ==” alt =“在此处输入图像描述”>

并且我有以下此类建议的示例:

@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建议

:围绕连接点的建议,例如方法调用。这是最有力的建议。围绕建议可以在方法调用之前和之后执行自定义行为。它还负责选择是否继续进行连接点或通过返回自己建议的方法来捷径建议的方法执行返回值或引发异常。

所以在我看来,周围建议

用于减少联合执行之前和之后的方法执行。我们可以使用它来控制建议的方法是否执行。我们还可以检查返回的值并进行更改。这是最有力的建议,需要正确应用。

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

方法之后。

但是到底有什么用呢?>

value = proceedingJoinPoint.proceed();

我认为这是连接点之前和之后的执行之间的分界点,在这种情况下,我认为proceed()

方法表示必须执行getName()方法并将其结果放入value
字段中。是对的还是我错过了什么?

所以回到原始陈述我可以说

[建议可能会吞噬或阻止传播目标方法抛出的异常。

为什么我可以说这是真的?究竟是什么意思?

我正在学习Spring Core认证,并且对基于我的学习资料的这个问题有以下疑问:关于建议类型和...,下列哪个陈述不正确?]

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

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

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

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

spring documentation

Around建议使用@Around注释声明。咨询方法的第一个参数必须是ProceedingJoinPoint类型。在建议的正文中,在ProceedingJoinPoint上调用proce()会使基础方法执行。可以将proced方法也称为传递Object []-进行时,数组中的值将用作方法执行的参数。

因此,特别是:value = proceedingJoinPoint.proceed();导致调用基础方法并将其返回值分配给value

环绕通知可以吞噬或阻止目标方法抛出的异常的传播。

这是通过做的:

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

java spring spring-mvc aop spring-aop
2个回答
6
投票
因此,在前面的示例中,我认为它执行了两次:第一次执行getName()方法之前,第二次执行getName()方法之后。

5
投票
使用@Around就像编写您自己的代码并调用方法一样,只不过您使用的是proceedingJoinPoint.proceed()。与普通方法调用一样,您可以选择不执行它(将其包装为条件包装)或捕获由它引发的错误(将调用包装在try块中)。

spring documentation

Around建议使用@Around注释声明。咨询方法的第一个参数必须是ProceedingJoinPoint类型。在建议的正文中,在ProceedingJoinPoint上调用proce()会使基础方法执行。可以将proced方法也称为传递Object []-进行时,数组中的值将用作方法执行的参数。
© www.soinside.com 2019 - 2024. All rights reserved.