当前位置: 首页 > news >正文

Spring AOP - 配置文件方式实现

目录

AOP基础概念

示例1:模拟在com.text包及子包项下所有类名称以ServiceImpl结尾的类的所有方法执行前、执行后、执行正常后返回值、执行过程中出异常的情况

示例2:统计com.text包及子包项下所有类名称以DaoImpl结尾的类的所有方法执行时长情况


AOP基础概念

AOP:Aspect Oriented Programming 面向切面编程

使用场景:将一些通用的功能封装成切面类,切面类作用在目标类方法的前后,并通过自动插拔实现目标类方法的前后逻辑,示意图如下:

上述的示意图显示,Aspect切面类横向贯穿了3个目标类方法的执行逻辑之前,由此可以看出,AOP实现需要如下组件:

  1. 切面类(Aspect类)
  2. 切点(Pointcut),即上图的各个目标方法,通过切点表达式(execution)实现
  3. 连接点(JoinPoint) ,切面和切点之间的连接信息,可以理解为横切面和切点的交汇处
  4. 通知(Advice) ,在目标类方法的之前、之后还是环绕执行切面逻辑

Spring AOP实现需要引入aspectjweaver依赖

<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.6</version>
</dependency>

示例1:模拟在com.text包及子包项下所有类名称以ServiceImpl结尾的类的所有方法执行前、执行后、执行正常后返回值、执行过程中出异常的情况

1、配置文件:applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns="http://www.springframework.org/schema/beans"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--<context:component-scan base-package="com.text"/>--><bean id="studentService" class="com.text.service.impl.StudentServiceImpl"/><!-- 切面类交给IOC容器实例 --><bean id="methodAspect" class="com.text.aspect.MethodAspect"/><!-- aop配置--><aop:config><!-- 切点配置,expression表示com.text所有包及子包项下所有服务层(以ServiceImpl结束的类)的所有方法--><aop:pointcut id="pointcut" expression="execution(public * com.text..*ServiceImpl.*(..))"/><!-- 切面配置--><aop:aspect ref="methodAspect"><!-- 切点方法执行之前执行--><aop:before method="methodInvokeBefore" pointcut-ref="pointcut"/><!-- 切点方法执行之后执行--><aop:after method="methodInvokeAfter" pointcut-ref="pointcut"/><!-- 切点方法执行之后带返回值--><aop:after-returning method="methodInvokeAfterReturn" returning="ret" pointcut-ref="pointcut"/><!-- 切点方法执行时出现异常--><aop:after-throwing method="methodInvokeException" throwing="thr" pointcut-ref="pointcut"/></aop:aspect></aop:config></beans>

2、服务类及方法(pointcut)

package com.text.service.impl;import com.text.entity.Course;
import com.text.entity.Student;
import com.text.service.StudentService;public class StudentServiceImpl implements StudentService {@Overridepublic void save(Student student) {System.out.println(student + "正在被保存...");}@Overridepublic void deleteById(String id) {System.out.println("学生id=" + id + "的记录已被删除...");}@Overridepublic void updateById(String id) throws Exception{System.out.println("学生id=" + id + "的记录正在被修改...");throw new Exception("修改学生信息出异常");}@Overridepublic Student searchById(String id) {System.out.println("已查询到学生id=" + id + "的记录...");return new Student("张三",20,new Course("计算机"));}
}

3、切面类(aspect) 

