SpringAOP:基础概念

1.什么是AOP

这个问题应该在很多面试场景都会遇到,一般是热身问题。AOP是对OOP的补充。一些比较通用的逻辑,我们可以使用切面编程去解决,提高代码的可用性和提高效率。常见的场景如下:

  • 事务
  • 日志收集
  • 权限校验

2.AOP的底层技术

实现方式差别
jdk动态代理(默认)基于接口
cglib基于继承

3.AOP的概念

在使用AOP的时候,会有一些概念上的是需要知道的。

  • aspect:切面的类,使用@Aspect注解标识。我的理解是给Spring扫描的一个类,他集合了下面所有的通知、切面等等…
  • pointcut:连接点的集合。
  • Joinpoint:连接点。这个表示我们要作用在什么区域,一般是方法。
  • Weaving :织入。将代理逻辑加入到原来的逻辑的过程叫做织入。
  • target :目标对象
  • aop Proxy:代理对象。
  • advice:通知。包括两方面(位置+逻辑)。位置:指的是在哪实现我们的逻辑;逻辑:就是我们真正写业务代码的地方。
    advice的通知类型:
    Before:连接点执行之前,但是无法阻止连接点的正常执行,除非该段执行抛出异常。
    After :连接点正常执行之后,执行过程中正常执行返回退出,非异常退出。
    After throwing:执行抛出异常的时候
    After (finally):无论连接点是正常退出还是异常退出,都会执行
    Around advice:环绕通知可以在方法调用之前和之后执行自定义行为。

Proceedingjoinpoint 和JoinPoint的区别:Proceedingjoinpoint 继承了JoinPoint,proceed()这个是aop代理链执行的方法。并扩充实现了proceed()方法,用于继续执行连接点。JoinPoint仅能获取相关参数,无法执行连接点。JoinPoint的方法
1.java.lang.Object[] getArgs():获取连接点方法运行时的入参列表;
2.Signature getSignature() :获取连接点的方法签名对象;
3.java.lang.Object getTarget() :获取连接点所在的目标对象;
4.java.lang.Object getThis() :获取代理对象本身;
proceed()有重载,有个带参数的方法,可以修改目标方法的的参数

4.结语

SpringAOP还有很多概念。个人感觉平时使用掌握上面的已经基本足够了,如果有特殊的使用场景可以参考Spring的官网,里面非常详细。

5.SpringAOP案例

@RestController
public class TestController {
    @RequestMapping("/test")
    @Idempotent(limit = 1,timeUnit = TimeUnit.SECONDS)
    public String test(@RequestParam("userId") String userId) {
        return userId + "hello world";
    }
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Idempotent {

    /**
     * 多少时间以内不可以访问
     * @return 时间
     */
    int limit() default 1;

    /**
     * 时间单位
     * @return 时间单位
     */
    TimeUnit  timeUnit() default TimeUnit.SECONDS;

}

切面:

@Aspect
@Component
public class IdempotentAspect {

    public static final Map<String,String> CHECK_MAP = new HashMap<>(16);

    /**
     * 切点
     */
    @Pointcut("@annotation(Idempotent)")
    private void annotationPointCut() {

    }

    @Around("annotationPointCut()")
    public Object processJoinCut(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        String className = proceedingJoinPoint.getTarget().getClass().getName();
        MethodSignature signature = (MethodSignature)proceedingJoinPoint.getSignature();
        String methodNAme = signature.getMethod().getName();
        Idempotent idempotent = signature.getMethod().getAnnotation(Idempotent.class);
        int limit = idempotent.limit();
        TimeUnit timeUnit = idempotent.timeUnit();

        String targetMethodParams= Arrays.toString(proceedingJoinPoint.getArgs());
        String value = className + methodNAme + limit;
        if (CHECK_MAP.get(targetMethodParams) != null) {
            throw new RuntimeException("您操作太快了");
        }
        CHECK_MAP.put(targetMethodParams,value);
        System.out.println(CHECK_MAP.toString());
        //调用下一个切面或目标方法
        return proceedingJoinPoint.proceed();
    }

}

6.参考:

https://docs.spring.io/spring-framework/docs/current/reference/html/core.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值