作者 | 阿文

责编 | 屠敏

出品 | CSDN(ID:CSDNnews)

在 Spring 中 AOP 是一个非常非常重要的概念,那么什么是AOP呢?

AOP 即面向切面编程,也可以叫做面向方向编程,AOP不是一个新东西,它是OOP,即面向对象编程的一种补充,在当前已经成为一种成熟的编程方式。

为啥要使用 AOP

在学习AOP 之前,我们先了解下为啥我们要使用AOP?

那么,在传统的业务处理代码中,比如你要操作数据库,会进行事务的处理或者打印一些日志。虽然通过OOP 也可以实现,比如通过继承或组合的方式来达到代码的复用,但是如果实现某些功能,比如日志记录,相同的代码会分散到各个方法中,如果后面要想关闭某个功能或进行修改就必须要修改所有的方法,非常的不方便。

那么为了解决为了解决这个问题,AOP的思想随之产生。它采取了横向抽取机制。将分散在各个方法中的重复代码提取出来,然后在程序编译或运行时,再将这些提取出来的代码应用到需要执行的地方。这种采用横向提取机制的方式。是采用传统的AOP方式下无法办到的。因为传统的面向对象思想只能实现父子关系的纵向重用。

在AOP思想中,通过aspect(切面)可以分别在不同的类的方法中加入,例如事务日志权限和异常处理等功能。

使用切面这种横向方式。能够使开发人员在编写业务逻辑时专注于核心业务逻辑,而不用过度的关注与其他业务逻辑的实现。这样可以提高开发效率,同时还增强了代码的可维护性。

目前主流的AOP 框架有2个,分别是spring aop 和aspectJ,前者是纯Java 实现的,不需要专门的编译过程和类加载器,在运行期间可以通过代理的方式向目标内植入增强的代码。而AspectJ是一个基于Java语言的AOP框架。在Spring 2.0 开始,引入了对AspectJ 的支持,并提供了一个专门的编译器在编译时提供横向代码的植入。

相关术语

在了解AOP之前,首先要了解一下它的专业术语。这些术语包括Aspect、Joinpiont、Pointcut、Advice、Target Object、Proxy 和Weaving,对于这些专业术语具体的解释如下:

  • Aspect,切面在实际的应用中,切面通常是指封装的用于横向插入系统功能,比如事务日志的类,该类被spring容器识别为切面,需要在配置文件中通过\<bean\>来指定。

  • Joinpiont,连接点,在程序执行过程中的某个阶段点。它实际上是对象的一个操作,例如方法的调用或异常的抛出。在spring AOP中连接点就是指方法的调用。

  • Pointcut,切入点,切入点是指切面与程序流程的交叉点,即那些需要处理的连接点,通常在程序中切入点是指。类或者是方法名,比如说某个通知要应用到所有的以add开头的方法中。那么所有满足这一规则的方法都是切入点。

  • Adivce,通知增强处理,AOP 框架在特定的切入点执行增强处理,即在定义好的切入点处理所需要执行的程序代码,你可以理解其为切面类中的方法,它是切面的具体实现。

  • Target Object ,目标对象,是指所有通知的对象。也称为北增强对象。如果AOP框架采用的是动态的AOP实现,那么该对象就是一个被代理对象。

  • Proxy ,代理,将通知应用到目标对象之后被动态创建的对象。

  • Weaving, 织入,将切面代码插入目标对象上,从而生成代理对象的过程。

AspectJ 开发

使用AspectJ 实现AOP 的方式有

  • XML 声明

  • 注解

XML 声明

这种方式是通过XML文件来定义切面、切入点以及通知等,所有的切面、切入点和通知都必须定义在<aop:config>元素中,在<beans>元素中可以包含多个<aop:config>元素,一个 <aop:config> 中又可以包含子元素和属性,其子元素包含<aop:pointcut、<aop:advisor、<aop:aspect>,在配置时,需要严格按照顺序来定义,在<aop:aspect>下,同样包含属性和多个子元素,通过使用<aop:aspect>元素以及其子元素 可以在XML中配置切面、切入点和通知。如下所示

<?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:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.3.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.3.xsd"><!-- 1 目标类 --><bean id="userDao" class="com.ssm.aspectj.UserDaoImpl" /><!-- 2 切面 --><bean id="myAspect" class="com.ssm.aspectj.xml.MyAspect" /><!-- 3 aop编程 --><aop:config><!-- 1.配置切面 --><aop:aspect id="aspect" ref="myAspect"><!-- 2.配置切入点 --><aop:pointcut expression="execution(* com.ssm.aspectj.*.*(..))"    id="myPointCut" /><!-- 3.配置通知 --><!-- 前置通知 --><aop:before method="myBefore" pointcut-ref="myPointCut" /><!--后置通知--><aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="returnVal"/><!--环绕通知 --><aop:around method="myAround" pointcut-ref="myPointCut" /><!--异常通知 --><aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e" /><!--最终通知 --><aop:after method="myAfter" pointcut-ref="myPointCut" /></aop:aspect></aop:config>
</beans>

