热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:图文并茂!!!一文搞懂SpringAOP(面向切面编程)

篇首语:本文由编程笔记#小编为大家整理,主要介绍了图文并茂!!!一文搞懂SpringAOP(面向切面编程)相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了图文并茂!!!一文搞懂SpringAOP(面向切面编程)相关的知识,希望对你有一定的参考价值。








文章目录


    • SpringAOP
      • AOP概述
        • 核心原理及使用案例
        • AOP的基本概念(Spring的专业术语)

      • SpringAOP实现
        • SpringAOP的使用
          • 导入实现AOP的AspectJ的jar
          • 基于AspectJ的xml配置实现
          • 五种通知类型配置
          • 注解实现







SpringAOP

我们为什么要使用AOP(面向切面编程)?当我们在现实中完成实际的项目时,我们总是需要在一个“动作”进行前,进行中,或进行后进行一些操作,比如当我们在运行程序时,我们想要进行日志保存,或者在每一个方法调用后输出一句话,这就表示我们每一次进行一个“动作”都需要进行同样的操作,这就导致程序员会进行大量的、无用的重复性动作,面对这种情况,AOP应运而生。


AOP概述

AOP,即Aspect Oriented Rrogramming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能统一维护的一种技术。AOP可以对业务漏极的各个部分进行隔离,从而使得业务逻辑之间得耦合性降低,提高程序得可重用性,同时提高了开发得效率。

AOP和OOP是两种不同的设计思想。OOP(面向对象编程)针对业务处理过程得实体及其属性和行为进行抽象封装,获得清晰高效得逻辑单元划分。AOP则是针对业务处理过程中得切面进行提取,是面对业务处理过程中的某个步骤或阶段,获得逻辑过程中各部分之间低耦合性得隔离效果。

面向切面编程的好处就是:减少重复,专注业务。它是面向对象编程的一种补充。


核心原理及使用案例

原理:使用动态代理的方式在执行方法前后或出现异常时加入相关的逻辑。

使用:

事务处理:开启事务,关闭事务,出现异常回滚事务.....
权限判断:执行方法前,判断是否具有权限;
日志处理;
......

在这里插入图片描述


AOP的基本概念(Spring的专业术语)

0.增强:向各个程序内部注入一些逻辑代码从而增强原有程序的功能。

1.连接点(JoinPoint):类中可以被增强的方法,这个方法就就被称为连接点,切记连接点并不是一定会被增强。

2.切入点(Pointcut):类中实际被增强的方法。

3.通知(Advice):指一个切面在特定的连接点要做的事情,简单来说就是“增强”。可以分为方法执行前通知,方法执行后通知,环绕通知等等。

4.切面(Aspect):把通知添加到切入点的过程就叫切面。

5.目标(Target):代理的目标对象,即要增强的方法所在的类。

6.代理(Proxy):向目标对象应用通知之后创建的代理对象。


SpringAOP实现

很多的框架都对AOP这种编程思想进行了实现。Spring只是其中的一种,可以完成面向切面编程。AspectJ也是一个面向切面的框架,并且实现方式更为简捷,更为方便,并且支持注解式开发。所以,Spring又将AspectJ对于AOP的实现引入到自己的框架之中。

Spring中使用AOP开发时,通常使用AspectJ的实现方式。其中常用的通知有五种类型:

前置通知:方法执行前执行;
后置通知:方法执行后执行;
环绕通知:前后都执行;
异常通知:出异常时通知;
最终通知:如return后执行。

SpringAOP的使用


导入实现AOP的AspectJ的jar



<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aspectsartifactId>
<version>5.2.2.RELEASEversion>
dependency>

基于AspectJ的xml配置实现

所有的配置都在spring.xml文件中进行。

1.创建一个增强功能的类。

