备注:思考实现一个切面都需要哪些步骤?
(1)肯定需要写具体的切面业务逻辑(对应aspect)
(2)那写好逻辑后什么时候执行?是主要逻辑前还是主要逻辑后?(对应advice,执行时机)
(3)需要定义一个在哪里使用切面,比如某个insert方法要使用切面,校验insert之前的一些null或者空字符串(对应join point)
(4)不是所有方法都用到这个切面,怎么控制?(通过point cut来控制和匹配)
连接点
join point,程序的一个执行点,类似类的一个方法,方法里边一个代码块
切入点
Point cut,捕获连接点的代码结构,定一个代码逻辑用来捕获某个连接点的实现逻辑
切面
aspect,具体被执行的代码逻辑,就是我们想要的那些校验、记录日志、发送短信通知等这些逻辑实现代码
通知
advice,定义在连接点什么时机来执行aspect,包含before(主要逻辑之前执行)、after(主要逻辑之后执行)、around(前、后都执行)
假如想要提交一个请假申请,在申请单有性别、请假时间等,创建申请单之前校验提交的参数(sex、startDate、endDate)不能为空,将这个校验逻辑使用切面来实现。
自定义一个注解ApplyAnnotation
import java.lang.annotation.*;
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApplyAnnotation {
}
创建aspect类
package portal.aop;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Objects;
/**
* 申请单插入前校验的切面
*
*/
@Slf4j
@Aspect
@Component
public class ApplyAspect {
/**
* 校验:对sex、startDate、endEnd参数进行校验
* @param joinPoint
* @throws RRException
*/
@Before("@annotation(ApplyAnnotation)")
public void before(JoinPoint joinPoint) throws RRException {
if(joinPoint.getArgs()!=null && joinPoint.getArgs().length>0) { //获取参数使用joinPoint.getArgs
String json = JSONObject.toJSONString(joinPoint.getArgs()[0]);
// 将参数转换成一个entity对象
UpdateApplyForm form = objectMapper.convertValue(joinPoint.getArgs()[0], UpdateApplyForm.class);
if (Objects.isNull(form.getSex())) {
throw new Exception("参数错误,请检查参数sex是否传递");
}
if (Objects.isNull(form.getStartDate())) {
throw new Exception("参数错误,请检查参数startDate是否传递");
}
if (Objects.isNull(form.getEndDate())) {
throw new Exception("参数错误,请检查参数endDate是否传递");
}
}
}
@After("@annotation(ApplyViewAnnotation)")
public void after(JoinPoint joinPoint) {
// 可以在主要逻辑之后执行一些 记录日志或者发送短信通知等逻辑
}
}
在想要使用的地方添加注解
/**
* 在controller的createApply方法使用注解
* 创建一条请假申请,加上ApplyAnnotation注解后,会在执行createApply方法之前去调用切面的before方法进行校验
* @param form
* @return
* @throws Exception
*/
@PostMapping("/create-apply")
@ApplyAnnotation
public R createApply(@RequestBody UpdateApplyForm form) throws Exception {
// 主要业务逻辑
portalLogic.createApply(form);
return R.ok();
}
体验完上述的实例之后,会发现,我们的主要逻辑portalLogic.createApply(form)没有混入一些奇奇怪怪的if else进行校验,而是直接用一个注解就将这些校验逻辑实现了,从代码层次看,让代码更加的简洁,从架构上看,将校验逻辑和主要逻辑进行解耦。
简介: 6月4日,以“开启分布式云新时代”为主题2021云边协同大会在北京举行,本...
在默认情况之下,如果在Canvas之中将某个物体(源)绘制在另一个物体(目标)之...
本文没有咬文嚼字的地方,只是一个配色技巧的分享,十分简单,简单到流泪,但或...
前言 Canvas绘制多变形非常简单,只要懂得Canvas路径 + 简单的初中数学知识即可...
1、纯工具操作步骤,懂代码更容易 划线就是不符合国人的审美观念,看着就别扭,...
作者:Joe Seifi 译者:前端小智 移动: https://mp.weixin.qq.com/s/p5... 有梦...
一、虽然有的属性是boolean类型,但仍旧建议按照XHTML书写(属性名=属性值)格式...
背景 在公司参与一个原生APP和h5混合开发的项目,本人在项目中负责h5部分,现将...
折叠式卡片布局在PC版网站中可能不常见,但是在手机版,小屏幕的网页浏览会大发...
1.先瞧瞧效果: 2.代码是这样的: img src=images/circle.png alt= id=circle/@m...