初试AspectJ切面编程(AOP)

AspectJ框架是什么

AspectJ框架是一个用于面向切面编程(AOP)的框架。

它是基于Java语言的扩展,提供了更强大和灵活的AOP功能。AspectJ可以在编译时或者运行时织入代码,以实现横切关注点的功能。它支持更细粒度的切入点表达式,可以在类级别、方法级别甚至字段级别进行切面编程。AspectJ还提供了更多的通知类型,如前置通知、后置通知、异常通知、环绕通知等,使开发人员能够更精确地控制横切逻辑的执行时机。AspectJ可以独立于其他框架使用,但也可以与Spring等框架集成,提供更强大的AOP能力。

和SpringAop有什么区别

AspectJ框架和Spring AOP是两种不同的AOP实现方式。

AspectJ是一个独立的AOP框架,它提供了更强大和灵活的AOP功能。它使用编译时织入(CTW)或者运行时织入(RTW)的方式来实现横切关注点的织入。AspectJ支持更多的切入点表达式,可以在更细粒度的层面上进行切面编程。它还提供了更多的通知类型,如前置通知、后置通知、异常通知、环绕通知等。AspectJ可以独立于Spring框架使用,但也可以与Spring集成。

Spring AOP是Spring框架的一部分,它提供了一种更简化的AOP实现方式。它使用运行时代理(Proxy)的方式来实现横切关注点的织入。Spring AOP的功能相对较为有限,只支持方法级别的切入点表达式,通知类型也相对较少,包括前置通知、后置通知、异常通知。Spring AOP主要用于在Spring应用程序中实现横切关注点的功能。

总的来说,AspectJ提供了更强大和灵活的AOP功能,适用于更复杂的切面编程需求;而Spring AOP则提供了一种更简单和轻量级的AOP实现,适用于简单的切面编程需求,并且与Spring框架集成更紧密。

以实现自定义注解为例,两步学会使用

举例实现一个短时间内【限制接口请求次数】的注解

1.自定义注解

java 复制代码
package com.pth.server.core.http;

import java.lang.annotation.*;

/**
 * @author Administrator
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestRate {

    /**
     * 用户id
     * @return
     */
    String userId();

    /**
     * 限制次数
     * @return
     */
    int rateCount() default 3;

    /**
     * 过期时间
     * @return
     */
    int expireTime() default 10;

}

2.AOP处理实现

java 复制代码
package com.pth.server.core.http;

import cn.hutool.core.convert.Convert;
import com.pth.server.core.constants.RedisConstants;
import com.pth.server.core.exception.ServerException;
import com.pth.server.core.utils.ParamsUtil;
import net.sf.json.JSONObject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

@Component
@Aspect
public class RequestRateAspect {

    @Autowired
    protected RedisTemplate<String, String> redisTemplate;

    @Pointcut("@annotation(com.pth.server.core.http.RequestRate)")
    public void rateAspect(){}

    @Before("rateAspect()")
    public void beforeRate(JoinPoint joinPoint){
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        // 获取注解中的参数 用于根据属性名获取属性值 因为某些注解的属性值是字符串 但实则是变量
        JSONObject paramsJson = ParamsUtil.getParams(joinPoint);
        RequestRate requestRate = method.getAnnotation(RequestRate.class);
        String userId = paramsJson.get(requestRate.userId()).toString();
        String key = RedisConstants.REQUEST_RATE + userId;
        Integer val = Convert.toInt(this.redisTemplate.opsForValue().get(key));
        if(val == null){
            val = 0;
        }else if(val >= requestRate.rateCount()){
            throw new ServerException("请求频率过高,请稍后再试");
        }
        this.redisTemplate.opsForValue().set(key, Convert.toStr(++val), requestRate.expireTime(), TimeUnit.MINUTES);
    }

    @After("rateAspect()")
    public void afterRate(JoinPoint joinPoint){



    }

}

使用注解

java 复制代码
@RequestMapping(path = "/test", method = RequestMethod.GET)
@RequestRate(userId = "userId")
void getImgCode(String userId, HttpServletResponse response) throws IOException {

}

注解说明(面向小白)

以上用到的注解是用于定义切面的。在面向切面编程(AOP)中,切面是一种用于横切关注点的模块化方式。

@Aspect 注解用于标识一个类为切面类,它通常与其他注解一起使用。

@Before 注解用于指定在目标方法执行之前执行的通知(advice)。

@After 注解用于指定在目标方法执行之后执行的通知。

@Pointcut 注解用于定义一个切入点,切入点是一个表达式,它定义了哪些方法将被切入。切入点表达式可以使用通配符和逻辑操作符来匹配目标方法。

这些注解一起提供了一种方式,通过在特定的切入点上执行额外的逻辑,从而实现横切关注点的功能,例如日志记录、性能监控等。

结尾

怎么样,是不是很简单,就那几个注解就实现了,我写的文章都很简洁,简单便捷,高效实用,哈哈~

相关推荐
葫芦和十三7 小时前
图解 MongoDB 22|读写关注:持久性与一致性的档位选择
后端·mongodb·agent
葫芦和十三14 小时前
图解 MongoDB 21|选举与 failover:Primary 是怎么选出来的
后端·mongodb·agent
GetcharZp14 小时前
26k Star 开源内网穿透神器 NetBird,一分钟实现全球设备互联!
后端
考虑考虑15 小时前
Mybatis实现批量插入
java·后端·mybatis
咖啡八杯16 小时前
GoF设计模式——中介者模式
java·后端·spring·设计模式
lizhongxuan18 小时前
多Agent之间的区别
后端
青石路19 小时前
记一次多JDK版本问题的排查,一坑套一坑,差点没爬上来
java
杨充20 小时前
1.面向对象设计思想
后端
IT_陈寒20 小时前
Java的Date类又坑了我一次,改用时间戳真香
前端·人工智能·后端
systemPro21 小时前
2.6亿条设备数据,历史查询从超时到50ms,我做了什么
后端