AOP切面简单分析
aop的几个术语:
1.通知:就是你想要的功能(安全,事务,日期之类),先把他给定义好,然后在想要的地方用一下.
2.连接点:spring允许通知可以加在的地方,一般指方法的前后
3.切入点:连接点是spring允许你加的地方,而切入点就是你自己决定要加的地方
4.切面:切点和通知加起来就叫做切面(方法增强+增强的地方),通知说明了干什么和什么时候干(什么时候通过方法名中的before,after,around等就能知道),切入点说明了在哪干(指定到底是哪个方法)
5.引入:在现有类之中添加新方法的属性,把切面(也就是新方法属性:通知定义的)用到目标类中
6.目标:被增强的类
@Aspect //声明切面,标记类
public class Audience {
@Pointcut("execution(* *.perform(..))") //定义切点,标记方法
public void performance() {}
@Before("performance()") //切点之前执行
public ....
@AfterReturning("performance()") //切点之后执行
public ...
@AfterThrowing("performance()") //切点抛出异常后执行
public ...
}
注意的是切点的配法
execution(public * com.longshansi.method.cos..*.*(..))
先是execution()表达式,public是权限修饰自然不用多说
然后是 * 表示的是返回类型
接下来com.longshansi.method.cos是aop切入的包名,后面的 .. 表示这个包以及他的子包名
..后面的是一个 * ,表示的是这个包下所有的类,当然你可以指定某一个具体的类
最后的一个* , 指的是方法
(..) 里面是方法的参数,注意的是左括号前的一定是方法,方法也可能作匹配
下面以南哥的微信**系统做一个aop切面增强的示例:
@Pointcut("execution(public * com.it.weshell.controller.Seller*.*(..))" +
"&& !execution(public * com.it.weshell.controller.SellerUserController.*(..))")
public void verify() {}
这句话的意思是:
在com.it.weshell.controller这个包下面,所有以Seller作为开头的类下面的所有的方法都会加上verify()这个增强,但是SellerUserController这个类下的所有方法除外.
增强类(不用看具体的实现细节):
@Before("verify()")
public void doVerify() {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//查询cookie
Cookie cookie = CookieUtil.get(request, CookieConstant.TOKEN);
if (cookie == null) {
log.warn("【登录校验】Cookie中查不到token");
throw new SellerAuthorizeException();
}
//去redis里查询
String tokenValue = redisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_PREFIX, cookie.getValue()));
if (StringUtils.isEmpty(tokenValue)) {
log.warn("【登录校验】Redis中查不到token");
throw new SellerAuthorizeException();
}
}
需要注意的是上面提到了AspectJ的通知注解,需要了解清楚
@Before: 前置通知, 在方法执行之前执行
@After: 后置通知, 在方法执行之后执行 。
@AfterRunning: 返回通知, 在方法返回结果之后执行
@AfterThrowing: 异常通知, 在方法抛出异常之后
@Around: 环绕通知, 围绕着方法执行