基于Spring3.0实现AOP的小案例

前言

AOP(Aspect Oriented Programming)即面向切面编程,是一种通过预编译方式和运行期间动态代理实现程序功能统一维护的技术。针对功能增强的描述,可以理解为:“AOP允许在不修改源代码的情况下,通过定义切面(Aspect)和切入点(Pointcut),对目标对象的方法进行功能增强。”

具体来说,AOP能够将业务逻辑中的横切关注点(如日志、安全、事务等)与核心业务逻辑分离,从而降低代码间的耦合度,提高程序的可重用性和开发效率。在Spring框架中,AOP提供了多种增强类型,如前置增强、后置增强、环绕增强、异常抛出增强和引介增强等,这些增强类型可以灵活应用于不同的业务场景,以满足不同的功能需求。

 案例分析

实现手机购买和售卖的案例,利用AOP添加日志功能,显示当前时间等信息。

案例实现

 第一步:创建maven项目,导入相关依赖

pom.xml

这是spring3.0使用AOP的相关依赖,如果使用的是spring5.0以上,导包可能没有这么多,这是我的spring3.0 AOP的最佳实践

<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>3.0.5.RELEASE</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>3.0.5.RELEASE</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.6.11</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>3.0.5.RELEASE</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.6.11</version></dependency><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>2.1</version></dependency>

第二步:创建service层业务,创建接口和实现类完成基本功能

 

PhoneBiz

public interface PhoneBiz {void buyPhone(int num);void salePhone(int num) throws OutOfStackException;
}

PhoneBizImpl

public class PhoneBizImpl implements PhoneBiz {int num;  //库存@Overridepublic void buyPhone(int num) {System.out.println("手机进货,数量为"+num+"部");this.num+=num;}@Overridepublic void salePhone(int num) throws OutOfStackException {System.out.println("手机销售,数量为"+num+"部");}
}

第三步:创建LogAspect切面类和spring的配置文件spring.xml

LogAspect

完成前置通知,在原始方法执行前进行日志输出

public class LogAspect {public String currTime(){SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");return sdf.format(new Date());}/*** 前置通知* @param jp*/public void before(JoinPoint jp){//获得请求方法的参数Object[] args= jp.getArgs();//获得请求方法名String methodName= jp.getSignature().getName();if ("buyPhone".equals(methodName)){System.out.println("日志:"+currTime()+",即将开始进货操作,数量为"+args[0]+"部");}if ("salePhone".equals(methodName)){System.out.println("日志:"+currTime()+",即将开始销售操作,数量为"+args[0]+"部");}}

spring.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:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.0.xsd"><bean id="phoneBiz" class="com.by.service.PhoneBizImpl"></bean><bean id="logAspectBean" class="com.by.util.LogAspect"></bean><aop:config proxy-target-class="true"><aop:pointcut id="p1" expression="execution( void *Phone(int))"/><aop:aspect id="logAspect" ref="logAspectBean"><aop:before method="before" pointcut-ref="p1"/></aop:aspect></aop:config></beans>

 第四步:分别完成最终通知,后置通知,异常通知,环绕通知

LogAspect

