Spring AOP

面向切面编程(AOP)是Spring的两大核心之一.AOP的思想能够帮助咱们在不侵入代码的状况下对原有功能进行加强,修改;编程

大体是如下流程

反射 -> proxy(动态代理) -> AOP(面向切面)api

@Aspect

*   定义切面类

@Pointcut

*   切点

Advice

*   在切入点上执行的加强处理
*   @Before
*   @After
*   @AfterReturning 切点方法拿到返回值后执行
*   @AfterThrowing 切点方法抛出异常后执行
*   @Around 环绕加强

正常的执行顺序是:@Around ->@Before->主方法体->@Around中pjp.proceed()->@After->@AfterReturning
@Around
若是不执行proceedingJoinPoint.proceed()方法,那么目标方法不会执行;
能够决定是否执行目标方法;@before只是拦截方法;若是加了@around,原方法交给proceed()控制
//xx()是切点
@Around("xx()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
       log.info("进入around")
       return proceedingJoinPoint.proceed();
    
    }
语法规则
  • 支持&&,||,!
  • @Pointcut(execution(url)) 指定切面方法
  • @Pointcut("@annotation(url)") 自定义注解指定切面方法
  • within,this,target...

demo

spd系统中使用aop对向外提供的api接口进行token校验权限控制.this

1.首先自定义注解并在须要权限认证的接口上加上注解url

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

2.代理

@Component
@Aspect
@Slf4j
public class OrderReportAspect {

@Autowired
private ISysUserService sysUserService;

@Pointcut("@annotation(com.x.common.annotation.ReportPermission)")
 public void pointCut() {} 
 
//根据角色控制容许访问接口的用户
@Around("pointCut()")
 public Object before(ProceedingJoinPoint pjp) throws Throwable {

 Object[] in = pjp.getArgs();

 if (in.length >= 1) {
  HttpServletRequest request = (HttpServletRequest) in[0];
  log.info("切面获取request:{}",request);
  String userId = JwtUtil.checkToken(request.getHeader("token"));
  //校验当前userId是否有读取接口的权限
  int count = sysUserService.isSpecified(userId,Constant.LOGISTICS_REPORT_RECEIVER);
 
 if (count == 1) {return pjp.proceed();}
 log.warn("api接口角色校验失败");
 return null;
 }
 log.warn("api接口角色校验失败");
 return null;
 }
}