配置AOP标签

在配置文件中配置了以下标签,即可开启AOP:

<aop:aspectj-autoproxy />

此标签有以下两个属性:

<aop:aspectj-autoproxy proxy-target-class="false" expose-proxy="false"/>

开启AOP之后:会使用AspectJAutoProxyBeanDefinitionParser()解析器进行解析

解析器初始化的操作:

public class AopNamespaceHandler extends NamespaceHandlerSupport {public AopNamespaceHandler() {}public void init() {this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());}
}

这些解析器都是对BeanDefinitionParser接口的实现,所以入口都是parse()方法。

BeanDefinitionParser接口源码:

public interface BeanDefinitionParser {BeanDefinition parse(Element var1, ParserContext var2);
}

一旦遇到aspectj-autoproxy就会使用AspectJAutoProxyBeanDefinitionParser解析器进行解析:

AspectJAutoProxyBeanDefinitionParser解析器源码:

class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {AspectJAutoProxyBeanDefinitionParser() {}// 解析器的入口public BeanDefinition parse(Element element, ParserContext parserContext) {// 注册AnnotationAutoProxyCreatorAopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);// 对注解的子类处理,扩展操作this.extendBeanDefinition(element, parserContext);return null;}//...省略其他源码
}

主要是registerAspectJAnnotationAutoProxyCreatorIfNecessary这个方法,以下是这个方法的源码:

// 注册AnnotationAutoProxyCreator
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {// 注册或者升级BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));// 对于proxy-target-class和expose-proxy属性的处理useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);// 注册组件并通知,便于监听器做进一步处理registerComponentIfNecessary(beanDefinition, parserContext);
}

下面分别是registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法的源码和useClassProxyingIfNecessary()方法的源码

1、注册AnnotationAwareAspectJAutoProxyCreator自动代理创建器或者升级自动代理创建器为AnnotationAwareAspectJAutoProxyCreator自动代理创建器

对于AOP的实现基本上都是靠AnnotationAwareAspectJAutoProxyCreator去完成的

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(Class cls, BeanDefinitionRegistry registry, Object source) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");// 如果已经存在自动代理创建器if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");//如果自动代理创建器与现在的不一致,需要根据优先级来判断到底需要使用哪个if (!cls.getName().equals(apcDefinition.getBeanClassName())) {// 获取当前的自动代理创建器的优先级int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());// 获取AnnotationAwareAspectJAutoProxyCreator自动代理创建器的优先级int requiredPriority = findPriorityForClass(cls);// 如果优先级小于AnnotationAwareAspectJAutoProxyCreator自动代理创建器的优先级,则将当前的升级为AnnotationAwareAspectJAutoProxyCreator自动代理创建器,大于则不需要升级if (currentPriority < requiredPriority) {// 改变bean最重要的就是改变bean所对应的className属性 apcDefinition.setBeanClassName(cls.getName());}}// 当前的的自动代理创建器就是AnnotationAwareAspectJAutoProxyCreator自动代理创建器,不在创建return null;} else {// 不存在自动代理创建器,创建AnnotationAwareAspectJAutoProxyCreator自动代理创建器RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);beanDefinition.setSource(source);beanDefinition.getPropertyValues().add("order", -2147483648);beanDefinition.setRole(2);registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);return beanDefinition;}
}

2、对于proxy-target-class和expose-proxy属性的处理

private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {if (sourceElement != null) {boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute("proxy-target-class")).booleanValue();// 处理proxy-target-class属性if (proxyTargetClass) {AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);}boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute("expose-proxy")).booleanValue();// 处理expose-proxy属性if (exposeProxy) {AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);}}
}

proxy-target-class属性:用来设置JDK动态代理和CGLIB动态代理之间的切换

<aop:aspectj-autoproxy proxy-target-class="false"/>

默认为false表示使用JDK动态代理。如果实现了至少一个接口,Spring会优先选择使用JDK动态代理,若果没有实现任何接口,则spring会选择CGLIB动态代理,强制使用CGLIB动态代理,使用以下配置:

<aop:aspectj-autoproxy proxy-target-class="true"/>

epose-proxy属性:暴露当前的代理对象

springAOP 只会拦截public方法,不会拦截provided和private方法,并且不会拦截public方法内部调用的其他方法,也就是说只会拦截代理对象的方法,即增强的是代理对象,而不是原对象。

<aop:aspectj-autoproxy expose-proxy="true"/>

通过上面的设置就可以暴露出代理对象,拦截器会获取代理对象,并且将代理对象转换成原对象。从而对内部调用的方法进行增强。


声明:本文是自己学习《Spring 源码深度解析》一书的笔记,为了给自己加深印象。

