当前位置: 首页 > 编程笔记 >

Spring学习教程之AOP模块的概述

满自明
2023-03-14
本文向大家介绍Spring学习教程之AOP模块的概述,包括了Spring学习教程之AOP模块的概述的使用技巧和注意事项,需要的朋友参考一下

概述

spirng-aop模块是Spring框架中的核心模块,虽然Spring Ioc container并不依赖AOP,但AOP给Ioc的实现提供了一种强大而灵活的解决方案。

在Spring Framework中,AOP主要是用于两种目的:

  • 提供一些 企业 级的声明式服务,典型的应用如 declarative transaction management .
  • 允许用户实现自己的aspects,用AOP的方式来帮助和补充OOP的功能及实现

AOP从功能的角度来讲,可能看作OOP编程方式的一种补充,提供了一种不同的代码或者系统组织方式。OOP中的核心概念是Class,而在AOP中则是Aspect。

spirng-aop模块是Spring框架中的核心模块,虽然Spring Ioc container并不依赖AOP,但AOP给Ioc的实现提供了一种强大而灵活的解决方案。

在Spring Framework中,AOP主要是用于两种目的:

  • 提供一些企业级的声明式服务,典型的应用如 declarative transaction management.
  • 允许用户实现自己的aspects,用AOP的方式来帮助和补充OOP的功能及实现

Spring AOP由纯Java实现,无须特殊的编译处理,也不需要控制类加载器的层次结构,所以它可以适用于Servlet Container和其它application server.

Spring AOP目前只支持方法级别的切换或拦截,属性的拦截现在不支持,如果想要拦截属性,可以考虑使用AspectJ语言。
Spring AOP的使用不同于其它大多数AOP框架。它的主要目的不是提供一套大而全的AOP实现,而是集成AOP不同实现协同Spring Ioc来帮助解决一些普遍性问题。

需要注意的是,一些细粒度的advised(如domain model),Spring AOP往往不能提供很好的支持,这场景也还是考虑AspectJ。即使如此,就普遍经验来说Spring AOP的强大机制依然能够解决大多数场景的问题。
那么该如何看待Spring AOP和AspectJ,引用Spring官方文档的原文:

Spring AOP will never strive to compete with AspectJ to provide a comprehensive AOP solution. We believe that both proxy-based frameworks like Spring AOP and full-blown frameworks such as AspectJ are valuable, and that they are complementary, rather than in competition. Spring seamlessly integrates Spring AOP and IoC with AspectJ, to enable all uses of AOP to be catered for within a consistent Spring-based application architecture. This integration does not affect the Spring AOP API or the AOP Alliance API: Spring AOP remains backward-compatible.

在Spring框架所有的模块设计中,始终遵守的核心信条之一是——无侵入性。

所以在使用Spring AOP时,不会强制我们在业务代码中引入特定类或者接口,可以最大限度的保持代码 clean and decouple。然而Spring也提供了另一种选择,如果有特定的场景需要的话,你可以在你的代码中直接引入Spring AOP。几乎所有Spring框架中的模块,在使用的方式上都会给你多种选择,以便让用户选择更适合自己场景的方式。使用AspectJ还是Spring AOP,使用annotation方式还是xml的配置方式,Depends On U。

了解了Spring AOP的初衷和使用场景,来看下它的大致实现原理

在软件世界中的绝大多数问题,都可以通过加一层来解决。

这里所说的层,当然是广义上的,可以是一层抽象,也可以是一层cache,大致含义是隔离和解耦的范畴。

在Spring的世界里,每一个模块的引入,或者第三方技术的集成,总会提供一个抽象层 ,对用户提供统一的API,屏蔽了所有的实现细节以及不同实现的差异。例如spring-cache,spring-jdbc,spring-jms以及spirng-messaging等模块都提供了一层抽象。

Spring AOP的实现是基于代理的机制,默认是采用Jdk dynamic proxy,也可以采用cglib的proxy。两者的区别主要是在于被代理的对象的不同。当目标对象是接口时,Jdk dynamic proxy可以完成代理,但目标对象是没有实现接口的类时(尽量少一些,面向接口编程是好习惯),是需要采用cglib proxy来完成代理的,当然你也可以强制接口也采用cglib来代理;另外需要注入或引用具体类型时,如果引用的东西恰恰是代理过的对象,此时也需要采用cglib的方式。

功能设计和实现上来可以分为两大块

  • aop基础设施的创建,可以看作是aopProxy的生成
  • aopProxy对象的调用时的处理拦截,即处理对目标对象的拦截器

AOP的创建

生成代理对象的核心类,ProxyFactoryBean getObjecct()

