SpringBoot_面向切面_AOP

简介

@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);
}

Guess you like

Origin blog.csdn.net/qq_15764943/article/details/107681578