文章结构

  • 获取增强器
    • 获取候选的增强器
    • 查找适配当前bena的增强器

增强方法的获取代码:

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {// 查找"候选的"增强方法List<Advisor> candidateAdvisors = findCandidateAdvisors();// 查找适应当前bean的增强方法List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);// 拓展advisorsextendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {// 排序eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;
}

对于增强方法的处理,首先是获取了"候选的"增强方法,然后缩小范围,获取了适应当前bean使用的增强方法。
所谓的适配就是指是不是符合切入点表达式。
这里可以猜测到获取"候选的"增强肯定是被缓存起来的。

获取增强器

获取候选的增强器

public List<Advisor> findAdvisorBeans() {// 是否已经被缓存过String[] advisorNames = this.cachedAdvisorBeanNames;if (advisorNames == null) {// 查找容器中所有实现了Advisor的beanNamesadvisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);this.cachedAdvisorBeanNames = advisorNames;}if (advisorNames.length == 0) {return new ArrayList<>();}List<Advisor> advisors = new ArrayList<>();for (String name : advisorNames) {// 实例化Advisor类型的bean,并把它们加入到advisors中advisors.add(this.beanFactory.getBean(name, Advisor.class));}return advisors;
}

查找适配当前bena的增强器

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {if (candidateAdvisors.isEmpty()) {return candidateAdvisors;}List<Advisor> eligibleAdvisors = new ArrayList<>();for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {eligibleAdvisors.add(candidate);}}boolean hasIntroductions = !eligibleAdvisors.isEmpty();for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor) {// already processedcontinue;}if (canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors;
}

看了方法的内容无非就是遍历"候选增强器",虽然是2个循环,但是主要不同点是canApply方法的参数不同。
那么需要看下canApply方法。

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {if (advisor instanceof IntroductionAdvisor) {return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);}else if (advisor instanceof PointcutAdvisor) {// 一般都是这个类型PointcutAdvisor pca = (PointcutAdvisor) advisor;return canApply(pca.getPointcut(), targetClass, hasIntroductions);}else {// It doesn't have a pointcut so we assume it applies.return true;}
}

canApply方法分类判断了IntroductionAdvisor类型和PointcutAdvisor类型2种情况。
IntroductionAdvisor类型的直接就执行了matches方法,而PointcutAdvisor代码如下:

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {// 添加目标类的所有接口,既然后续查找了所有的方法那么这是有必要???classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));for (Class<?> clazz : classes) {// 递归查找 clazz的所有方法Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);for (Method method : methods) {if (introductionAwareMethodMatcher != null ?introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :methodMatcher.matches(method, targetClass)) {return true;}}}return false;
}

看到最后我们还是发现最后是调用了matches方法进行匹配,如果匹配上说明增强器适配当前的bena,匹配不上则不适配。而对于matches就不什么研究了。
猜测是matches调用了底层aop表达式解析方法进行了适配。

到这里我们不免提出几个疑问:

  • @Before等注解在哪里处理的,肯定是我们在哪里遗漏了
  • 我们多次在"增强器适配"的方法中看到了分类谈论,如按candidate类型分类而且似乎就是分为2类
    下面讲解决一下上面的几个疑问。

传送门:保姆式Spring5源码解析

欢迎与作者一起交流技术和工作生活

联系作者

