一、注解的继承性回顾
  1. 被@Inherited元注解标注的注解标注在类上的时候,子类可以继承父类上的注解。
  2. 注解未被@Inherited元注解标注的,该注解标注在类上时,子类不会继承父类上标注的注解。
  3. 注解标注在接口上,其子类及子接口都不会继承该注解
  4. 注解标注在类或接口方法上,其子类重写该方法不会继承父类或接口中方法上标记的注解

根据注解继承的特性,我们再做AOP切面拦截的时候会遇到拦截不到的问题,今天我们就讲解下对这些特殊情况如何解决,对源码不做过渡深入的讲解。

二、注解标注在父类、接口、父类方法、接口方法上如何通过子类拦截,首先了解下几个核心类

AnnotationMatchingPointcut切点类是用来判定是否需要拦截类、父类、实现接口中方法,其中一共四个构造函数如下:

 /*** Create a new AnnotationMatchingPointcut for the given annotation type.* @param classAnnotationType the annotation type to look for at the class level*/
public AnnotationMatchingPointcut(Class<? extends Annotation> classAnnotationType) {this(classAnnotationType, false);}/*** Create a new AnnotationMatchingPointcut for the given annotation type.* @param classAnnotationType the annotation type to look for at the class level* @param checkInherited whether to also check the superclasses and interfaces* as well as meta-annotations for the annotation type* @see AnnotationClassFilter#AnnotationClassFilter(Class, boolean)*/public AnnotationMatchingPointcut(Class<? extends Annotation> classAnnotationType, boolean checkInherited) {this.classFilter = new AnnotationClassFilter(classAnnotationType, checkInherited);this.methodMatcher = MethodMatcher.TRUE;}/*** Create a new AnnotationMatchingPointcut for the given annotation types.* @param classAnnotationType the annotation type to look for at the class level* (can be {@code null})* @param methodAnnotationType the annotation type to look for at the method level* (can be {@code null})*/public AnnotationMatchingPointcut(@Nullable Class<? extends Annotation> classAnnotationType,@Nullable Class<? extends Annotation> methodAnnotationType) {this(classAnnotationType, methodAnnotationType, false);}/*** Create a new AnnotationMatchingPointcut for the given annotation types.* @param classAnnotationType the annotation type to look for at the class level* (can be {@code null})* @param methodAnnotationType the annotation type to look for at the method level* (can be {@code null})* @param checkInherited whether to also check the superclasses and interfaces* as well as meta-annotations for the annotation type* @since 5.0* @see AnnotationClassFilter#AnnotationClassFilter(Class, boolean)* @see AnnotationMethodMatcher#AnnotationMethodMatcher(Class, boolean)*/public AnnotationMatchingPointcut(@Nullable Class<? extends Annotation> classAnnotationType,@Nullable Class<? extends Annotation> methodAnnotationType, boolean checkInherited) {Assert.isTrue((classAnnotationType != null || methodAnnotationType != null),"Either Class annotation type or Method annotation type needs to be specified (or both)");if (classAnnotationType != null) {this.classFilter = new AnnotationClassFilter(classAnnotationType, checkInherited);}else {this.classFilter = new AnnotationCandidateClassFilter(methodAnnotationType);}if (methodAnnotationType != null) {this.methodMatcher = new AnnotationMethodMatcher(methodAnnotationType, checkInherited);}else {this.methodMatcher = MethodMatcher.TRUE;}}

以上四个构造函数,支持仅标记在类上注解、仅标记方法上的注解、即指定标记类上且标记在方法上的注解(是否拦截父类及接口上标记的方法)三种构造方式。

通过上述四个构造函数可以构造如下几种切点类型:

  • 注解标注在当前类,只拦截当前类的方法
  • 注解标注在当前类的父类上,拦截父类及子类中的方法
  • 注解标注在当前类实现的接口上 ,拦截接口方法的实现方法
  • 注解标注在当前类的方法上,拦截当前类的方法
  • 注解标注在当前类父类或接口的方法上,拦截父类的方法或者当前类实现方法。

通过上述切点可以构造出我们需要的大多数场景,如果需要更灵活的实现还需要结合ComposablePointcut类,此类可以实现类级别标注的交集、并集,方法级别的交集、并集,切点级别的交集并集。

