当前位置: 首页 > 知识库问答 >
问题:

Spring AOP:aspect@around不起作用

康鹏云
2023-03-14

项目地址:https://github.com/zalizko/spring-aop-playground

@Aspect
@Component
public final class MethodRepeater {

    @Around("execution(* *(..)) && @annotation(RetryOnFailure)")
    public Object wrap(final ProceedingJoinPoint joinPoint) throws Throwable {
        // code is here
    }
}

所以,我的目标是:

@RequestMapping
public String index() {
    inTry();
    return "OK";
}


@RetryOnFailure(attempts = 3, delay = 2, unit = TimeUnit.SECONDS)
public void inTry() {
    throw new RuntimeException("Exception in try " + ++counter);
}

共有1个答案

全兴运
2023-03-14

您犯了一个典型的Spring AOP初学者的错误:您忘记了基于代理的AOP只有在从外部调用代理方法时才起作用,而不是通过这个(避免使用代理)。但是内部调用intry()this.intry()相同。因此,intry不会触发方面,您必须像这样重新排列代码:

package spring.aop;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

@RestController("/")
public class HomeController {

    static int counter = 0;

    @RequestMapping
    @RetryOnFailure(attempts = 3, delay = 2, unit = TimeUnit.SECONDS)
    public String index() {
        throw new RuntimeException("Exception in try " + ++counter);
    }
}

我还稍微改变了一下方面,以便

  • 避免反射,直接通过@annotation()
  • 将注释绑定到advice参数
  • 在触发通知和
  • 时记录连接点
  • 在try#3上返回“OK”(只是为了好玩,没有必要)。
package spring.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public final class MethodRepeater {

    @Around("execution(* spring.aop..*(..)) && @annotation(retryOnFailure)")
    public Object wrap(final ProceedingJoinPoint joinPoint, RetryOnFailure retryOnFailure) throws Throwable {
        System.out.println(joinPoint);
        return proceed(joinPoint, retryOnFailure);
    }

    private Object proceed(ProceedingJoinPoint joinPoint, RetryOnFailure retryOnFailure) throws Throwable {
        int attempt = 1;
        while (true) {
            try {
                return joinPoint.proceed();
            } catch (final Throwable ex) {
                System.out.println("Try #" + attempt + " failed: " + ex);
                if (++attempt >= retryOnFailure.attempts())
                    return "OK";
                if (retryOnFailure.delay() > 0L)
                    retryOnFailure.unit().sleep(retryOnFailure.delay());
            }
        }
    }
}
execution(String spring.aop.HomeController.index())
Try #1 failed: java.lang.RuntimeException: Exception in try 1
Try #2 failed: java.lang.RuntimeException: Exception in try 2
 类似资料:
  • around 是一个权限管理解决方案,它基于 springboot 实现,遵循阿里 java 开发手册,代码实现相对于 springmvc 来说更加优雅。缓存可以不基于任何缓存复杂臃肿的缓存系统,但是简单的实现了自带的 redis 缓存。在配置里可以关闭,也可以自定义任何缓存系统,来实现你心目中的样子。权限模块是实现了 springframework 的 HandlerInterceptor 这个

  • 因此,我在一个控制器中有一个非常简单的代码片段,在这个代码片段中,我使用从外部文件中获取数据,它工作得很好!但是当我使用时,我会在控制台中得到一个

  • 问题内容: 正则表达式似乎还可以,因为第一行将子字符串正确替换为“ helloworld”,但是后者却不匹配,因为我看不到“ whynothelloworld?”。在控制台上 问题答案: 期望 整个 字符串匹配,而不仅仅是子字符串。 使用正则表达式匹配器对象的方法代替:

  • @Around是一种通知类型,可确保在方法执行之前和之后运行建议。 以下是@Around建议的语法。 语法 (Syntax) @PointCut("execution(* com.wenjiangs.Student.getAge(..))") private void selectGetName(){} @Around("selectGetAge()") public void aroundAdv

  • Around是一种通知类型,可确保在方法执行之前和之后运行建议。 以下是around建议的语法。 语法 (Syntax) <aop:config> <aop:aspect id = "log" ref = "logging"> <aop:PointCut id = "PointCut-id" expression = "execution( expression )"/>

  • Weather Around (YQL Demo) 应用是用来展示如何使用 iOS 的 YQL ,解析和显示 JSON 格式的数据。同时,它还包括一些简单的 GPS 位置示例。用户可以输入多个城市的名字,通过 SQL(比如 YQL API 的查询信息)来获取天气预报信息。