转载请注明出处:https://blog.csdn.net/zknxx/article/details/80724180 在开始这个系列之前大家先想一下我们是怎么在项目中使用SpringAOP的(这里的分析都是基于AspectJ注解的)。我们需要在我们的Spring配置文件中引入SpringAOP的命名空间和标签,然后定义切面Bean,进行AOP配置。大概如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"<!--AOP的命名空间-->xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!--开启自动包扫描--><context:component-scan base-package="com.zkn.spring.learn.aop.spring"/><!--使用AspectJ注解--><aop:aspectj-autoproxy/>
</beans>
复制代码

我们在使用Spring中不同的功能的时候可能会引入不同的命名空间比如xmlns:context,xmlns:aop,xmlns:tx等等。关于命名空间的东西我们这里先不多说。在Spring中定义了一个这样的抽象类专门用来解析不同的命名空间。这个类是NamespaceHandler,我们看一下这个和这个类相关的一些子类:

在不同的命名空间实现类中定义了不同类型的实现类,这些实现类主要是用来初始化一些解析对应的标签的类。比如我们接下来要分析的AopNamespaceHandler这个类。在上面关于AOP的配置中,我们使用了一个AOP的标签:

<aop:aspectj-autoproxy/>
复制代码

为什么我们只要使用这个标签,就可以使用SpringAOP的功能呢?看一下AopNamespaceHandler这个类的内容你就会明白了:

public class AopNamespaceHandler extends NamespaceHandlerSupport {@Overridepublic void init() {// In 2.0 XSD as well as in 2.1 XSD.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());//我们看到了这样的一段代码  aspectj-autoproxy这个再加上aop 是不是就是 aop:aspectj-autoproxy呢//这段代码的意思是使用AspectJAutoProxyBeanDefinitionParser来解析aop:aspectj-autoproxy标签//AspectJAutoProxyBeanDefinitionParser这个类就是SpringAOP和Spring框架结合的关键registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());// Only in 2.0 XSD: moved to context namespace as of 2.1registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());}}
复制代码

PS:每个框架对应的NamespaceHandler就是你分析Spring中的对应框架的关键入口。 下面我们来分析一下AspectJAutoProxyBeanDefinitionParser这个类。先看一下它的parse方法。

