org.aspectj.lang.JoinPoint-中文简要API

本文介绍了AspectJ中表示目标类连接点对象的JoinPoint接口及其子接口ProceedingJoinPoint。详细阐述了这两个接口的主要方法,包括获取方法入参、方法签名、目标对象等信息,以及如何通过ProceedingJoinPoint执行连接点处的方法。

AspectJ使用org.aspectj.lang.JoinPoint接口表示目标类连接点对象,如果是环绕增强时,使用org.aspectj.lang.ProceedingJoinPoint表示连接点对象,该类是JoinPoint的子接口。任何一个增强方法都可以通过将第一个入参声明为JoinPoint访问到连接点上下文的信息。我们先来了解一下这两个接口的主要方法:
###1)JoinPoint

  • java.lang.Object[] getArgs():获取连接点方法运行时的入参列表;
  • Signature getSignature() :获取连接点的方法签名对象;
  • java.lang.Object getTarget() :获取连接点所在的目标对象;
  • java.lang.Object getThis() :获取代理对象本身;

###2)ProceedingJoinPoint

ProceedingJoinPoint继承JoinPoint子接口,它新增了两个用于执行连接点方法的方法:

  • java.lang.Object proceed() throws java.lang.Throwable:通过反射执行目标对象的连接点处的方法;

  • java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通过反射执行目标对象连接点处的方法,不过使用新的入参替换原来的入参。


项目推荐



DC3是基于Spring Cloud的开源可分布式物联网(IOT)平台,用于快速开发、部署物联设备接入项目,是一整套物联系统解决方案。