AOP 原理分析《四》- 获取增强器相关推荐

  1. MyBatis原理分析之获取SqlSession

    流程原理分析系列: MyBatis原理分析之获取SqlSessionFactory MyBatis原理分析之获取SqlSession MyBatis原理分析之获取Mapper接口的代理对象 MyBat ...

  2. AOP 原理分析《五》- 增强器获取的细节补充

    文章结构 获取增强器细节补充 先介绍下几个核心类 再介绍不同类型的增强器(Advice): 说明上文为何在源码没有看到@Before注解等 补充说明一下增强器的分类 总结获取增强器 获取增强器细节补充 ...

  3. 史上最烂 spring aop 原理分析

    盗引·中篇·spring aop spring aop: jdk 动态代理和 cglib 动态代理的特点.区别.使用方式.原理及各自对反射的优化.二者在 spring 中的统一.通知顺序.从 @Asp ...

  4. 动态代理、CGlib、AOP原理分析与实现

    Java 代理模式实现方式,主要有如下五种方法 静态代理,工程师编辑代理类代码,实现代理模式:在编译期就生成了代理类. 基于 JDK 实现动态代理,通过jdk提供的工具方法Proxy.newProxy ...

  5. spring AOP原理分析:静态代理;JDK实现接口动态代理;Cglib继承父类代理;SpringAop的责任链模式调用

    普通静态代理 代理类和真实类都需要实现同一个接口 接口 package com.fchan.layui.represent.service; /*** 静态代理demo*/ public interf ...

  6. Spring事务原理分析(一)--@EnableTransactionManagement 到底做了什么?

    目录 一.概述 二.事务的ACID属性 三.事务的隔离级别 四.事务的传播行为 五.Spring声明式事务环境搭建 六.@EnableTransactionManagement分析 七.AutoPro ...

  7. xposed hook java_[原创]Android Hook 系列教程(一) Xposed Hook 原理分析

    章节内容 一. Android Hook 系列教程(一) Xposed Hook 原理分析 二. Android Hook 系列教程(二) 自己写APK实现Hook Java层函数 三. Androi ...

  8. Spring3.1.0实现原理分析(七).填充Bean属性,初始化Bean,登记善后处理,注册单例Bean

    大家好,上篇博客我较详细分析了实例化过程,今天继续探讨实例化之后的其它步骤,分别是"填充Bean属性","初始化Bean","登记善后处理" ...

  9. Spring3.1.0实现原理分析(七).填充Bean属性,初始化Bean,登记善后处理,注册单例Bean...

    大家好,上篇博客我较详细分析了实例化过程,今天继续探讨实例化之后的其它步骤,分别是"填充Bean属性","初始化Bean","登记善后处理" ...

最新文章

  1. Python+OpenCV实现AI人脸识别身份认证系统(3)—训练人脸识别模型
  2. 四、HTTP响应报文格式
  3. python 保留两位小数 实现方法
  4. 比一比Nmap、Zmap、Masscan三种扫描工具
  5. 鸡肋工具-Oracle建表工具
  6. 【One by One系列】IdentityServer4(二)使用Client Credentials保护API资源
  7. 多变量逻辑回归python_Python实现逻辑回归(Logistic Regression in Python)
  8. STM32F407之常识
  9. CentOS 搭建简单svn服务器【转】
  10. 微软 Windows 10 将支持 8 英寸以下 ARM 平板设备
  11. 一句话搞懂JavaSE、JavaEE和JavaME之间的区别
  12. FreeRTOS可视化追踪软件 —— 破解Tracealyzer 4.2.12
  13. 欧姆龙服务器数码管不显示问题,TM1640驱动数码管不显示问题
  14. C#实现在FastReport报表中添加电子图章
  15. 我国最高山峰是珠穆朗玛峰,8848米。现在我有一张足够大的纸,它的厚度是0.01米。请问,我折叠多少次,可以折成珠穆朗玛峰的高度?
  16. 【VMware Fusion】如何配置VMware Fusion中的Vmnet网卡
  17. html自动移动滚动条,css如何实现div随滚动条移动?
  18. Conclusion for Inheritance and Object Oriented Design
  19. 数学建模层次分析法一致性检验建立
  20. PVS-Vdisk升级tools

热门文章

  1. 《视觉SLAM十四讲》读书笔记(三)
  2. (六)从零开始学人工智能-搜索:对抗搜索
  3. nginx根据二级域名转发不同的地址
  4. cf两边黑屏怎么解决win10_Win10屏幕两边有黑框怎么全屏
  5. 生成视频的活动要求在edius里如何设置
  6. Android短信大全
  7. 公务员考试知识点总结_判断
  8. 出师未捷身先死 常使英雄泪满襟——记伍楚华
  9. matlab中内插cubic,matlab中二维插值中cubic方法的实现原理(个人见解)
  10. Uboot引导系统启动优化