SpringBoot学习笔记——aop

它是一种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想。用于切入到指定类指定方法的代码片段叫做切面,而切入到哪些类中的哪些方法叫做切入点

AOP编程允许把遍布应用各处的功能分离出来形成可重用的组件

 

实现一个AOP可以分成下面几个步骤:

1.引入依赖 

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.自定义注解 @Permission,其中的 @Target 和 @Retention 元注解参考:元注解(Annotation)

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Permission {
}

参考

3.编写切点

常用的Aspect指示器:@execution,@within,@annotation

@execution:用于在方法执行时触发,如:在com.example.demo.controller.XXXController.register方法在任意参数(..)下执行,返回任意类型(*)的情况下执行

@Pointcut("execution(* com.example.demo.controller.XXXController.register(..))")

@within:用于在方法执行时触发,如:在com.example.demo.controller包下的任意方法执行

@Pointcut("within(com.example.demo.controller.*)")

@annotation:用于注解对象,如:指定 com.example.xxx 包下及其所有子目录下的所有带有 @hello 注解的方法体为切点

@Pointcut("within(com.example.xxx.*) && @annotation(hello)")

  

4.编写切点checkTokenCut,以及定义切面Aspect,简单检查request请求的cookie中是否包含token,且切点设置在添加了 @Permission 注解的 方法上

此外还可以在aop类上添加 @Order注解,来定义Spring IOC容器中Bean的执行顺序的优先级,值越小拥有越高的优先级,可为负数

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

@Slf4j
@Aspect
@Component
public class PermissionAspect {

    @Pointcut("@annotation(com.example.demo.annotation.Permission) && within(com.example.demo.controller.*)")
    public void checkTokenCut() {
    }

    @Around("checkTokenCut()")
    public Object doCheckToken(ProceedingJoinPoint point) throws Throwable {
        ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = attr.getRequest();
        Cookie[] cookies = request.getCookies();
        int len = cookies.length;
        for (int i = 0; i < len; i++) {
            Cookie cookie = cookies[i];
            if ("token".equals(cookie.getName())) {
                log.info("has token");
                break;
            }
            if (i == len - 1) {
                log.info("no token");
            }
        }
   //执行代理目标方法
        return point.proceed();
    }

}

5.注入AspectJ切面 @Permission

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@RequestMapping(path = "/fail", method = RequestMethod.GET)
@Permission
public ControllerResponseT fail() {
return ControllerResponseT.ofFail(50001, "error", null);
}

请求接口的时候将会执行check token逻辑

 

 

参考:SpringBoot使用AOP+注解实现简单的权限验证

前后端分离:使用spring的Aop实现Token验证

 

其他aop的例子:

使用aop实现数据脱敏:改造了以前写的数据脱敏插件,更好用了

使用aop实现接口响应时间记录:Spring Boot 2实践系列(四十七):Spring AOP 实现API接口处理请求耗时监控

使用aop实现全局异常处理以及统一打印接口请求入参和返回结果日志,打印接口访问性能日志,处理sql注入攻击以及处理入参特殊字符等问题:Springboot项目全局异常统一处理

posted @ 2016-03-23 18:53  tonglin0325  阅读(525)  评论(0编辑  收藏  举报