自定义注解、AOP实例

目录
一、学习自定义注解
二、自己编写一个注解,并在controller上使用这个注解,看一下5种通知类型的调用顺序。
三、过滤器、拦截器、AOP的区别

一、学习自定义注解

自定义注解常用在日志,权限,加密等场景下。
我们使用最常见的@SpringbootApplication,看一下注解的定义中会用到哪些注解。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
  • @Documented 注解
    指明修饰的注解,可以被例如javadoc此类的工具文档化,只负责标记,没有成员取值。

  • @Retention 注解

    指明修饰的注解的生存周期,即会保留到哪个阶段。
    RetentionPolicy的取值包含以下三种:
    SOURCE:源码级别保留,编译后即丢弃
    CLASS:编译级别保留,编译后的class文件中存在,在jvm运行时丢弃,这是默认值。
    RUNTIME: 运行级别保留,编译后的class文件中存在,在jvm运行时保留,可以被反射调用。
    
  • @Target 注解

    指明了修饰的这个注解的使用范围,即被描述的注解可以用在哪里。
    ElementType的取值包含以下几种:
    TYPE:类,接口或者枚举
    FIELD:域,包含枚举常量
    METHOD:方法
    PARAMETER:参数
    CONSTRUCTOR:构造方法
    LOCAL_VARIABLE:局部变量
    ANNOTATION_TYPE:注解类型
    PACKAGE:包
    

二、自己编写一个注解,并在controller上使用这个注解,看一下5种通知类型的调用顺序。

MyAnnotation.java(我自定义的一个测试注解)

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public  @interface MyAnnotation {
    String value() default "";
}

MyAnnotationInterceptor.java(自定义测试注解的拦截器)

/**
 * MyAnnotation注解对应的拦截器
 * AspectJ 支持 5 种类型的通知注解:
 *
 * @Before: 前置通知, 在方法执行之前执行
 * @After: 后置通知, 在方法执行之后执行
 * @AfterRunning: 返回通知, 在方法返回结果之后执行
 * @AfterThrowing: 异常通知, 在方法抛出异常之后
 * @Around: 环绕通知, 围绕着方法执行
 **/
@Component
@Aspect
public class MyAnnotationInterceptor {
    public static final Logger logger = LoggerFactory.getLogger(MyAnnotationInterceptor.class);

    @Pointcut("@annotation(com.lbc.demo.aop.MyAnnotation)")
    public void functionAspect() {

    }

    @Around(value = "functionAspect()")
    public void doAround(ProceedingJoinPoint pjp) throws Throwable {
        logger.info("around执行方法之前");
        Object object = pjp.proceed();
        logger.info("around执行方法之后--返回值:" + object);
    }

    @Before("functionAspect()")
    public void doBefore(JoinPoint joinPoint) {
        logger.info("doBefore");
    }

    @After("functionAspect()")
    public void doAfter(JoinPoint joinPoint) {
        logger.info("doAfter");
    }

    @AfterReturning(returning = "returnObj", pointcut = "functionAspect()")
    public void doAfterReturning(JoinPoint joinPoint, Object returnObj) {
        logger.info("AfterReturning");
    }

    @AfterThrowing(value = "functionAspect()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
        logger.info("AfterThrowing");
    }
}
执行结果:
image.png
直接放结论:
  • 正常情况


    image.png
  • 异常情况


    image.png
@Order注解的作用:
  • @Order(Ordered.HIGHEST_PRECEDENCE)代表这个过滤器在众多过滤器中级别最高,也就是过滤的时候最先执行
  • @Order(Ordered.LOWEST_PRECEDENCE)恰恰相反,表示级别最低,最后执行过滤操作
@Inherited注解的作用:
  • 类继承关系中@Inherited的作用
    类继承关系中,子类会继承父类使用的注解中被@Inherited修饰的注解
  • 接口继承关系中@Inherited的作用
    接口继承关系中,子接口不会继承父接口中的任何注解,不管父接口中使用的注解有没有被@Inherited修饰
  • 类实现接口关系中@Inherited的作用
    类实现接口时不会继承任何接口中定义的注解

过滤器、拦截器、AOP的区别

过滤器
过滤器可以拦截到方法的请求和响应(ServletRequest request, SetvletResponse response),
并对请求响应做出响应的过滤操作,比如设置字符编码、鉴权操作。
拦截器
Spring中拦截器有三个方法:preHandle,postHandle,afterCompletion。
public boolean preHandle(HttpServletRequest httpServletRequest, 
HttpServletResponse httpServletResponse, Object o)
表示被拦截的URL对应的方法执行前的自定义处理

public void postHandle(HttpServletRequest httpServletRequest, 
HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView)
表示此时还未将modelAndView进行渲染,被拦截的URL对应的方法执行后的自定义处理,。

public void afterCompletion(HttpServletRequest httpServletRequest, 
HttpServletResponse httpServletResponse, Object o, Exception e)
表示此时modelAndView已被渲染,执行拦截器的自定义处理。
AOP切片
AOP操作可以对操作进行横向的拦截,最大的优势在于可以获取执行方法的参数,对方法进行统一的处理,常见使用日志,事务,请求参数安全验证等。

顺序
请求->>过滤器->>拦截器-->Aspect->>拦截器->>过滤器->>响应

三者使用场景类似
**从过滤器--》拦截器--》切面,拦截规则越来越细致,执行顺序依次是过滤器、拦截器、切面。**
一般情况下数据被过滤的时机越早对服务的性能影响越小,因此我们在编写相对比较公用的代码时,优先考虑过滤器,然后是拦截器,最后是aop。
比如权限校验,一般情况下,所有的请求都需要做登陆校验,此时就应该使用过滤器在最顶层做校验;日志记录,一般日志只会针对部分逻辑做日志记录,
而且牵扯到业务逻辑完成前后的日志记录,因此使用过滤器不能细致地划分模块,此时应该考虑拦截器,
然而拦截器也是依据URL做规则匹配,因此相对来说不够细致,因此我们会考虑到使用AOP实现,AOP可以针对代码的方法级别做拦截,很适合日志功能。

参考:https://www.jianshu.com/p/8cbfff715581
https://zhuanlan.zhihu.com/p/96597358
https://blog.csdn.net/u011277123/article/details/91532149
https://www.jianshu.com/p/7f54e7250be3
https://www.cnblogs.com/natian-ws/p/10824363.html
https://www.cnblogs.com/quartz/p/12601091.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343