简介
@Aspect注解将一个java类定义为切面类
@Pointcut定义一个切入点,规则表达式
execution: 匹配连接点
execution(方法修饰符(可选) 返回类型 类路径 方法名 参数 异常模式(可选))
1)execution(public * (…))——表示匹配所有public方法
2)execution( set*(…))——表示所有以“set”开头的方法
3)execution(* com.xyz.service.AccountService.(…))——表示匹配所有AccountService接口的方法
4)execution( com.xyz.service..(…))——表示匹配service包下所有的方法
5)execution(* com.xyz.service….(…))——表示匹配service包和它的子包下的方法
within: 某个类里面
this: 指定AOP代理类的类型
target:指定目标对象的类型
args: 指定参数的类型
bean:指定特定的bean名称,可以使用通配符(Spring自带的)
@target: 带有指定注解的类型
@args: 指定运行时传的参数带有指定的注解
@within: 匹配使用指定注解的类
@annotation:指定方法所应用的注解
@Before在切入点开始处切入内容
@After在切入点结尾处切入内容
@AfterReturning在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)
@Around在切入点前后切入内容,并自己控制何时执行切入点自身的内容
@AfterThrowing用来处理当切入内容部分抛出异常之后的处理逻辑
依赖
<!--SpringBoot的Web模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--AOP依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
示例
对指定方法进行人员限流
业务切面
/**
* 服务管理统一权限认证
*
*
* @author lsp
* @Date 2020年7月29日
*/
@Component
@Aspect
@Slf4j
public class CenterInterceptor extends BaseApiResult<JSONObject>{
@Autowired
private RedisUtil redisUtil;
/**
* 限流接入点
*/
@Pointcut("@annotation(com.xxx.tx.center.ann.Limit)")
public void limitAspect(){
}
/**
* 限流拦截处理
*
* @param joinPoint
*/
@Before("limitAspect()")
public void before(JoinPoint joinPoint){
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Limit limit = method.getAnnotation(Limit.class);
boolean personal = limit.isPersonal();
String prefixKey = limit.prefixKey();
long second = limit.second();//秒 默认 5s
if(personal){
hanlder(prefixKey+user().getWorkcode(), second);
}else{
hanlder(prefixKey, second);
}
}
private void hanlder(String key,long second){
String str = redisUtil.get(key);
if(StringUtils.isBlank(str)){
redisUtil.set(key, "1");
redisUtil.expire(key, second, TimeUnit.SECONDS);
}else{
throw new CenterException(200,HaircutEnum.MsgEnum.OVERLOAD_OPERATION.getData());
}
}
}
自定义注解
/**
* 限流
*
* @author lsp
* @Date 2020年7月29日
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Limit {
boolean isPersonal(); //是否个人
String prefixKey();//唯一key
long second() default 5;//控制多少秒
}
业务使用
//提交支付
@PostMapping("add")
@Limit(isPersonal=true,prefixKey="haircut_add_")
public BaseResult<Object> add(String id,String code){
AssertUtil.notBlank(id,"服务id不能为空");
AssertUtil.notBlank(code,"服务时间段不能为空");
if(!centerService.rangeData(id,Constants.SERVICE_HAIRCUT_SIGN).contains(code)){
AssertUtil.notBlank("");
}
//默认个人账户支付 1
if(StringUtils.isBlank(Channel.getName(1))){
AssertUtil.notBlank("");
}
return haircutService.addAndPayOrder(user(),id,code+"",1);
}