什么是注解:
annotation 是 源代码的元数据
本质一:附属品,依赖其他元素存在(方法,类,字段,接口等)
本质二:由外部程序解析产生作用。
注解的分类:
运行机制划分:source 源码注解;class 编译时注解; Runtime 运行时注解
按来源划分:内置注解;第三方注解;自定义注解
注解的使用:
eg:
自定义注解
@Target(ElementType.METHOD,ElementType.TTPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface cacheResult{
String key();
String cacheName();
String backupCacgeName() default "";
boolean needBloomFilter() default false;
boolean needlock() default false;
}
使用
@cacheResult(key="class-key",cacheName="class-cn")
public class OrderDetailServiceImpl{}
获取注解信息
- 使用JDK反射获取注解信息
- spring容器中获取注解信息
AOP+自定义注解搭配使用
参考几篇文章感觉aop+自定义注解对比单纯使用Aop的好处
- 每个接口都充斥着重复的代码,有没有办法提取这部分代码,做到统一管理呢?答案是使用
Spring aop
面向切面执行这段公共代码。 - 单纯的使用AOP充斥着 硬编码 的味道,有些场景会要求在接口响应结束后,打印日志信息,保存到数据库,甚至要把日志记录到
elk
日志系统等待,同时这些操作要做到可控,有没有什么操作可以直接声明即可?答案是使用自定义注解
,声明式的处理访问日志。 - 表达切入点的表达式问题。原因如下
在切面类DemoAspect中,我们看到了切入点的设置
@Pointcut("execution(public * com.jackie.springbootdemo.controller.HelloController.test*(..))")
public void addAdvice(){}
其中Pointcut后面的表达式是用于控制切面的有效影响范围。
**表达式中,第一个表示返回任意类型,第二个表示任意方法名,后面的小括号表示任意参数值,这里是以test为前缀的,所以可以匹配上test1和test2方法。
注意,在第二个之前也可以再有个,即HelloController所在位置,表示任意类名,假如这里是有两个*.则表示包括包里面的子包。**
好了,明白了表达式的含义,我们自然就看到了AOP的局限性。
当我们要使用切面前,就要写好表达式,但是项目一直在做,代码一直在加,那谁能保证后面接收代码的兄弟也正好知道这个test前缀的意义这么重大呢?
如果他非要用hello作为前缀,那么本应该匹配到的接口就匹配不上了,日志也就不能正常打印了。
这时候,自定义注解,就能够很好的解决这个问题
个人能力有限推荐下感觉还行的几篇文章
https://blog.csdn.net/king_kgh/article/details/75270558 ( 小demo )
https://www.jianshu.com/p/814e30454616 ( 案例 )
https://www.cnblogs.com/bigdataZJ/p/springboot-aop.html ( springBoot实践 )