AOP介绍
1.六种通知方式
- 环绕通知:在目标方法执行前和执行后实施增强,可用于日志记录,事务处理等
- 前置通知:在目标方法执行前实施增强,可用于权限管控等
- 后置返回通知:在目标方法成功执行后实施增强,可用于关闭流,删除临时文件等
- 后置通知:在目标方法执行后实施增强(无论方法是否发生异常都执行),可用于释放资源
- 异常通知:在目标方法抛出异常时实施增强,可用于处理异常,记录日志等
- 引入通知:在目标类中添加一些方法和属性,用于修改目标类
2.AspectJ相关注解
@Aspect
:用于定义一个切面,注解在切面类上@Pointcut
:用于定义切点表达式,在使用时,需要定义一个切入点方法,该方法返回值为void,且方法体为空的普通方法@Before
:用于定义前置通知,通常为其指定value属性,该值可以是已有切入点,也可以定义切点表达式@AfterReturning
:用于定义后置返回通知,通常为其指定value属性,该值可以是已有切入点,也可以定义切点表达式@Around
:用于定义环绕通知,通常为其指定value属性,该值可以是已有切入点,也可以定义切点表达式AfterThrowing
:用于定义异常通知,通常为其指定value属性,该值可以是已有切入点,也可以定义切点表达式。另外还有一个 throwing属性用于访问目标方法抛出的异常,该属性值与异常通知方法中同名的形参一致After
:用于定义后置最终通知,通常为其指定value属性,该值可以是已有切入点,也可以定义切点表达式
定义切入点的两种方式
1.注解
//定义注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface SafetyHarness { String defaultValue() default ""; } //切入点 @Pointcut("@annotation(com.xx.xx.xx.web.annotation.SafetyHarness)") public void efficacyParameters(){ }
2.表达式
//该controller所有方法,可以直接指定 /* execution():表达式主体 第一个 * 表示返回类型,使用*表示所有类型,该 * 与包名之间有一个空格 第二个 * 表示类名 第三个 * 表示方法名 ..表示任意参数 */ @Pointcut("value = "execution(* com.xx.xx.xx.web.controller.*.* (..)))") public void efficacyParameters(){ }
常用两种通知获取参数
1.@Before
@Before("efficacyParameters()") public void beforeEfficacyParameters(JoinPoint joinPoint){ //获取请求参数 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = Objects.requireNonNull(attributes).getRequest(); Map<String, String[]> parameterMap = request.getParameterMap(); //通过参数名获取 Object ext1 = parameterMap.get("ext1"); Object ext2 = parameterMap.get("ext2"); }
2.@Around
@Around("efficacyParameters()") public T beforeEfficacyParameters(ProceedingJoinPoint joinPoint){ //接口返回结果,该结果可在业务前或业务后执行 Object proceed = joinPoint.proceed(); Object[] obj = joinPoint.getArgs(); if (obj == null || obj.length == 0) { return T; } //获取请求参数 Map<String, Object> fieldsName = getFieldsName(joinPoint); Object ext1 = fieldsName.get("ext1"); //POST请求强转 SafetyAuditPageVo ext2 = (SafetyAuditPageVo) fieldsName.get("ext"); //修改请求参数 SafetyAuditPageVo vo = (SafetyAuditPageVo) obj[0]; vo.setXxxx("XXXXXX"); obj[0] = vo; return joinPoint.proceed(obj); } private static Map<String, Object> getFieldsName(ProceedingJoinPoint joinPoint) { Object[] args = joinPoint.getArgs(); ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer(); MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); String[] parameterNames = pnd.getParameterNames(method); Map<String, Object> paramMap = new HashMap<>(32); for (int i = 0; i < parameterNames.length; i++) { paramMap.put(parameterNames[i], args[i]); } return paramMap; }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。