热门标签 | 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();}
}



推荐阅读
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • CentOS7源码编译安装MySQL5.6
    2019独角兽企业重金招聘Python工程师标准一、先在cmake官网下个最新的cmake源码包cmake官网:https:www.cmake.org如此时最新 ... [详细]
  • golang常用库:配置文件解析库/管理工具viper使用
    golang常用库:配置文件解析库管理工具-viper使用-一、viper简介viper配置管理解析库,是由大神SteveFrancia开发,他在google领导着golang的 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 数据库内核开发入门 | 搭建研发环境的初步指南
    本课程将带你从零开始,逐步掌握数据库内核开发的基础知识和实践技能,重点介绍如何搭建OceanBase的开发环境。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • XNA 3.0 游戏编程:从 XML 文件加载数据
    本文介绍如何在 XNA 3.0 游戏项目中从 XML 文件加载数据。我们将探讨如何将 XML 数据序列化为二进制文件,并通过内容管道加载到游戏中。此外,还会涉及自定义类型读取器和写入器的实现。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 本文详细分析了Hive在启动过程中遇到的权限拒绝错误,并提供了多种解决方案,包括调整文件权限、用户组设置以及环境变量配置等。 ... [详细]
  • 本文详细介绍了IBM DB2数据库在大型应用系统中的应用,强调其卓越的可扩展性和多环境支持能力。文章深入分析了DB2在数据利用性、完整性、安全性和恢复性方面的优势,并提供了优化建议以提升其在不同规模应用程序中的表现。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • Python自动化处理:从Word文档提取内容并生成带水印的PDF
    本文介绍如何利用Python实现从特定网站下载Word文档,去除水印并添加自定义水印,最终将文档转换为PDF格式。该方法适用于批量处理和自动化需求。 ... [详细]
  • 将Web服务部署到Tomcat
    本文介绍了如何在JDeveloper 12c中创建一个Java项目,并将其打包为Web服务,然后部署到Tomcat服务器。内容涵盖从项目创建、编写Web服务代码、配置相关XML文件到最终的本地部署和验证。 ... [详细]
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社区 版权所有