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

Spring框架中的面向切面编程(AOP)技术详解

面向切面编程(AOP)是Spring框架中的关键技术之一,它通过将横切关注点从业务逻辑中分离出来,实现了代码的模块化和重用。AOP的核心思想是将程序运行过程中需要多次处理的功能(如日志记录、事务管理等)封装成独立的模块,即切面,并在特定的连接点(如方法调用)动态地应用这些切面。这种方式不仅提高了代码的可维护性和可读性,还简化了业务逻辑的实现。SpringAOP利用代理机制,在不修改原有代码的基础上,实现了对目标对象的增强。

AOP[面向切面编程]

1.什么是AOP?
AOP (Aspect Oriented Programing) 称为:面向切面编程,它是一种编程思想。
通常情况下一个系统/软件的需求有2种:
1.业务需求:实现具体某一个业务逻辑功能的实现过程。【添加,删除,修改,查询等等】
2.系统需求:在整个系统运行的过程中帮助完善系统业务需求的功能【性能监视,事务管理,安全检查,缓存,日志记录等】
现在我们需要完成的动作就是在需要使用系统需求的位置能够快速的将系统需求植入给必要的业务需求功能中。
此时我们可以通过代理模式将系统需求功能快速的植入到业务需求功能中。
代理模式有静态代理和动态代理两种
静态代理由父子模式和兄弟模式--------传统纵向继承体系【大量代码重复性编写】
动态代理由JDK动态代理和CGLIB动态代理----横向抽取机制
由于JDK动态代理只能给实现过接口的java对象生成代理对象,所以也不会作为使用系统需求功能快速植入给必要的业务需求功能中的操作方式。
CGLIB动态代理,由于可以为任何java类提供代理对象,因此被选择成为AOP[面向切面编程]的底层实现。
CGLIB动态代理是Aop的底层实现。
2.AOP相关的概念
joinpoint(连接点):指那些被拦截到的点。在spring中指的可以被代理(增强)的方法。【业务类中的业务需求方法】
poingcut(切入点):对哪些连接点进行拦截的定义。在Spring中指的真正需要被代理(增强)的方法。
advice(通知/增强):指拦截到连接点之后要做的事情。真正增强的那些代码(逻辑)。
通知/增强分为:
前置通知,后置通知,异常通知,最终通知,环绕通知。
aspect(切面):是切入点和通知/增强的结合过程。
introduction(引介):一种特殊的通知在不修改类代码的前提下,introduction可以在运行期为类动态地添加一些方法或者字段。
target(目标对象):代码的目标对象。
weaving(织入):把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入。而AspectJ采用编译期织入和类装在期织入。
proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类。
在这里插入图片描述

3.AOP[面向切面编程]的具体实现
重点:掌握切入点表达式的编写
下面给出一些通用切入点表达式的例子。
1.任意公共方法的执行:
execution(public * (…))
2.任何一个名字以“set”开始的方法的执行:
execution(
set*(…))
3.AccountService接口定义的任意方法的执行:
execution(* com.xyz.service.AccountService.(…))
4.在service包中定义的任意方法的执行:
execution(
com.xyz.service..(…))
5.在service包或其子包中定义的任意方法的执行:
execution(* com.xyz.service….(…))
6.在service包中的任意连接点(在Spring AOP中只是方法执行):
within(com.xyz.service.)
7.在service包或其子包中的任意连接点(在Spring AOP中只是方法执行):
within(com.xyz.service…
)
8.实现了AccountService接口的代理对象的任意连接点 (在Spring AOP中只是方法执行):
this(com.xyz.service.AccountService)
'this’在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得代理对象在通知体内可用。
9.实现AccountService接口的目标对象的任意连接点 (在Spring AOP中只是方法执行):
target(com.xyz.service.AccountService)
'target’在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得目标对象在通知体内可用。
10.任何一个只接受一个参数,并且运行时所传入的参数是Serializable 接口的连接点(在Spring AOP中只是方法执行)
args(java.io.Serializable)
'args’在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得方法参数在通知体内可用。
请注意在例子中给出的切入点不同于 execution(* *(java.io.Serializable)): args版本只有在动态运行时候传入参数是Serializable时才匹配,而execution版本在方法签名中声明只有一个 Serializable类型的参数时候匹配。
11.目标对象中有一个 @Transactional 注解的任意连接点 (在Spring AOP中只是方法执行)
@target(org.springframework.transaction.annotation.Transactional)
'@target’在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
12.任何一个目标对象声明的类型有一个 @Transactional 注解的连接点 (在Spring AOP中只是方法执行):
@within(org.springframework.transaction.annotation.Transactional)
'@within’在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
13.任何一个执行的方法有一个 @Transactional 注解的连接点 (在Spring AOP中只是方法执行)
@annotation(org.springframework.transaction.annotation.Transactional)
'@annotation’在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
14.任何一个只接受一个参数,并且运行时所传入的参数类型具有@Classified 注解的连接点(在Spring AOP中只是方法执行)
@args(com.xyz.security.Classified)
‘@args’在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
15任何一个在名为’tradeService’的Spring bean之上的连接点 (在Spring AOP中只是方法执行):
bean(tradeService)
16.任何一个在名字匹配通配符表达式’*Service’的Spring bean之上的连接点 (在Spring AOP中只是方法执行):
bean(*Service)
例如:

com.wangxing.spring.bean
StudentBean
public void insertStudent();
public void insertStudent(Student);
PersonBean
public void insertPerson();
public void insertPerson(Student);
public void deletePerson(int perid);
execution(com.wangxing.spring.bean.*.*(..))
execution(com.wangxing.spring.bean.StudentBean.*(..))
execution(com.wangxing.spring.bean.*.insert*(..))

1.基于XML文件【Spring配置文件】的AOP实现


org.springframeworkspring-context5.1.5.RELEASE

org.springframeworkspring-context-support5.1.5.RELEASE

org.springframeworkspring-aspects5.1.5.RELEASE
package com.wangxing.spring.service;
//业务需求类
public class UserService {//添加用户信息的业务方法public void insertUser(){System.out.println("添加用户信息的业务方法");}//修改用户信息的业务方法public void updateUser(){System.out.println("修改用户信息的业务方法");//int a=10/0;}//删除用户信息的业务方法public void deleteUser(){System.out.println("删除用户信息的业务方法");}//查询用户信息的业务方法public void selectUser(){System.out.println("查询用户信息的业务方法");}
}package com.wangxing.spring.service;
import org.aspectj.lang.ProceedingJoinPoint;
//增强类/通知类
public class MyAvice {//系统需求功能实现方法public void saveLog(){System.out.println("记录执行日志");}//执行环绕通知的系统需求功能实现方法public void testAround(ProceedingJoinPoint joinPoint) throws Throwable{saveLog();joinPoint.proceed(); // 调用真正的业务方法saveLog();}
}


2.基于注解的Aop实现

org.springframeworkspring-context5.1.5.RELEASE

org.springframeworkspring-context-support5.1.5.RELEASE