但是 XML 的配置过于复杂,因为日常开发过程中,我们更倾向于使用注解的方式来进行AOP的开发

为了在应用中使用@AspectJ支持,Spring需要添加三个库:

  • aspectjweaver.jar

  • aspectjrt.jar

  • aopalliance.jar

因此,我们需要配置maven,如下所示

<dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.6.12</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.6.12</version></dependency>

新建一个app.xml ,我们需要在Spring配置文件中做如下配置:

<?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:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.3.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.3.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd"><!-- 指定需要扫描的包,使注解生效 --><context:component-scan base-package="com.ssm.aspectj" /><!-- 启动基于注解的声明式AspectJ支持 --><aop:aspectj-autoproxy />
</beans>

然后,我们创建一个UserDao 的接口,如下所示

package com.ssm.aspectj;public interface UserDao {// add userpublic void addUser();//delete userpublic void delUser();
}

将 UserDao 实例化,并加上注解@Repository("userDao"),方便后续进行调用具体的方法

package com.ssm.aspectj;import org.springframework.stereotype.Repository;@Repository("userDao")
public class UserDaoImpl implements UserDao{@Overridepublic void addUser() {System.out.println("add user");}@Overridepublic void delUser() {System.out.println("delete user");}
}

定义一个切面类,在该类中编写各种通知

package com.ssm.aspectj.xml;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/*** 切面类,在此类中编写通知*/
@Aspect
@Component
public class MyAspect {//定义切入点表达式@Pointcut("execution(* com.ssm.aspectj.*.*(..))")//使用一个返回值为void、方法体为空的方法来命名切入点private void myPointCut(){}//前置通知@Before("myPointCut()")public void myBefore(JoinPoint joinPoint){System.out.print("前置通知:模拟执行权限检查..,");System.out.print("目标类是:"+joinPoint.getTarget());System.out.println(",被植入增强处理的目标方法为:"+joinPoint.getSignature().getName());}//后置通知@AfterReturning(value="myPointCut()")public void myAfterReturning(JoinPoint joinPoint) {System.out.print("后置通知:模拟记录日志..,");System.out.println("被植入增强处理的目标方法为:" + joinPoint.getSignature().getName());}/*** 环绕通知* ProceedingJoinPoint是JoinPoint的子接口,表示可执行目标方法* 1.必须是Object类型的返回值* 2.必须接收一个参数,类型为ProceedingJoinPoint* 3.必须throws Throwable*/@Around("myPointCut()")public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{//开始System.out.println("环绕开始:执行目标方法之前,模拟开启事务..,");//执行当前目标方法Object obj=proceedingJoinPoint.proceed();//结束System.out.println("环绕结束:执行目标方法之后,模拟关闭事务..,");return obj;}//异常通知@AfterThrowing(value="myPointCut()",throwing="e")public void myAfterThrowing(JoinPoint joinPoint,Throwable e){System.out.println("异常通知:出错了"+e.getMessage());}//最终通知@After("myPointCut()")public void myAfter(){System.out.println("最终通知:模拟方法结束后释放资源..");}
}

srping 的通知包括五种通知工作:

在上述代码中,其中 @Pointcut("execution(* com.ssm.aspectj.*.*(..))") 表示定义切入点,使用注解@Pointcut 后面的execution(* com.ssm.aspectj.*.*(..)) 表示匹配所有目标类的所有方法。第一个*代表返回类型,第二个*代表方法名,而..代表任意入参的方法,他的格式如下:

语法:execution(修饰符 返回值 包.类.方法(参数) throws 异常)

最后编写个测试类从ClassPathXmlApplicationContext 读取xml 文件,然后调用getBean 获取userDao并执行addUser方法。