import org.aspectj.lang.ProceedingJoinPoint;
//通知(Advice):在连接点要做的事情
public class Aop {
public void doLog() {
System.out.println("&#61;&#61;&#61;&#61;&#61;保存日志&#61;&#61;&#61;&#61;&#61;");
}
public void commit() {
System.out.println("&#61;&#61;&#61;&#61;&#61;提交事务&#61;&#61;&#61;&#61;&#61;");
}
public void around(ProceedingJoinPoint proceedingJoinPoint) {
System.out.println("&#61;&#61;&#61;&#61;&#61;&#61;方法前通知&#61;&#61;&#61;&#61;&#61;&#61;");
try {
proceedingJoinPoint.proceed();//调用自己的方法
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("&#61;&#61;&#61;&#61;&#61;&#61;方法后通知&#61;&#61;&#61;&#61;&#61;&#61;");
}
public void throwable(Throwable throwable) {
System.out.println("&#61;&#61;&#61;&#61;&#61;&#61;出异常了&#61;&#61;&#61;&#61;&#61;&#61;");
System.out.println(throwable.getMessage());
}
}

2.将装有增强功能的类交给交由spring管理


<beans xmlns&#61;"http://www.springframework.org/schema/beans"
xmlns:xsi&#61;"http://www.w3.org/2001/XMLSchema-instance"
xmlns:context&#61;"http://www.springframework.org/schema/context"
xmlns:aop&#61;"http://www.springframework.org/schema/aop"
xsi:schemaLocation&#61;"http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
>


<bean id&#61;"aop" class&#61;"com.cwd.spring4pro.demo1.aop.Aop">bean>


beans>

3.配置切面&#xff08;Aspect&#xff09;

先准备一个被增强的类&#xff0c;即目标&#xff08;Target&#xff09;

import org.springframework.stereotype.Component;
//目标(Target):代理的目标对象&#xff0c;即要增强的类
&#64;Component(value &#61; "target")
public class Target {
/*
连接点(Joinpoint),可以被增强的方法
切入点(pointcut),实际被增强的方法,被增强了
*/

public void pointCut() {
System.out.println("这是一个保存的操作!!!");
return;
}
}

将通知添加到切入点。


<aop:config>


<aop:pointcut id&#61;"pointCut" expression&#61;"execution(* com.cwd.spring4pro.demo.Target.pointCut(..))"/>

<aop:aspect ref&#61;"aop">


<aop:before method&#61;"doLog" pointcut-ref&#61;"pointCut"/>
aop:aspect>
aop:config>

在这里插入图片描述


五种通知类型配置

1.前置通知


<aop:config>
<aop:pointcut id&#61;"pointCut" expression&#61;"execution(* com.cwd.spring4pro.demo.Target.pointCut(..))"/>
<aop:aspect ref&#61;"aop">

<aop:before method&#61;"doLog" pointcut-ref&#61;"pointCut"/>
aop:aspect>
aop:config>

在这里插入图片描述

2.后置通知


<aop:config>
<aop:pointcut id&#61;"pointCut" expression&#61;"execution(* com.cwd.spring4pro.demo.Target.pointCut(..))"/>
<aop:aspect ref&#61;"aop">

<aop:after method&#61;"commit" pointcut-ref&#61;"pointCut"/>
aop:aspect>
aop:config>

在这里插入图片描述

3.环绕通知


<aop:config>
<aop:pointcut id&#61;"pointCut" expression&#61;"execution(* com.cwd.spring4pro.demo.Target.pointCut(..))"/>
<aop:aspect ref&#61;"aop">

<aop:around method&#61;"around" pointcut-ref&#61;"pointCut"/>
aop:aspect>
aop:config>

在这里插入图片描述

4.异常通知

修改一下pointCut

public void pointCut() {
System.out.println("这是一个保存的操作!!!");
int a &#61; 10 / 0;
return;
}


<aop:config>
<aop:pointcut id&#61;"pointCut" expression&#61;"execution(* com.cwd.spring4pro.demo.Target.pointCut(..))"/>
<aop:aspect ref&#61;"aop">

<aop:after-throwing method&#61;"throwable" pointcut-ref&#61;"pointCut" throwing&#61;"throwable"/>
aop:aspect>
aop:config>

在这里插入图片描述

5.最终通知


<aop:config>
<aop:pointcut id&#61;"pointCut" expression&#61;"execution(* com.cwd.spring4pro.demo.Target.pointCut(..))"/>
<aop:aspect ref&#61;"aop">

<aop:after-returning method&#61;"commit" pointcut-ref&#61;"pointCut"/>
aop:aspect>
aop:config>

最终通知一般在return之后执行。


注解实现

开启aop注解扫描


<aop:aspectj-autoproxy/>

在通知类中进行配置&#xff0c;如下所示&#xff1a;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
&#64;Component//将这个类交给Spring管理
&#64;Aspect//标注这个类时装有通知的类
public class Aop {
&#64;Before("execution(* com.cwd.spring4pro.demo.Target.pointCut(..))")
public void doLog() {
System.out.println("&#61;&#61;&#61;&#61;&#61;保存日志&#61;&#61;&#61;&#61;&#61;");
}
&#64;After("execution(* com.cwd.spring4pro.demo.Target.pointCut(..))")
public void commit() {
System.out.println("&#61;&#61;&#61;&#61;&#61;提交事务&#61;&#61;&#61;&#61;&#61;");
}
public void around(ProceedingJoinPoint proceedingJoinPoint) {
System.out.println("&#61;&#61;&#61;&#61;&#61;&#61;方法前通知&#61;&#61;&#61;&#61;&#61;&#61;");
try {
proceedingJoinPoint.proceed();//调用自己的方法
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("&#61;&#61;&#61;&#61;&#61;&#61;方法后通知&#61;&#61;&#61;&#61;&#61;&#61;");
}
&#64;AfterThrowing(value &#61; "execution(* com.cwd.spring4pro.demo.Target.pointCut(..))",throwing &#61; "throwable")
public void throwable(Throwable throwable) {
System.out.println("&#61;&#61;&#61;&#61;&#61;&#61;出异常了&#61;&#61;&#61;&#61;&#61;&#61;");
System.out.println(throwable.getMessage());
}
&#64;AfterReturning("execution(* com.cwd.spring4pro.demo.Target.pointCut(..))")
public void returnAfter() {
System.out.println("&#61;&#61;&#61;&#61;&#61;&#61;return后&#61;&#61;&#61;&#61;&#61;");
}
}





推荐阅读
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 大类|电阻器_使用Requests、Etree、BeautifulSoup、Pandas和Path库进行数据抓取与处理 | 将指定区域内容保存为HTML和Excel格式
    大类|电阻器_使用Requests、Etree、BeautifulSoup、Pandas和Path库进行数据抓取与处理 | 将指定区域内容保存为HTML和Excel格式 ... [详细]
  • 属性类 `Properties` 是 `Hashtable` 类的子类,用于存储键值对形式的数据。该类在 Java 中广泛应用于配置文件的读取与写入,支持字符串类型的键和值。通过 `Properties` 类,开发者可以方便地进行配置信息的管理,确保应用程序的灵活性和可维护性。此外,`Properties` 类还提供了加载和保存属性文件的方法,使其在实际开发中具有较高的实用价值。 ... [详细]
  • Python 序列图分割与可视化编程入门教程
    本文介绍了如何使用 Python 进行序列图的快速分割与可视化。通过一个实际案例,详细展示了从需求分析到代码实现的全过程。具体包括如何读取序列图数据、应用分割算法以及利用可视化库生成直观的图表,帮助非编程背景的用户也能轻松上手。 ... [详细]
  • Python 程序转换为 EXE 文件:详细解析 .py 脚本打包成独立可执行文件的方法与技巧
    在开发了几个简单的爬虫 Python 程序后,我决定将其封装成独立的可执行文件以便于分发和使用。为了实现这一目标,首先需要解决的是如何将 Python 脚本转换为 EXE 文件。在这个过程中,我选择了 Qt 作为 GUI 框架,因为之前对此并不熟悉,希望通过这个项目进一步学习和掌握 Qt 的基本用法。本文将详细介绍从 .py 脚本到 EXE 文件的整个过程,包括所需工具、具体步骤以及常见问题的解决方案。 ... [详细]
  • 在Java Web服务开发中,Apache CXF 和 Axis2 是两个广泛使用的框架。CXF 由于其与 Spring 框架的无缝集成能力,以及更简便的部署方式,成为了许多开发者的首选。本文将详细介绍如何使用 CXF 框架进行 Web 服务的开发,包括环境搭建、服务发布和客户端调用等关键步骤,为开发者提供一个全面的实践指南。 ... [详细]
  • 本文探讨了资源访问的学习路径与方法,旨在帮助学习者更高效地获取和利用各类资源。通过分析不同资源的特点和应用场景,提出了多种实用的学习策略和技术手段,为学习者提供了系统的指导和建议。 ... [详细]
  • 如何轻松地将多个文件导入Python:简明指南 ... [详细]
  • 深入浅出 webpack 系列(二):实现 PostCSS 代码的编译与优化
    在前一篇文章中,我们探讨了如何通过基础配置使 Webpack 完成 ES6 代码的编译。本文将深入讲解如何利用 Webpack 实现 PostCSS 代码的编译与优化,包括配置相关插件和加载器,以提升开发效率和代码质量。我们将详细介绍每个步骤,并提供实用示例,帮助读者更好地理解和应用这些技术。 ... [详细]
  • 在 Linux 环境下,多线程编程是实现高效并发处理的重要技术。本文通过具体的实战案例,详细分析了多线程编程的关键技术和常见问题。文章首先介绍了多线程的基本概念和创建方法,然后通过实例代码展示了如何使用 pthreads 库进行线程同步和通信。此外,还探讨了多线程程序中的性能优化技巧和调试方法,为开发者提供了宝贵的实践经验。 ... [详细]
  • C++ 开发实战:实用技巧与经验分享
    C++ 开发实战:实用技巧与经验分享 ... [详细]
  • ButterKnife 是一款用于 Android 开发的注解库,主要用于简化视图和事件绑定。本文详细介绍了 ButterKnife 的基础用法,包括如何通过注解实现字段和方法的绑定,以及在实际项目中的应用示例。此外,文章还提到了截至 2016 年 4 月 29 日,ButterKnife 的最新版本为 8.0.1,为开发者提供了最新的功能和性能优化。 ... [详细]
  • Vue应用预渲染技术详解与实践 ... [详细]
  • 本文探讨了利用Python实现高效语音识别技术的方法。通过使用先进的语音处理库和算法,本文详细介绍了如何构建一个准确且高效的语音识别系统。提供的代码示例和实验结果展示了该方法在实际应用中的优越性能。相关文件可从以下链接下载:链接:https://pan.baidu.com/s/1RWNVHuXMQleOrEi5vig_bQ,提取码:p57s。 ... [详细]
  • 在使用SSH框架进行项目开发时,经常会遇到一些常见的问题。例如,在Spring配置文件中配置AOP事务声明后,进行单元测试时可能会出现“No Hibernate Session bound to thread”的错误。本文将详细探讨这一问题的原因,并提供有效的解决方案,帮助开发者顺利解决此类问题。 ... [详细]
author-avatar
静静我想你啦
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有