下图是生成代理时,是用Jdk还是cglib的选择逻辑:


找到了生成代理的具体执行者,那么这个操作是在什么时候被调用的呢,了解过Spring bean生命周期的都应该知道,bean在创建的时候,有一系列的回调接口供用户插入自定义的行为,来左右bean的一些特性,其中BeanPostProcessor是接口中的一种。以往的文章有介绍过(玩转Spring bean的终极利器)。而Spring AOP正是利用这个契机,在创建bean的过程中插了一手,如果正在创建的bean是我们aop的target,则创建代理,并最终把代理对象返回给Ioc。

AbstractAutoProxyCreator 这个类是一个BeanPostProcessor的实现,用来创建代理,来看这个处理器的后处理方法,最终是返回了createProxy()方法返回的代理


AOP切面的增强的执行

可以理解成对目标对象上所有拦截器链的调用

由于Spring AOP的代理具体实现有两种,JDK dynamic proxy和cglib,所以执行拦截器的方式有所不同,具体可以阅读源码JdkDynamicAopProxy类的invoke方法

对目标方法的调用最终是依靠ReflectiveMethodInvocation.

ReflectiveMethodInvocation中的proceed处理是采用递归的方式处理拦截器链

CglibAopProxy的 intercept方法

CglibMethodInvoation是继承了ReflectiveMethodInvocation,处理拦截器链也是用的上边的proceed()方法。

在使用Spring AOP时需要注意的两点细节:

1、在类内部的方法调用时(self-invoke),Spring AOP不起作用,原因是内部调用没通过代理对象,直接使用的目标对象。解决方法有:

  • 重构代码,避免内部调用
  • AopContext.currentProxy()
  • 或者干脆使用AspectJ语言吧...

2、在注入bean时,如果想注入bean的具体的类型而不是接口,那么采用cglib吧

Spring AOP的功能很强大,设计巧妙,这里梳理了主要脉络,细节不再一一讨论。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对小牛知识库的支持。

 类似资料:
  • 本文向大家介绍Laravel学习教程之本地化模块,包括了Laravel学习教程之本地化模块的使用技巧和注意事项,需要的朋友参考一下 前言 本文主要给大家介绍了关于Laravel本地化模块的相关内容,分享出来供大家参考学习,话不多说了,来一起看看详细的介绍吧。 本文是基于Laravel 5.4版本的本地化模块代码进行分析书写; 模块组成 下图展示了本地化模块各个文件的关系,并进行简要说明; Tran

  • 主要内容:1、AOP 基本概念,2、AOP(底层原理),3、AOP(JDK 动态代理),4、AOP(术语),5、AOP操作,6、AOP 操作(AspectJ 注解),7、有多个增强类对同一个方法进行增强,设置增强类优先级,8、AOP 操作(AspectJ 配置文件)1、AOP 基本概念 (1)面向切面编程(方面),利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得 业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。 (2)通俗描述:不通过修改源代码方式,在主干功能里

  • 本文向大家介绍Python 学习教程之networkx,包括了Python 学习教程之networkx的使用技巧和注意事项,需要的朋友参考一下 networkx是Python的一个包,用于构建和操作复杂的图结构,提供分析图的算法。图是由顶点、边和可选的属性构成的数据结构,顶点表示数据,边是由两个顶点唯一确定的,表示两个顶点之间的关系。顶点和边也可以拥有更多的属性,以存储更多的信息。 对于netwo

  • 本文向大家介绍socket.io学习教程之深入学习篇(三),包括了socket.io学习教程之深入学习篇(三)的使用技巧和注意事项,需要的朋友参考一下 前言 socket.io提供了基于事件的实时双向通讯,本文深入的介绍了socket.io,下面来看看详细的内容吧。 静态文件 socket.io默认情况下会通过socket.io-client包提供socket.io.min.js和socket.i

  • 本文向大家介绍spring cloud学习入门之config配置教程,包括了spring cloud学习入门之config配置教程的使用技巧和注意事项,需要的朋友参考一下 前言 本文主要给大家分享了关于spring cloud的入门教程,主要介绍了config配置的相关内容,下面话不多说了,来一起看看看详细的介绍吧。 简介 Spring cloud config 分为两部分 server clie

  • 本文向大家介绍NodeJS学习笔记之MongoDB模块,包括了NodeJS学习笔记之MongoDB模块的使用技巧和注意事项,需要的朋友参考一下 一,开篇分析 这篇属于扩展知识篇,因为在下面的文章中会用到数据库操作,所以今天就来说说它(Mongodb模块)。 (1),简介  MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。  Mo