初试AspectJ切面编程(AOP)

小菜鸟 1年前 (2023-11-07) 阅读数 1081 #编程日记
文章标签 后端

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

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

结尾

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

文章源地址:https://juejin.cn/post/7298168155160231970
热门
标签列表