org.springframeworkspring-aspects5.1.5.RELEASE
package com.wangxing.spring.service;import org.springframework.stereotype.Component;//业务类
@Component("personService")
public class PersonService {public void insertPerson(){System.out.println("添加个人信息的业务方法");}public void updatePerson(){System.out.println("修改个人信息的业务方法");//int a=10/0;}public void deletePerson(){System.out.println("删除个人信息的业务方法");}public void selectPerson(){System.out.println("查询个人信息的业务方法");}
}package com.wangxing.spring.service;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;//增强类
//@Aspect,表示这个系统需求类是一个切面
@Component
@Aspect
public class MyAvice {//系统需求功能实现方法//@Before("execution(* com.wangxing.spring.service.PersonService.selectPerson())")//@AfterReturning("execution(* com.wangxing.spring.service.PersonService.deletePerson())")//@AfterThrowing("execution(* com.wangxing.spring.service.PersonService.updatePerson())")@After("execution(* com.wangxing.spring.service.PersonService.updatePerson())")public void saveLog(){System.out.println("记录执行日志");}//执行环绕通知的系统需求功能实现方法@Around("execution(* com.wangxing.spring.service.PersonService.insertPerson())")public void testAround(ProceedingJoinPoint joinPoint) throws Throwable{saveLog();joinPoint.proceed(); // 调用真正的业务方法saveLog();}
}



推荐阅读
  • 技术分享:深入解析GestureDetector手势识别机制
    技术分享:深入解析GestureDetector手势识别机制 ... [详细]
  • 掌握Android UI设计:利用ZoomControls实现图片缩放功能
    本文介绍了如何在Android应用中通过使用ZoomControls组件来实现图片的缩放功能。ZoomControls提供了一种简单且直观的方式,让用户可以通过点击放大和缩小按钮来调整图片的显示大小。文章详细讲解了ZoomControls的基本用法、布局设置以及与ImageView的结合使用方法,适合初学者快速掌握Android UI设计中的这一重要功能。 ... [详细]
  • 利用树莓派畅享落网电台音乐体验
    最近重新拾起了闲置已久的树莓派,这台小巧的开发板已经沉寂了半年多。上个月闲暇时间较多,我决定将其重新启用。恰逢落网电台进行了改版,回忆起之前在树莓派论坛上看到有人用它来播放豆瓣音乐,便萌生了同样的想法。通过一番调试,终于实现了在树莓派上流畅播放落网电台音乐的功能,带来了全新的音乐享受体验。 ... [详细]
  • 本文深入探讨了CGLIB BeanCopier在Bean对象复制中的应用及其优化技巧。相较于Spring的BeanUtils和Apache的BeanUtils,CGLIB BeanCopier在性能上具有显著优势。通过详细分析其内部机制和使用场景,本文提供了多种优化方法,帮助开发者在实际项目中更高效地利用这一工具。此外,文章还讨论了CGLIB BeanCopier在复杂对象结构和大规模数据处理中的表现,为读者提供了实用的参考和建议。 ... [详细]
  • 在处理遗留数据库的映射时,反向工程是一个重要的初始步骤。由于实体模式已经在数据库系统中存在,Hibernate 提供了自动化工具来简化这一过程,帮助开发人员快速生成持久化类和映射文件。通过反向工程,可以显著提高开发效率并减少手动配置的错误。此外,该工具还支持对现有数据库结构进行分析,自动生成符合 Hibernate 规范的配置文件,从而加速项目的启动和开发周期。 ... [详细]
  • 本文探讨了利用Java实现WebSocket实时消息推送技术的方法。与传统的轮询、长连接或短连接等方案相比,WebSocket提供了一种更为高效和低延迟的双向通信机制。通过建立持久连接,服务器能够主动向客户端推送数据,从而实现真正的实时消息传递。此外,本文还介绍了WebSocket在实际应用中的优势和应用场景,并提供了详细的实现步骤和技术细节。 ... [详细]
  • 开发笔记:深入解析Android自定义控件——Button的72种变形技巧
    开发笔记:深入解析Android自定义控件——Button的72种变形技巧 ... [详细]
  • 在CentOS上部署并使用FFmpeg多媒体处理工具
    最近在进行音频处理时需要用到FFmpeg,本文将详细介绍如何在CentOS系统上部署并使用这一强大的多媒体处理工具。首先,从官方网站下载FFmpeg的最新版本,然后通过Xftp工具将下载的压缩包(如ffmpeg-4.3.1.tar.xz)传输到服务器上。接下来,解压文件并按照官方文档进行编译安装。安装完成后,可以通过命令行工具验证FFmpeg是否成功安装,并开始进行多媒体文件的转换和处理。此外,文章还将介绍一些常用的FFmpeg命令和参数,帮助用户快速上手。 ... [详细]
  • Java Web开发中的JSP:三大指令、九大隐式对象与动作标签详解
    在Java Web开发中,JSP(Java Server Pages)是一种重要的技术,用于构建动态网页。本文详细介绍了JSP的三大指令、九大隐式对象以及动作标签。三大指令包括页面指令、包含指令和标签库指令,它们分别用于设置页面属性、引入其他文件和定义自定义标签。九大隐式对象则涵盖了请求、响应、会话、应用上下文等关键组件,为开发者提供了便捷的操作接口。动作标签则通过预定义的动作来简化页面逻辑,提高开发效率。这些内容对于理解和掌握JSP技术具有重要意义。 ... [详细]
  • 分布式开源任务调度框架 TBSchedule 深度解析与应用实践
    本文深入解析了分布式开源任务调度框架 TBSchedule 的核心原理与应用场景,并通过实际案例详细介绍了其部署与使用方法。首先,从源码下载开始,详细阐述了 TBSchedule 的安装步骤和配置要点。接着,探讨了该框架在大规模分布式环境中的性能优化策略,以及如何通过灵活的任务调度机制提升系统效率。最后,结合具体实例,展示了 TBSchedule 在实际项目中的应用效果,为开发者提供了宝贵的实践经验。 ... [详细]
  • 在Python编程中,探讨了并发与并行的概念及其区别。并发指的是系统同时处理多个任务的能力,而并行则指在同一时间点上并行执行多个任务。文章详细解析了阻塞与非阻塞操作、同步与异步编程模型,以及IO多路复用技术的应用。通过模拟socket发送HTTP请求的过程,展示了如何创建连接、发送数据和接收响应,并强调了默认情况下socket的阻塞特性。此外,还介绍了如何利用这些技术优化网络通信性能和提高程序效率。 ... [详细]
  • 在Java编程中,为了提高代码的可读性和执行效率,建议优先使用局部变量来存储方法的返回值,而不是多次调用同一个方法。这样不仅可以减少方法调用的开销,还能避免潜在的性能问题。此外,使用局部变量还可以增强代码的可维护性和调试便利性。 ... [详细]
  • 本文详细探讨了Zebra路由软件中的线程机制及其实际应用。通过对Zebra线程模型的深入分析,揭示了其在高效处理网络路由任务中的关键作用。文章还介绍了线程同步与通信机制,以及如何通过优化线程管理提升系统性能。此外,结合具体应用场景,展示了Zebra线程机制在复杂网络环境下的优势和灵活性。 ... [详细]
  • Nginx不仅是一款轻量级的高性能Web服务器,还具备出色的负载均衡和反向代理功能。它支持复杂的正则匹配规则、动静内容分离以及灵活的URL重写功能,使得配置和管理更加便捷高效。此外,Nginx提供了多种负载均衡算法,如轮询、加权轮询、最少连接数等,以满足不同应用场景的需求。 ... [详细]
  • 在尝试对从复杂 XSD 生成的类进行序列化时,遇到了 `NullReferenceException` 错误。尽管已经花费了数小时进行调试和搜索相关资料,但仍然无法找到问题的根源。希望社区能够提供一些指导和建议,帮助解决这一难题。 ... [详细]
author-avatar
djw
匠心独运
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有