配置Spring AOP aspectj-autoproxy标签源码解析相关推荐

  1. Spring AOP 增强器获取的源码解析

    Spring AOP 增强器获取的源码解析 转载于:https://juejin.im/post/5c2b230ae51d45778a5cad3e

  2. Spring 事务源码(2)—<tx:annotation-driven/>事务标签源码解析

      基于最新Spring 5.x,详细介绍了Spring 事务源码,包括< tx:annotation-driven/>标签源码解析.   此前我们已经学习了Spring的<tx:a ...

  3. Spring Boot 核心原理与源码解析 - 目录

    准备重新写 SpringBoot 配置文件解析原理 , 先在这里把要写的内容记下来 Spring Boot 核心原理与源码解析 - 目录 1\何时解析\如何解析 application.propert ...

  4. Spring源码深度解析(郝佳)-学习-Spring消息-整合RabbitMQ及源码解析

      我们经常在Spring项目中或者Spring Boot项目中使用RabbitMQ,一般使用的时候,己经由前人将配置配置好了,我们只需要写一个注解或者调用一个消息发送或者接收消息的监听器即可,但是底 ...

  5. Spring源码深度解析(郝佳)-Spring 常用注解使用及源码解析

      我们在看Spring Boot源码时,经常会看到一些配置类中使用了注解,本身配置类的逻辑就比较复杂了,再加上一些注解在里面,让我们阅读源码更加难解释了,因此,这篇博客主要对配置类上的一些注解的使用 ...

  6. @Import注解:导入配置类的四种方式源码解析

    微信搜索:码农StayUp 主页地址:https://gozhuyinglong.github.io 源码分享:https://github.com/gozhuyinglong/blog-demos ...

  7. springsecurity sessionregistry session共享_要学就学透彻!Spring Security 中 CSRF 防御源码解析...

    今日干货 刚刚发表查看:66666回复:666 公众号后台回复 ssm,免费获取松哥纯手敲的 SSM 框架学习干货. 上篇文章松哥和大家聊了什么是 CSRF 攻击,以及 CSRF 攻击要如何防御.主要 ...

  8. 要学就学透彻!Spring Security 中 CSRF 防御源码解析

    上篇文章松哥和大家聊了什么是 CSRF 攻击,以及 CSRF 攻击要如何防御.主要和大家聊了 Spring Security 中处理该问题的几种办法. 今天松哥来和大家简单的看一下 Spring Se ...

  9. Spring Framework 核心原理与源码解析-大纲

    读Spring Framework的源码的目的是什么? Spring源码阅读的难度在于其呢内容庞大,并不是里面有很复杂的算法,需要高智商才能理解.所以你搞懂了Spring的源码并不能说明你有多聪明,但 ...

  10. spring注解方式整合Dubbo源码解析

    系列文章目录 前言 本节我们的Dubbo源码版本基于2.6.x 在前一章我们的整合案例中,我们有几个比较关键的步骤: 在启动类上标注了@EnableDubbo注解 在provider类上面标注了@Se ...

最新文章

  1. Asp.Net中查询域名的Whois信息
  2. golang 数据类型之间的转换
  3. python pip-python的pip安装以及使用教程
  4. 做一个公众号大概要多少钱_公众号流量主一个月可以赚多少钱?
  5. TypeError: Object of type ‘datetime‘ is not JSON serializable
  6. 惠普:存储为未来而设计
  7. rabbit mq 入门
  8. 数据结构 10分钟让你掌握经典排序(一)
  9. 功放前级的左右_TDG Audio达芬奇:什么是前级,后极?
  10. searchBar没有光标解决方法
  11. outlook与shairepoint2010 数据同步
  12. HTML5:web socket 和 web worker
  13. visio转换html,【转】5款替代微软Visio的开源免费软件
  14. 软件架构之分层模式 Layered Architecture
  15. Python—猫眼电影票房爬虫实战 轻松弄懂字体反爬!
  16. cdr 表格自动填充文字_Excel表格设置生成自动填充序号、编号
  17. 碰撞的小球(100分)
  18. 正则表达式在线测试网站推荐
  19. Java数据结构和算法-图
  20. Linux中nexus使用ccproxy进行代理下载包

热门文章

  1. php 获取windows进程,PHP获取python进程并终止它。Xamp/Windows
  2. 以太坊EVM智能合约交易信息中Input和Logs解码
  3. 2021年安全生产模拟考试(全国特种作业操作证高处作业-高处安装维护拆除模拟考试题库二)安考星
  4. 输出的字体全部变成繁体字
  5. pmp项目管理师证书有什么用?
  6. cocos creator pc web端 全屏
  7. 嵌入式分享合集106
  8. 大数据开发有哪些难点?
  9. tomcat启动失败!‘Staring Tomcat v8.0 Server at localhost' has encountered a problem. failed to start
  10. 苹果手机绕过密码和指纹自动支付,细思极恐!