三、切点实现案例

    @Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public Advisor mybatisLogAdvisor(MybatisProperties properties) {//限定类级别的切点Pointcut cpc = new AnnotationMatchingPointcut(Mapper.class, properties.isCheckClassInherited());//限定方法级别的切点Pointcut mpc = new AnnotationMatchingPointcut(null, Mapper.class, properties.isCheckMethodInherited());//组合切面(并集),一、ClassFilter只要有一个符合条件就返回true,二、Pointcut pointcut = new ComposablePointcut(cpc).union(mpc);//mybatis日志拦截切面MethodInterceptor interceptor = new MybatisMethodInterceptor();//切面增强类AnnotationPointcutAdvisor advisor = new AnnotationPointcutAdvisor(interceptor, pointcut);//切面优先级顺序advisor.setOrder(AopOrderInfo.MYBATIS);return advisor;}

此拦截器可以实现对标注了Mapper方法进行日志拦截,具体实现可以参考GitHub源码

四、上述向上查询父类、父接口及其方法的核心是AnnotatedElementUtils工具类,示例参考如下:

 //返回当前类或父类或接口方法上标注的注解对象
targetDataSource = AnnotatedElementUtils.findMergedAnnotation(method, TargetDataSource.class);
//返回当前类或父类或接口上标注的注解对象
targetDataSource = AnnotatedElementUtils.findMergedAnnotation(method.getDeclaringClass(), TargetDataSource.class);

GitHub地址:https://github.com/mingyang66/spring-parent

springboot切面AOP拦截父类或接口中标记注解的方法相关推荐

  1. SpringBoot切面AOP打印请求和响应日志

    1.说明 Spring Boot微服务对外开放的Restful接口, 为了方便定位问题, 一般需要记录请求日志和响应日志, 而在每个接口中开发日志代码是非常繁琐的, 本文介绍使用Spring的切面AO ...

  2. Java接口、implements关键字、接口中抽象方法,默认方法,静态方法,私有方法,常量、final关键字

    接口: 接口是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量.构造方法和成员方法,那么 接口的内部主要就是封装了方法,包含抽象方法(JDK 7及以前),默认方法和静态方法(JD ...

  3. java private 接口_java接口中 定义 private 私有方法

    在传统的Java编程中,被广为人知的一个知识点是:java Interface接口中不能定义private私有方法.只允许我们定义public访问权限的方法.抽象方法或静态方法.但是从Java 9 开 ...

  4. Java私有方法解释_java接口中 定义 private 私有方法

    在传统的Java编程中,被广为人知的一个知识点是:java Interface接口中不能定义private私有方法.只允许我们定义public访问权限的方法.抽象方法或静态方法.但是从Java 9 开 ...

  5. Java 8——接口中个的默认方法和静态方法

    在Java SE 8之前,interface只是事物的抽象,用来定义统一的抽象事物和描述事物的抽象行为和属性. 但是在Java SE 8中,增加了可以在interface中增加默认实现的行为和事物的静 ...

  6. java 打成war_JAVA语言之Springboot打成war包并在tomcat中运行的部署方法

    本文主要向大家介绍了JAVA语言的Springboot打成war包并在tomcat中运行的部署方法,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助. 把spring-boot项目按照平常 ...

  7. 设计一个接口, 并设计一个实现类实现该接口,演示它们的使用。具体,创建一个名称为Person的接口,在接口中定义两个方法sayHello()和sayBye()。

    设计一个接口, 并设计一个实现类实现该接口,演示它们的使用. 具体,创建一个名称为Person的接口,在接口中定义两个方法sayHello()和sayBye().然后,创建两个实现了Person接口的 ...

  8. spring面向切面aop拦截器

    spring中有很多概念和名词,其中有一些名字不同,但是从功能上来看总感觉是那么的相似,比如过滤器.拦截器.aop等. 过滤器filter.spring mvc拦截器Interceptor .面向切面 ...

  9. 验证码及登录切面Aop拦截代码

    首先定义验证码和登录监测的两个注解 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; im ...

最新文章

  1. SQLServer表内自关联级联删除
  2. 服务人员在Hybris ASM手动分配coupon给某个客户
  3. [JavaWeb]Web概念概述
  4. c++和c语言的区别_C与C++傻傻分不清楚,有啥区别,咋用,杂学?
  5. js怎么动态加载js文件(JavaScript性能优化篇)
  6. linux系统装psp,Linux上的PSP模拟器PPSSPP 1.7 发布了
  7. 在Vue中使用Echarts可视化库的完整步骤记录
  8. 利用函数指针实现累加
  9. Java生成简单的验证码图片
  10. 用html做龙卷风特效,利用HTML5实现Canvas龙卷风特效
  11. React基础之事件机制
  12. Unity程序员如何提升自己的能力
  13. Maven下载sources时报错java.lang.RuntimeException: Cannot reconnect
  14. 逆天神器!“国外“最新版本,直接一键破解所有WiFi密码,傻眼了!
  15. 易点易动【设备管理】产品全新上线
  16. 自注意力中的不同的掩码介绍以及他们是如何工作的?
  17. 第4章第15节:图表:使用饼图制作投资公司四季收益图表 [PowerPoint精美幻灯片实战教程]
  18. 《IT老外在中国》第22期:“中国餐桌”上的法式创新
  19. Android 如何OTG 鼠标,otg键盘和鼠标映射软件v5.2.0 Android版
  20. python趣味程序_python游戏趣味编程:疯狂的小圆圈

热门文章

  1. linux服务器安装mysql步骤详解
  2. XGBoost调参笔记
  3. python 实战之模仿开发QQ聊天软件(二)MySQL数据库的连接和使用
  4. ios的vn服务器未响应,iOS应用程序导致内部服务器错误
  5. 苹果发布Swift编程语言 - iOS移动开发周报
  6. 八位二进制数能表示数的范围以及原码、反码和补码含义
  7. Swift - GCD 和延时调用
  8. 华硕ezflash3找不到u盘_华硕ez flash 3
  9. 宝塔界面为什么无法访问_宝塔面板登陆不上?宝塔面板打不开解决办法
  10. 集训队每周一赛2020-03-06(思维+暴力)