package com.text.aspect;import org.aspectj.lang.JoinPoint;/*** 定义方法切面类*/
public class MethodAspect {public void methodInvokeBefore(JoinPoint joinPoint) {String targetClassName = joinPoint.getTarget().getClass().getName();//获取切面执行的目标类String methodName = joinPoint.getSignature().getName();System.out.println(targetClassName + "." + methodName + "方法执行之前的处理逻辑...");}public void methodInvokeAfter(JoinPoint joinPoint) {String targetClassName = joinPoint.getTarget().getClass().getName();//获取切面执行的目标类String methodName = joinPoint.getSignature().getName();System.out.println(targetClassName + "." + methodName + "方法执行之后的处理逻辑...");}public void methodInvokeAfterReturn(JoinPoint joinPoint,Object ret) {String targetClassName = joinPoint.getTarget().getClass().getName();//获取切面执行的目标类String methodName = joinPoint.getSignature().getName();System.out.println(targetClassName + "." + methodName + "方法执行之后返回的结果为:" + ret);}public void methodInvokeException(JoinPoint joinPoint,Throwable thr) throws Throwable {String targetClassName = joinPoint.getTarget().getClass().getName();//获取切面执行的目标类String methodName = joinPoint.getSignature().getName();System.out.println(targetClassName + "." + methodName + "方法执行中的异常信息为:" + thr.getMessage());throw thr;}
}

4、测试类 Application

package com.text;
import com.text.entity.Course;
import com.text.entity.Student;
import com.text.service.StudentService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Application {public static void main(String[] args) throws Exception {ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");StudentService studentService = context.getBean("studentService", StudentService.class);studentService.save(new Student("张三",20,new Course("计算机")));System.out.println("======save end========");studentService.deleteById("1");System.out.println("======delete end ========");Student student = studentService.searchById("1");System.out.println("======search end ========");studentService.updateById("1");System.out.println("======update end ========");}
}

5、输出结果:

示例2:统计com.text包及子包项下所有类名称以DaoImpl结尾的类的所有方法执行时长情况

此需求如果按照之前的advice至少需要写2个,一个是aop:before,一个是aop:after,方法的总执行时间需要after的当前时间减去before的当前时间,这2个时间如何联通也存在困难,AOP 提供一种自定义的通知执行时机-Around Advice(环绕通知)可以轻松解决此需求

1、配置文件:applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns="http://www.springframework.org/schema/beans"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--<context:component-scan base-package="com.text"/>--><bean id="studentDao" class="com.text.dao.impl.StudentDaoImpl"/><!-- 切面类交给IOC容器实例 --><bean id="methodAspect" class="com.text.aspect.MethodAspect"/><!-- aop配置--><aop:config><!-- 切点配置,expression表示com.text所有包及子包项下所有服务层(以DaoImpl结束的类)的所有方法--><aop:pointcut id="pointcut" expression="execution(public * com.text..*DaoImpl.*(..))"/><!-- 切面配置--><aop:aspect ref="methodAspect"><!-- 自定义的环绕通知--><aop:around method="countMethodInvokeTime" pointcut-ref="pointcut"/></aop:aspect></aop:config></beans>

2、服务类及方法(pointcut)

package com.text.dao.impl;
import com.text.dao.StudentDao;public class StudentDaoImpl implements StudentDao {@Overridepublic void getById(String id) throws Exception {Thread.sleep(1000);System.out.println("查询学生id=" + id + "的信息");}
}

3、切面类(aspect) 

package com.text.aspect;import org.aspectj.lang.ProceedingJoinPoint;import java.util.Date;/*** 定义方法切面类*/
public class MethodAspect {public void countMethodInvokeTime(ProceedingJoinPoint proceedingJoinPoint) {System.out.println("目标方法执行之前记录初始时间...");Date startTime = new Date();try {proceedingJoinPoint.proceed();//执行目标方法 即:StudentDaoImpl.getById方法System.out.println("目标方法执行之后记录结束时间...");String methodName = proceedingJoinPoint.getTarget().getClass().getName() + "." +proceedingJoinPoint.getSignature().getName();Date endTime = new Date();System.out.println(methodName + "方法执行总时长为:" + (endTime.getTime() - startTime.getTime()) + "毫秒");} catch (Throwable throwable) {throwable.printStackTrace();}}
}

4、测试类 Application

package com.text;import com.text.dao.StudentDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Application {public static void main(String[] args) throws Exception {ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");StudentDao studentDao = context.getBean("studentDao", StudentDao.class);studentDao.getById("1");System.out.println("======getById end========");}
}

5、输出结果:

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 字节跳动的微服务独家面经
  • 52 文本预处理_by《李沐:动手学深度学习v2》pytorch版
  • docker面经
  • 【ASE】第三课_山丘颜色梯度效果
  • C++——输入三个整数,按照由小到大的顺序输出。用指针方法处理。
  • HTTP(超文本传输协议)基础
  • 【洛谷】P4588 [TJOI2018] 数学计算 的题解 + 线段树板子代码
  • 示例:WPF中Grid显示网格线的几种方式
  • 常见服务端口号和中文大全
  • 2409js,学习js1
  • 【安当产品应用案例100集】017-助力软件服务商高效集成多因素认证
  • 深入探讨 Flask、Gunicorn、Gevent 与 RecursionError:事件循环与 Monkey Patching 的正确使用
  • 常见区块链数据模型介绍
  • 深圳前海壹方汇的免费停车点探寻
  • linux之进程信号
  • 【跃迁之路】【699天】程序员高效学习方法论探索系列(实验阶段456-2019.1.19)...
  • 07.Android之多媒体问题
  • conda常用的命令
  • Cookie 在前端中的实践
  • Git学习与使用心得(1)—— 初始化
  • java正则表式的使用
  • Java知识点总结(JDBC-连接步骤及CRUD)
  • JDK9: 集成 Jshell 和 Maven 项目.
  • leetcode98. Validate Binary Search Tree
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • magento2项目上线注意事项
  • markdown编辑器简评
  • Node 版本管理
  • Promise初体验
  • Python语法速览与机器学习开发环境搭建
  • Python中eval与exec的使用及区别
  • React16时代,该用什么姿势写 React ?
  • tensorflow学习笔记3——MNIST应用篇
  • Vue ES6 Jade Scss Webpack Gulp
  • 电商搜索引擎的架构设计和性能优化
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • 前端面试之CSS3新特性
  • 小试R空间处理新库sf
  • 正则与JS中的正则
  • ​ 无限可能性的探索:Amazon Lightsail轻量应用服务器引领数字化时代创新发展
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • ​软考-高级-系统架构设计师教程(清华第2版)【第20章 系统架构设计师论文写作要点(P717~728)-思维导图】​
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • (3)nginx 配置(nginx.conf)
  • (C)一些题4
  • (cljs/run-at (JSVM. :browser) 搭建刚好可用的开发环境!)
  • (不用互三)AI绘画:科技赋能艺术的崭新时代
  • (超详细)语音信号处理之特征提取
  • (附源码)springboot家庭财务分析系统 毕业设计641323
  • (入门自用)--C++--抽象类--多态原理--虚表--1020
  • (十)c52学习之旅-定时器实验
  • (原)Matlab的svmtrain和svmclassify
  • (转)使用VMware vSphere标准交换机设置网络连接
  • (转载)hibernate缓存
  • .cfg\.dat\.mak(持续补充)