package com.ssm.aspectj;import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestXmlAspectJ {@Testpublic void testAnnotation() {ApplicationContext applicationContext=new ClassPathXmlApplicationContext("app.xml");//从容器中获得内容UserDao userDao= (UserDao) applicationContext.getBean("userDao");//执行方法userDao.addUser();}
}

结果如下:

更多精彩推荐
☞苹果或在 WWDC 宣布放弃英特尔转向自研 5nm ARM 芯片,这次时机成熟了?
☞国产数据库技术全面破冰,金融核心系统打破国外巨头垄断指日可待
☞Linux 之父怒删工程师提交的补丁,称“太蠢了”网友:怼得好!
☞干货!3 个重要因素,带你看透 AI 技术架构方案的可行性!
☞干货 | 大白话彻底搞懂 HBase RowKey 详细设计
☞热评 | 警惕新基建热潮中的区块链项目烂尾
你点的每个“在看”,我都认真当成了喜欢

如何理解 Spring AOP 以及使用 AspectJ?相关推荐

  1. 从面向对象设计思想出发理解Spring AOP编程

    都说AOP是OOP(面向对象)的继承与延续,我觉得理解AOP还是得从OOP出发,经历从暴露问题到解决问题的过程. 目录 一. 面向对象设计思想(OOP) (1)概述 1. POP编程 2. OOP的优 ...

  2. 彻底理解Spring AOP

    目录 前言 1. AOP概念 2. AOP的实现 3. Spring的IoC理解: 4. Sping知识整理 前言 AOP英文名为Aspect Oriented Programming,意为面向切面编 ...

  3. 正确理解Spring AOP中的Around advice

    Spring AOP中,有Before advice和After advice,这两个advice从字面上就可以很容易理解,但是Around advice就有点麻烦了. 乍一看好像是Before ad ...

  4. java @around_正确理解Spring AOP中的Around advice

    Spring AOP中,有Before advice和After advice,这两个advice从字面上就可以很容易理解,但是Around advice就有点麻烦了. 乍一看好像是Before ad ...

  5. 结合代码彻底理解Spring AOP的术语

    每本Spring的书在介绍AOP之前,总能有一箩筐的术语,看半天似懂非懂,也就没兴趣再继续学习下去,其实并没有这么复杂. 难懂的定义我们就不贴了,就说说咱们通俗的解释,下面让我们结合代码来理清楚各个术 ...

  6. Spring Aop实例之AspectJ注解配置

    上篇博文<Spring Aop实例之xml配置>中,讲解了xml配置方式,今天来说说AspectJ注解方式去配置spring aop. 依旧采用的jdk代理,接口和实现类代码请参考上篇博文 ...

  7. 带你理解Spring AOP

    AOP概述 在我们的日常开发中,除了正常业务逻辑外,还可能经常会需要在业务逻辑的特定位置加入日志,以便于调试和问题分析.但是这种插入日志的逻辑和业务逻辑间并不存在连续性和依赖性,这种逻辑侵入随着项目的 ...

  8. 实例简述Spring AOP之对AspectJ语法的支持

    Spring的AOP可以通过对@AspectJ注解的支持和在XML中配置来实现,本文通过实例简述如何在Spring中使用AspectJ. 一:使用AspectJ注解: 1,启用对AspectJ的支持: ...

  9. 深入理解Spring AOP思想

    什么是AOP?AOP解决了什么问题? 在传统的开发模式中,以下层次的是非常常见的一种,业务层每一个方法都要有重复的事务代码 如何改善这个问题? AOP希望将A.B 这些分散在各个业务逻辑中的相同代码, ...

最新文章

  1. [Scheduled Timer]第三回:事件存储(EventStorage)
  2. 第四届中国国际大数据大会务实推进应用落地
  3. tokyo cabinet java_Tokyo Cabinet的安装,含Java版(CentOS 5.4)
  4. 访问云服务器储存的mp4_服务器如何存储视频文件格式
  5. SAP 电商云 Spartacus UI 的持续集成 - Continous integration
  6. memcache连接是否有用户名和密码的设置
  7. 计算机c盘坏了,电脑c盘损坏,怎样修复?
  8. 计算机工控机配置,研华工控机最新配置IPC-610
  9. Chrome\Edge 更新后访问网站变慢或加载不出来,其他浏览器正常
  10. Java获取国内手机号码归属地
  11. mysql优化之in内子查询
  12. 老广人为粤语---广州话写篇文章
  13. Z字型变幻,整数反转
  14. 【周刊】“熊孩子”乱敲键盘攻破 Linux 桌面;500 个值得学习的 AI 开源项目;Rust 升级成为微软一级项目...
  15. 5分绩点转4分_gpa5分制换算4分制(5分绩点转4分)
  16. 【Matlab】多元线性回归(Excel可直接替换数据)
  17. 3dsmax: Failed to load max file: C:/Users/cyl/AppData/Local/Thinkbox/Deadline/s
  18. LM321 低功耗单运算放大器 1MHZ增益带宽积 用于充电器 适配器
  19. “开源之夏”活动火热报名中,丰厚奖金等你来拿
  20. 总线、I/O总线、I/O接口

热门文章

  1. 【软工3】迭代二 心得体会及感想
  2. VBS操作XML文档,拷贝结点 (转)
  3. 学习 jQuery -2 document 对象的 ready 事件
  4. 各机器学习平台视频建模功能汇总
  5. 集成Jupyter notebook的工具或平台
  6. c语言0可以除10吗,C语言10.0
  7. 矩池云上安装chumpy失败
  8. noip复赛电脑有excel吗_指南 | 现在就必须了解的信息学竞赛(高一学生)
  9. windows 代理软件_MacOS好用软件推荐(一)
  10. 手机虚拟摄像头_新游 | 打破次元壁障,《猪猪侠AR虚拟使命》现实约战,一切尽在创酷互动!...