由于SpringBoot不需要再写applicationContext.xml,转为更为简洁风格的application.yml,也就没有了AOP如下配置
而是依靠application.yml短短代码和大量注解来完成
代码是简洁了,但各种细节配置都被隐藏了,找个错费半天劲,所以这就需要有更坚实的技术啊!
-
导包
-
设置application.yml
jdk: 默认,面向接口
cglib: 面向继承类(推荐)
-
编写一个普通类,用来做增强类
申请为被Spring管理bean,SpringBoot使用Aspect来处理AOP功能
使用以下注解来代表增强类型:
@Around:环绕增强,相当于MethodInterceptor
@AfterReturning:后置增强,相当于AfterReturningAdvice,方法正常退出时执行
@Before:前置增强,相当于BeforeAdvice的功能,相似功能的还有
@AfterThrowing:异常抛出增强,相当于ThrowsAdvice
@After: final增强,不管是抛出异常或者正常退出都会执行
3.1 切点具体路径
通配规则匹配和Spring AOP一致
3.2 切点注解
编写一个软接口,准备注解切入点
无参数例子
有参数例子:
引入自定义注解
切入注解–带参数
//切入注解
//@Around("@annotation(com.xly.aop.RedisAnnotation)")
@Around("@annotation(com.xly.aop.RedisAnnotation) && @annotation(redisAnnotation)")
public Object invoke(ProceedingJoinPoint joinPoint,RedisAnnotation redisAnnotation) throws Throwable{
System.out.println("the aspect around is working");
//获取注解自定义参数,用于设计不同的处理方法
String listType = redisAnnotation.listType();
//尝试从redis读取数据 recommendList
String result = redisTemplate.opsForValue().get(listType);
if(result == null) {
System.out.println("未从redis获取到数据");
//如果为空,执行原方法
List<Product> list = (List<Product>) joinPoint.proceed();
//转JSON串
String jsonString = JSON.toJSONString(list);
//存入redis
redisTemplate.opsForValue().set(listType, jsonString);
//返回原始数据库数值
return list;
}
//如果不为空,则直接读取redis
else {
System.out.println("已从redis获取到数据");
//JSON转list
List<Product> list = JSON.parseArray(result, Product.class);
//返回redis数值
return list;
}
}
增强方法参数一致原则:
增强方法的参数数量,类型,位置 需要和 切点保持一致,比如
注解的切点 args( i , j ) 和 int i, int j 必须保持一致
普通类型参数使用 args 来声明参数一致
注解类型参数使用 @annotation 来声明参数一致
其中 ProceedingJoinPoint(环绕),JoinPoint(其它)是AOP特殊类型,不需要遵循参数一致原则
- 放置软接口注解,实现方法级增强
分页只是一个测试AOP的例子,如果考虑分页那么缓存意义就不大,代码会更复杂。
建议做法:- 一次查询固定数量条目list,然后缓存到redis
- list丢入到前台,由前台框架实现分页功能
- 后续补充功能
分割读写Redis功能
5.1 使用注解参数区分读,写请求
5.2 读请求,完成上面逻辑
5.3 写请求,修改原始数据库,删除Redis记录,再重新存入Redis