package step2; import java.util.Arrays; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; //添加组件和切面注解 //===============begin=============== //================end================ public class LoggingAspect { @Before("execution(public int step2.ArithmeticCalculator.*(..))") public void beforeMethod(JoinPoint joinPoint){ String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); System.out.println("INFO: The method " + methodName + " begin with " + Arrays.asList(args)); } @After("execution(public int step2.ArithmeticCalculator.*(..))") public void afterMethod(JoinPoint joinPoint){ String methodName = joinPoint.getSignature().getName(); System.out.println("INFO: The method " + methodName + " end."); } //添加返回通知,切入点表达式为step2.ArithmeticCalculator下的所有方法,带返回值; //通知信息为“INFO: The method 方法名 return result 返回值” //===============begin=============== //================end================ } package step2; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { ApplicationContext cxt = new ClassPathXmlApplicationContext("spring-aop.xml"); //IoC容器中获取ArithmeticCalculatorImpl类型对象,调用add(10,20)方法 //===============begin=============== //================end================ } }
04-01
package sfw.xmut.guomao.aspect; import sfw.xmut.guomao.entity.OperationLog; import sfw.xmut.guomao.mapper.OperationLogMapper; import sfw.xmut.guomao.utils.ServletUtil; import jakarta.servlet.http.HttpServletRequest; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import java.time.LocalDateTime; @Aspect @Component public class OperationLogAspect { private final OperationLogMapper logMapper; public OperationLogAspect(OperationLogMapper logMapper) { this.logMapper = logMapper; } @Around("execution(* sfw.xmut.guomao.controller.*.*(..))") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); HttpServletRequest request = attributes.getRequest(); if (request.getRequestURI().endsWith("/operationLog/page")) { return joinPoint.proceed(); } long startTime = System.currentTimeMillis(); Object result = joinPoint.proceed(); long spendTime = System.currentTimeMillis() - startTime; OperationLog log = new OperationLog(); log.setUserName("admin"); // TODO: Get from JWT token log.setOperationType(request.getRequestURI()); log.setOperationMethod(request.getMethod()); log.setRequestUrl(request.getRequestURL().toString()); log.setOperationIp(ServletUtil.getClientIP(request)); log.setOperationStatus("成功"); log.setLastOperationTime(LocalDateTime.now()); logMapper.insert(log); return result; } }log.setUserName("admin"); // TODO: Get from JWT token 这一行代码怎么把他改成不管哪个用户登录这个管理系统日志上面都可以更新,不要像这个admin锁住固定住不管谁登录都是显示他的名称
06-19
package com.ym.engine.bus.config; import com.ym.engine.bus.annotate.Idempotent; import com.ym.engine.bus.annotate.IdempotentKeyResolver; import com.ym.engine.bus.utils.RedisHelper; import com.ymlib.common.result.IdempotentException; import com.ymlib.common.result.JSONBeans; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import java.lang.reflect.Method; import java.time.LocalDateTime; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** * * @projectName: com.ym.engine.bus.config * @packageName: com.ym.engine.bus.config * @fileName: IdempotentAspect.java * @remark: * @createTime: 2024-10-11 10:28 * @author: yex * @Copyright: 2024 Inc. All rights reserved. * @version: V1.0 * */ @Aspect @Component @Slf4j public class IdempotentAspect { private ThreadLocal<Map<String,Object>> threadLocal = new ThreadLocal(); private static final String RMAPCACHE_KEY = "idempotent"; private static final String KEY = "key"; private static final String DELKEY = "delKey"; private RedisHelper redisHelper; /** * IdempotentKeyResolver 集合 */ private final Map<Class<? extends IdempotentKeyResolver>, IdempotentKeyResolver> keyResolvers; public IdempotentAspect(List<IdempotentKeyResolver> keyResolvers, RedisHelper redisHelper) { this.keyResolvers = keyResolvers.stream().collect( Collectors.toMap(IdempotentKeyResolver::getClass, product -> product,(key1, key2) -> key2)); this.redisHelper = redisHelper; } @Pointcut("@annotation(com.ym.engine.bus.annotate.Idempotent)") public void pointCut(){} @Around(value = "@annotation(idempotent)") public Object aroundPointCut(ProceedingJoinPoint joinPoint, Idempotent idempotent) throws Throwable { // 获得 IdempotentKeyResolver IdempotentKeyResolver keyResolver = keyResolvers.get(idempotent.keyResolver()); Assert.notNull(keyResolver, "找不到对应的 IdempotentKeyResolver"); // 解析 Key String key = keyResolver.resolver(joinPoint, idempotent); // 1. 锁定 Key boolean success = redisHelper.setIfAbsent(key, idempotent.expireTime()); // 锁定失败,抛出异常 if (!success) { log.info("[aroundPointCut][方法({}) 参数({}) 存在重复请求]", joinPoint.getSignature().toString(), joinPoint.getArgs()); throw new IdempotentException(new JSONBeans(idempotent.info())); } // 2. 执行逻辑 try { return joinPoint.proceed(); } catch (Throwable throwable) { // 3. 异常时,删除 Key if (idempotent.deleteKeyWhenException()) { redisHelper.delete(key); } throw throwable; } } @Before("pointCut()") public void beforePointCut(JoinPoint joinPoint)throws Exception{ ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = requestAttributes.getRequest(); MethodSignature signature = (MethodSignature)joinPoint.getSignature(); Method method = signature.getMethod(); if(!method.isAnnotationPresent(Idempotent.class)){ return; } Idempotent idempotent = method.getAnnotation(Idempotent.class); boolean isIdempotent = idempotent.idempotent(); if(!isIdempotent){ return; } String url = request.getRequestURL().toString(); String argString = Arrays.asList(joinPoint.getArgs()).toString(); String key = url + argString; long expireTime = idempotent.expireTime(); String info = idempotent.info(); TimeUnit timeUnit = idempotent.timeUnit(); boolean delKey = idempotent.delKey(); //do not need check null Map<String, String> rMapCache = redisHelper.hgetAll(RMAPCACHE_KEY); String value = LocalDateTime.now().toString().replace("T", " "); Object v1; if (null != rMapCache.get(key)){ //had stored throw new IdempotentException(new JSONBeans("[idempotent]:"+info)); } synchronized (this){ v1 = rMapCache.putIfAbsent(key, value); if(null != v1){ throw new IdempotentException(new JSONBeans("[idempotent]:"+info)); }else { log.info("[idempotent]:has stored key={},value={},expireTime={}{},now={}",key,value,expireTime,timeUnit,LocalDateTime.now().toString()); } } Map<String, Object> map = CollectionUtils.isEmpty(threadLocal.get()) ? new HashMap<>(4):threadLocal.get(); map.put(KEY,key); map.put(DELKEY,delKey); threadLocal.set(map); } @After("pointCut()") public void afterPointCut(JoinPoint joinPoint){ Map<String,Object> map = threadLocal.get(); if(CollectionUtils.isEmpty(map)){ return; } Map<String, String> mapCache = redisHelper.hgetAll(RMAPCACHE_KEY); if(mapCache.size() == 0){ return; } String key = map.get(KEY).toString(); boolean delKey = (boolean)map.get(DELKEY); if(delKey){ mapCache.remove(key); log.info("[idempotent]:has removed key={}",key); } threadLocal.remove(); } }
最新发布
12-24
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值