    public BeanDefinition parse(Element element, ParserContext parserContext) {//这个地方是向ApplicationContext中注入使用AspectJ注解自动创建代理对象的beanAopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);extendBeanDefinition(element, parserContext);return null;}
复制代码

AopNamespaceUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary的方法内容如下:

   public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {//parserContext.getRegistry()这个是获取到的全局的BeanDefinitionRegistry//我们看这个方法做了什么BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));//这两个方法的内容一看就知道是什么意思了 就先不分析了useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);registerComponentIfNecessary(beanDefinition, parserContext);}
复制代码

AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary

 public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source)   {//这里传入了一个AnnotationAwareAspectJAutoProxyCreator的classreturn registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);}private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");//这里先判断是不是已经注入过name为org.springframework.aop.config.internalAutoProxyCreator的BeanDefinition了if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {//如果已经注入过了 判断之前注入的BeanDefinition的Class和传入的Class是不是一致BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);if (!cls.getName().equals(apcDefinition.getBeanClassName())) {//如果不一致的话 则取他们的优先级int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());int requiredPriority = findPriorityForClass(cls);//优先级高的生效 这个优先级 一会儿说if (currentPriority < requiredPriority) {apcDefinition.setBeanClassName(cls.getName());}}return null;}//如果之前没有向BeanDefinitionRegistry中注入过此beanname的BeanDefinition//那就创建一个新的BeanDefinition添加到BeanDefinitionRegistry中RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);beanDefinition.setSource(source);beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);return beanDefinition;}
复制代码

我们上面提到了一个优先级的东西,那这个优先级是在哪儿定义的呢?在AopConfigUtils中有这样的一段代码:

   static {APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);}
复制代码

在AopConfigUtils初始化的时候就会向APC_PRIORITY_LIST中添加这三个Class类。而上面提到的优先级就是他们在APC_PRIORITY_LIST中的位置。由此可见AspectJAwareAdvisorAutoProxyCreator会覆盖InfrastructureAdvisorAutoProxyCreatorBeanDefinition中的class,而AnnotationAwareAspectJAutoProxyCreator又会覆盖AspectJAwareAdvisorAutoProxyCreator的BeanDefinition中的class(当然也会覆盖InfrastructureAdvisorAutoProxyCreator的BeanDefinition)。而我们在上面传入的Class是AnnotationAwareAspectJAutoProxyCreator,即是优先级最大的Class。说了半天,这三个Class都有什么用呢?和我们今天说的SpringAOP又有什么关系呢?通过上面的分析,我们只知道使用

<aop:aspectj-autoproxy/>
复制代码

会向BeanDefinitionRegistry中注入一个beanClass为AnnotationAwareAspectJAutoProxyCreator的Bean。 我们先来看一下这三个类的关系:

我们发现他们三个是同一个类的子类:AbstractAdvisorAutoProxyCreator,这个类的作用是创建代理对象并为每个代理对象找到合适的Advisor(这一部分的东西可以参考前面的博文),那么它的子类也具有相同的功能。AnnotationAwareAspectJAutoProxyCreator主要是为AspectJ注解服务的,InfrastructureAdvisorAutoProxyCreator是一个基础建设性的类,即识别不使用AspectJ注解的AOP配置(比如事务的实现)。OK,我们在上废话了一大堆其实就是说了一件事:那就是在Spring启动的时候会使用AopNamespaceHandler和AspectJAutoProxyBeanDefinitionParser来解析AOP标签,并注入对应的BeanDefinition(AnnotationAwareAspectJAutoProxyCreator和InfrastructureAdvisorAutoProxyCreator)。 我们在项目中使用AspectJ注解比较多,所以我们在下篇文章中会分析一下AnnotationAwareAspectJAutoProxyCreator这个类。 转载请注明出处:https://blog.csdn.net/zknxx/article/details/80724180

转载于:https://juejin.im/post/5b61c69f6fb9a04f8c5ef4d5

Spring系列之Spring框架和SpringAOP集成过程分析(十)相关推荐

  1. Spring系列 1.Spring概述及IOP

    Spring概述 简介 Spring : 春天 ->给软件行业带来了春天 2002年,Rod Jahnson首次推出了Spring框架雏形interface21框架. 2004年3月24日,Sp ...

  2. Spring系列之Spring Web MVC-20

    目录 Spring Web MVC DispatcherServlet 上下文层次结构 特殊Bean Web MVC 配置 程序配置 工作原理 异常 视图解析 配置 重定向 转发 内容协商 过滤器 F ...

  3. Spring系列之Spring常用注解总结

    参看博客:https://www.cnblogs.com/xiaoxi/p/5935009.html 传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop.事物,这么做有两个缺 ...

  4. 【Spring 系列】Spring知识地图

    文章目录 Spring IOC 知道 会用 熟练 掌握 专家 Spring AOP 知道 会用 熟练 掌握 专家 Spring MVC 知道 会用 熟练 掌握 专家 Spring WebFlux 知道 ...

  5. Spring系列之Spring常用注解总结 原文:https://www.cnblogs.com/xiaoxi/p/5935009.html

    传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop.事物,这么做有两个缺点: 1.如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大:如果按需求分开.xml文 ...

  6. Spring系列之一 Spring MVC

    摘要: 最近在看Spring的书,之前一直跟着项目做,虽然项目用到了Spring的很多功能,但是我很少有机会在工作的项目中去配置Spring.感觉只有理论是不够的,虽然只是用Spring的配置让人感觉 ...

  7. Spring系列(六) Spring Web MVC 应用构建分析

    DispatcherServlet DispatcherServlet 是Spring MVC的前端控制器名称, 用户的请求到达这里进行集中处理, 在Spring MVC中, 它的作用是为不同请求匹配 ...

  8. 【Spring系列】- Spring循环依赖

    Spring循环依赖

  9. 【Spring系列】 Spring注解方式实现IOC、DI及其Spring其他注解

    文章目录 注解回顾 JDK内置注解 自定义注解 1.声明一个注解类,由`@interface`修饰 2.通过元注解修饰注解的定义 `@Target`:(常用) `@Retention`:(常用) `@ ...

最新文章

  1. ubuntu16.04 安装微信和qq
  2. 程序员职场第二次课笔记 9.9号
  3. 市面上常见的TCP/IP以太网一卡通设备硬件产品电路拆解分析
  4. 为何互联网大厂热衷于春节撒红包?谁才是最大赢家?
  5. linux——用脚本实现全自动安装虚拟机
  6. Linux将硬盘转化为pv,Linux扩展硬盘 物理卷(PV) 卷组(VG) 逻辑卷(LV)
  7. 浪擎全融合灾备云获大数据安全领域最佳创新奖
  8. java工作笔记018---java中BigDecimal小数位数的四舍五入等操作
  9. C核心技术手册(二十八)
  10. Monkey Test
  11. sqlserver数据库置疑处理
  12. Mac软件下载提示:“已损坏,无法打开”解决办法
  13. 计算机视觉之基本概论
  14. PPP和PDP激活区别
  15. 紧贴潮流,初心未改:OpenInfra Days China升级回归,打造专属OpenStackers的开源大趴
  16. 数学基础知识总结 —— 7. 行列式的基本知识
  17. tkinter 设置不可编辑_jquery 设置页面元素不可点击、不可编辑、只读(备忘)
  18. 【技能】小白耳机维修入门--各种耳机插头接线图--耳机维修汇总贴
  19. sym8 matlab,【Matlab学习手记】sym8小波滤波
  20. html鼠标滑过导航条展开导航条,JS+CSS实现鼠标滑过时动态翻滚的导航条效果

热门文章

  1. MySql: 常见错误
  2. windows如何卸载Oracle
  3. schema类SpringMVC+Hibernate+Spring整合(二)
  4. C++ 随机函数----谈rand() 和 srand() 体会
  5. Linq To select
  6. Vuebnb:一个用vue.js和Laravel构建的全栈应用
  7. mybatis 中#与$的区别
  8. 中国大唐集团公司的发展战略
  9. ZooKeeper伪分布式集群安装及使用
  10. 政府和银行运维的差异