 /*** 后置通知* @param jp*/public void afterReturing(JoinPoint jp){//获得请求方法的参数Object[] args= jp.getArgs();//获得请求方法名String methodName= jp.getSignature().getName();if ("buyPhone".equals(methodName)){System.out.println("日志:"+currTime()+",进货操作结束,数量为"+args[0]+"部");}if ("salePhone".equals(methodName)){System.out.println("日志:"+currTime()+",销售操作结束,数量为"+args[0]+"部");}}/*** 异常通知* @param jp* @param e*/public void afterThrowing(JoinPoint jp,OutOfStackException e){String methodName= jp.getSignature().getName();System.out.println(currTime()+":"+methodName+"发生异常:"+e.getMessage());}/*** 后置通知,发生异常也会执行* @param jp*/public void after(JoinPoint jp){String methodName= jp.getSignature().getName();if ("buyPhone".equals(methodName)){System.out.println("日志:"+currTime()+",进货操作完毕,发生异常也会执行");}if ("salePhone".equals(methodName)){System.out.println("日志:"+currTime()+",销售操作完毕,发生异常也会执行");}}/*** 环绕通知* @param pjp* @return* @throws Throwable*/public Object around(ProceedingJoinPoint pjp) throws Throwable {String methodName=  pjp.getSignature().getName();System.out.println(methodName+"方法开始执行:");long begin= System.currentTimeMillis();try {return pjp.proceed();} finally {long end= System.currentTimeMillis();System.out.println(methodName+"方法执行完毕,耗时"+(end-begin)+"毫秒");}}public String currTime(){SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");return sdf.format(new Date());}

spring.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:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.0.xsd"><bean id="phoneBiz" class="com.by.service.PhoneBizImpl"></bean><bean id="logAspectBean" class="com.by.util.LogAspect"></bean><aop:config proxy-target-class="true"><aop:pointcut id="p1" expression="execution( void *Phone(int))"/><aop:aspect id="logAspect" ref="logAspectBean"><aop:before method="before" pointcut-ref="p1"/><aop:after-returning method="afterReturing" pointcut-ref="p1"/><aop:after-throwing method="afterThrowing" pointcut-ref="p1" throwing="e"/><aop:after method="after" pointcut-ref="p1"/><aop:around method="around" pointcut-ref="p1"/></aop:aspect></aop:config></beans>

注意:如果要完成异常通知,需要预先自定义一个异常类。

package com.by.util;/*** 库存异常类*/
public class OutOfStackException extends Exception {public OutOfStackException(String message) {super(message);}
}

在PhoneBizImpl中新增判断语句

  @Overridepublic void salePhone(int num) throws OutOfStackException {if (this.num<num){throw  new OutOfStackException("库存不足,需要"+num+"部,只有"+this.num+"部");}System.out.println("手机销售,数量为"+num+"部");}

 

第五步:将配置文件配置AOP的操作改为注解实现

将spring.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:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.0.xsd"><context:component-scan base-package="com.by"/><!--启用注解aop--><aop:aspectj-autoproxy/><!--    <bean id="phoneBiz" class="com.by.service.PhoneBizImpl"></bean>--><!--    <bean id="logAspectBean" class="com.by.util.LogAspect"></bean>--><!--    <aop:config proxy-target-class="true">-->
<!--        <aop:pointcut id="p1" expression="execution( void *Phone(int))"/>-->
<!--        <aop:aspect id="logAspect" ref="logAspectBean">-->
<!--            <aop:before method="before" pointcut-ref="p1"/>-->
<!--            <aop:after-returning method="afterReturing" pointcut-ref="p1"/>-->
<!--            <aop:after-throwing method="afterThrowing" pointcut-ref="p1" throwing="e"/>-->
<!--            <aop:after method="after" pointcut-ref="p1"/>-->
<!--            <aop:around method="around" pointcut-ref="p1"/>-->
<!--        </aop:aspect>-->
<!--    </aop:config>--></beans>

 在PhoneBizImpl实现类中:

@Component(value = "phoneBiz")
public class PhoneBizImpl implements PhoneBiz {
...}

 在LogAspect中使用注解:

/*** 通知类*/
@Aspect
@Component
public class LogAspect {/*** 前置通知* @param jp*/@Before("p1()")public void before(JoinPoint jp){//获得请求方法的参数Object[] args= jp.getArgs();//获得请求方法名String methodName= jp.getSignature().getName();if ("buyPhone".equals(methodName)){System.out.println("日志:"+currTime()+",即将开始进货操作,数量为"+args[0]+"部");}if ("salePhone".equals(methodName)){System.out.println("日志:"+currTime()+",即将开始销售操作,数量为"+args[0]+"部");}}/*** 后置通知* @param jp*/@AfterReturning("execution( void *Phone(int))")public void afterReturing(JoinPoint jp){//获得请求方法的参数Object[] args= jp.getArgs();//获得请求方法名String methodName= jp.getSignature().getName();if ("buyPhone".equals(methodName)){System.out.println("日志:"+currTime()+",进货操作结束,数量为"+args[0]+"部");}if ("salePhone".equals(methodName)){System.out.println("日志:"+currTime()+",销售操作结束,数量为"+args[0]+"部");}}/*** 异常通知* @param jp* @param e*/@AfterThrowing(pointcut = "execution( void *Phone(int))",throwing = "e")public void afterThrowing(JoinPoint jp,OutOfStackException e){String methodName= jp.getSignature().getName();System.out.println(currTime()+":"+methodName+"发生异常:"+e.getMessage());}/*** 后置通知,发生异常也会执行* @param jp*/@After("execution( void *Phone(int))")public void after(JoinPoint jp){String methodName= jp.getSignature().getName();if ("buyPhone".equals(methodName)){System.out.println("日志:"+currTime()+",进货操作完毕,发生异常也会执行");}if ("salePhone".equals(methodName)){System.out.println("日志:"+currTime()+",销售操作完毕,发生异常也会执行");}}/*** 环绕通知* @param pjp* @return* @throws Throwable*/@Around("execution( void *Phone(int))")public Object around(ProceedingJoinPoint pjp) throws Throwable {String methodName=  pjp.getSignature().getName();System.out.println(methodName+"方法开始执行:");long begin= System.currentTimeMillis();try {return pjp.proceed();} finally {long end= System.currentTimeMillis();System.out.println(methodName+"方法执行完毕,耗时"+(end-begin)+"毫秒");}}@Pointcut("execution( void *Phone(int))")public void p1(){}public String currTime(){SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");return sdf.format(new Date());}
}

总结

以上是基于spring3.0使用AOP实现日志记录功能的小案例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1550269.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

刚毕业就做项目经理,现在感觉越做越没动力,还有必要坚持下去吗?

那种一毕业就做项目经理的&#xff0c;以为是少走10年弯路&#xff0c;干了一年后&#xff0c;才发现这简直就是在坑自己。没点真材实料&#xff0c;经理也变成了“空中架子”。 因此&#xff0c;很多一毕业就当上项目经理的人&#xff0c;要么是干着干着就转回到技术岗位&…

【py】字符串切片

下面是一个简单的Python脚本&#xff0c;它读取输入的学号和姓名&#xff0c;然后按照要求拆分并输出&#xff1a; # 从键盘输入学号和姓名 input_str input("请输入学号和姓名&#xff1a;") # 学号和姓名的长度&#xff0c;可以根据实际情况调整 grade_length …

C语言自定义类型:枚举

目录 前言枚举类型1.枚举类型的声明2.枚举类型的优点3.枚举类型的使⽤ 总结 前言 这期我们来学习C语言的最后一个自定义类型——枚举&#xff0c;话不多说&#xff0c;正文开始&#xff1a; 枚举类型 1.枚举类型的声明 枚举顾名思义就是⼀⼀列举。 把可能的取值⼀⼀列举。 …

外资在华 | 这家欧洲医疗诊断龙头如何用纷享销客CRM深耕中国市场

该公司的起源可以追溯到19世纪末的欧洲&#xff0c;是全球体外诊断领域的领军企业之一。 目前该公司经营产品超过2000余种&#xff0c;在全球细菌学市场占据领先地位&#xff0c;市场占有率超过20%&#xff0c;是全球TOP5级别的感染性疾病诊断厂家&#xff0c;占全球超10%的市…

GPG error golang 1.19

1. 问题描述及原因分析 在飞腾2000的服务器&#xff0c;OS为Kylin Linux Advanced Server release V10环境下&#xff0c;docker版本为18.09.0&#xff08;docker-engine-18.09.0-101.ky10.aarch64&#xff09;&#xff0c;基于容器镜像golang:1.19编译新的容器镜像&#xff0…

第二百五十九节 JPA教程 - JPA查询选择两个属性示例

JPA教程 - JPA查询选择两个属性示例 从别名开始&#xff0c;我们可以使用点&#xff08;.&#xff09;运算符浏览实体关系。 以下JPQL从一个实体中选择两个属性。 List l em.createQuery("SELECT e.name, e.salary FROM Professor e")例子 下面的代码来自PersonDa…

四川财谷通信息技术有限公司抖音小店领域的强势力量

在数字化浪潮汹涌的今天&#xff0c;电商行业以其独特的魅力和无限潜力&#xff0c;成为了推动经济发展的重要力量。而在这片充满机遇与挑战的电商蓝海中&#xff0c;四川财谷通信息技术有限公司凭借其敏锐的市场洞察、创新的技术实力以及优质的服务品质&#xff0c;迅速崛起为…

无人机在农业方面的应用!

一、提高农业生产效率 通过搭载农业智能传感器和喷洒设备&#xff0c;可以实现对农田的精准施肥和喷药。这种方式不仅减少了农药和化肥的浪费&#xff0c;还降低了对环境的污染&#xff0c;提高了农业生产效率。 无人机利用热、多光谱和高光谱技术&#xff0c;可以高效、准确…

低代码统一代办系统:提升工作效率的新利器

什么是低代码统一代办系统&#xff1f; 低代码统一代办系统是通过低代码开发平台构建的一种工具&#xff0c;用于集中管理和跟踪团队成员的任务和待办事项。该系统具有可视化设计、模块化组件和灵活性&#xff0c;能够快速适应不同团队和项目的需求&#xff0c;提高工作效率。…

海滨体育馆管理:SpringBoot系统设计与实现

1引言 1.1课题背景 当今时代是飞速发展的信息时代。在各行各业中离不开信息处理&#xff0c;这正是计算机被广泛应用于信息管理系统的环境。计算机的最大好处在于利用它能够进行信息管理。使用计算机进行信息控制&#xff0c;不仅提高了工作效率&#xff0c;而且大大的提高了其…

关于没有启用root问题,分区表挂载错误,导致系统无法启动

1、为啥这样设置&#xff0c;root 2、密码破解也无效 2.1、开机启动&#xff0c;按 e 进入启动文件界面 2.2、把ro修改为rw&#xff0c;注意r和o之间包了个反斜杠 2.3、ctrl x退出当前模式 2.4、rw initsysroot/bin/sh 2.5、chroot /sysroot 2.6、然后输入touch /.autorelabe…

数字人直播屡次违规真相曝光!有哪些技术可以有效解决?

随着数字人直播的应用频率不断升高&#xff0c;其所蕴含着的市场需求和收益潜力日渐显现&#xff0c;让其用户规模得以持续扩大的同时&#xff0c;也让不少创业者都有了找数字人源码厂商搭建数字人直播系统的计划。在此背景下&#xff0c;与数字人直播违规吗相关的各类话题和答…

【Python报错已解决】NameError: name ‘time‘ is not defined

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

Shopline对接需要注意的问题

Shopline对接是一项复杂而细致的工作&#xff0c;为了确保对接的顺利进行&#xff0c;并保证系统的稳定性和可靠性&#xff0c;需要注意以下几个方面。 1.API文档的详细阅读 功能理解&#xff1a; 仔细阅读Shopline提供的API文档&#xff0c;全面了解每个接口的功能、参数、返…

T536 工业级设备处理器:为智能硬件与工业应用打造的高性能解决方案

T536 工业级设备处理器&#xff1a;为智能硬件与工业应用打造的高性能解决方案 引言 在当今快速发展的科技时代&#xff0c;工业自动化和智能硬件领域对处理器的需求日益增长。为了满足这一需求&#xff0c;Allwinner Technology推出了T536系列处理器&#xff0c;这是一款专为…

kafka发送消费核心参数与设计原理详解

核心参数详解: 发送端参数: 发送方式:默认值一般都是1: 重试参数 : 批量参数: 消费端参数: 自动提交参数: 如果是false,就是说消费完后不提交位移。也就是说比如之前消费的1-5.第N次还是消费到1-5.如果是false。那么第一次消费1-3,第二次消费4-5:默认是true:我们…

State-实时监测Mac运行状态,为你的Mac保驾护航!

你有没有遇到过这样的情况&#xff1a;当你的电脑突然变得非常慢&#xff0c;或者应用程序崩溃&#xff0c;你却无法确定是什么原因导致的呢&#xff1f; 这时候&#xff0c;一个可以实时监测电脑运行状态的软件就显得尤为重要。它可以帮助我们获取电脑的运行数据&#xff0c;让…

使用WPF实现一个快速切换JDK版本的客户端工具

发现网上一键切换JDK环境的方法都是在mac或Linux下的&#xff0c;本人主力电脑是Windows&#xff0c;于是看了一下WPF的文档&#xff0c;自己开发了一个客户端。 直接上代码吧&#xff1a; using JavaSwitch.Properties; using Newtonsoft.Json; using System; using System.…

3种方法解决Docker容器中配置运行环境问题

1. dockerfile用于通过脚本生成镜像 2.进入docker容器后&#xff0c;配置环境完&#xff0c;导出容器快照为镜像&#xff0c;拷贝到另一个主机&#xff0c;再进行加载&#xff1b; 3.在本地将依赖库等需要的文件按照目录整理好&#xff0c;映射到docker中。 1. dockerfile用于…

系统架构设计师-知识产权与标准化

目录 一、保护范围与对象 二、保护期限 三、知识产权人确定 四、侵权判断 五、标准化 一、保护范围与对象 知识产权是权利人依法就下列课题享有的专有权利&#xff1a; &#xff08;一&#xff09;作品&#xff08;著作&#xff09; &#xff08;二&#xff09;发明、实用…