Spring基于AOP(面向切面编程)开发

news2025/2/25 23:03:12

概述

        AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

为什么要学习AOP

在不修改源代码的情况下,对原方法进行增强

AOP可以校验,日志记录,性能监控,事务控制

底层实现(了解)

代理机制:

Spring的AOP的底层用到两种代理机制

        JDK动态代理:针对实现了接口的类产生的代理

        Cglib动态代理:针对没有接口的类产生的代理,应用了底层的字节码增强的技术,生成当前的子类对象

JDK动态代理

创建一个代理类

public class ProxyUser implements InvocationHandler {
	private Object target; // 代理的目标对象
	public LogJdkProxy(Object target) {
		this.target = target;
	}
	/** 创建代理对象 */
	public Object createProxyInstance() {
		// 第1个参数设置代码使用的类装载器,一般采用跟目标类相同的类装载器
		// 第2个参数设置代理类实现的接口
		// 第3个参数设置回调对象,当代理对象的方法被调用时,会调用该参数指定对象的invoke方法
		return Proxy.newProxyInstance(//
				getClass().getClassLoader(), // 第1个参数
				target.getClass().getInterfaces(), // 第2个参数
				this); // 第3个参数
	}
	/**
	 * @param proxy  目标对象的代理类实例
	 * @param method 对应于在代理实例上调用接口方法的Method实例
	 * @param args   传入到代理实例上方法参数值的对象数组
	 * @return 方法的返回值,没有返回值(void)时是null
	 */
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("== Log:开始执行操作,方法名:"+method.getName()+" ==");
		Object result = method.invoke(target, args); // 执行原方法,把方法调用委派给目标对象
		System.out.println("== Log:操作执行完毕 ==");
		return result;
	}
}

测试

Cglib动态代理

创建对象接口

// 此类不能是final的,否则不能有子类,CGLIB也就不能工作了
public class UserServiceImpl {
 
	// 这是final的方法,不能被子类重写,所以CGLIB不会拦截这个方法
	public final void foo1() {
		System.out.println(">> final的方法 <<");
	}
 
	// 这是static的方法,CGLIB不会拦截这个方法
	public static void foo2() {
		System.out.println(">> static的方法 <<");
	}
 
	// 这是private的方法,CGLIB不会拦截这个方法
	private void foo3() {
		System.out.println(">> private的方法 <<");
	}
 
	// CGLIB会拦截这个方法,可以是public, protected, default的修饰符
	public void deleteUser() {
		System.out.println(">> 删除一个User <<");
	}
}

创建Cglib代理类

// CGLIB代理类
public class LogCglibProxy implements MethodInterceptor {
	private Object target; // 代理的目标对象
	/**
	 * 创建代理对象
	 * @param <T>
	 * @param target 目标对象
	 */
	public <T> T createProxyInstance(T target) {
		this.target = target;
		Enhancer enhancer = new Enhancer(); // 该类用于生成代理对象
		enhancer.setSuperclass(target.getClass()); // 设置父类
		enhancer.setCallback(this); // 设置回调对象为自己这个对象
		return (T) enhancer.create(); // 创建代理对象并返回
	}
	/**
	 * @param proxy 		 目标对象代理类的实例
	 * @param method		代理类实例上调用父类方法的Method实例
	 * @param args 			传入到方法参数值的对象数组
	 * @param methodProxy 	使用它调用父类的方法
	 */
	@Override
	public Object intercept(Object proxy, Method method, Object[] args, 
MethodProxy methodProxy)	throws Throwable {
		System.out.println(proxy.getClass());
		System.out.println("== Log:开始执行操作,方法名:" + method.getName() + " ==");
		Object result = methodProxy.invoke(target, args); // 执行原方法
		System.out.println("== Log:操作执行完毕 ==");
		return result;
	}
}

测试

public class MainTest {

	@Test
	public void test() throws Exception {
		UserService userService = new UserService();
		userService = (UserService) new LogCglibProxy().createProxyInstance(userService); // 使用包装之的后的代理对象

		userService.saveUser();
		System.out.println();

		userService.deleteUser();
		System.out.println();
}
}

Spring使用AspectJ进行AOP开发

引入lib包

引入配置文件

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>
使用xml配置文件形式

通知类型

切入点表达式

编写一个切面类

public class MyAspectXml {
// 前置增强
public void before(){
System.out.println("前置增强===========");
    }
}

在application Context.xml中配置

<!-- 配置切面类 -->
<bean id="myAspectXml" class="cn.test.spring.demo3.MyAspectXml"></bean>
<!-- 进行 aop 的配置 -->
<aop:config>
<!-- 配置切入点表达式:哪些类的哪些方法需要进行增强 -->
<aop:pointcut expression="execution(* cn.test.spring.demo3.OrderDao.save(..))" id="pointcut1"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspectXml">
<aop:before method="before" pointcut-ref="pointcut1"/> </aop:aspect>
</aop:config>
使用注解来实现切面类

开启aop注解自动代理

AspectJ的AOP注解

@Aspect  定义切面类

通知类型

@Before        前置通知

@AfterReturing        后置通知

@Around        环绕通知

@After        最终通知

@AfterThrowing        异常抛出通知

@Pointcut        定义切入点

编写切面类

@Component
@Aspect
public class MyAspect {
    @Before("MyAspect.pointcut01()")
    public void before(){
        System.out.println("前置-----");
    }

    @After("MyAspect.pointcut01()")
    public void after(){
        System.out.println("后置-----");
    }
    @Pointcut("execution(* com.xuexi.dao.*.*(..))")
    public void pointcut01(){

    }
}

测试

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

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

相关文章

使用WAF防御之网络上的隐蔽威胁(XSS攻击)

跨站脚本攻击&#xff08;XSS&#xff09;是一种常见且危险的威胁。它允许攻击者在用户浏览器上执行恶意脚本&#xff0c;窃取信息、篡改网页内容&#xff0c;甚至劫持用户会话。 什么是XSS攻击 定义&#xff1a;XSS攻击是一种代码注入技术&#xff0c;攻击者通过在目标网站上…

练习题 删除链表的倒数第N个结点

题目 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;head [1], n 1 输出&#xff1a;[]示例 3&#…

潍坊数字孪生元宇宙赋能智能制造,助力工业制造业数字化转型

潍坊工业元宇宙数字孪生赋能智能制造&#xff0c;助力工业制造业数字化转型。在当今数字化时代&#xff0c;工业智能制造已成为制造业发展的必然趋势。潍坊市作为山东省的重要工业基地&#xff0c;积极探索数字孪生技术在工业智能制造领域的应用&#xff0c;为制造业企业数字化…

ant-design-vue Notification 通知提醒框 内容换行

直接上代码 const msg errArr.map((message, index) > ${index 1}. ${message};) notification.open({message: ${statu.moduleName} 告警信息,description: () > {// 将msg所有;替换为\n换行符const res msg.replaceAll(;, \n)return h(pre,{style: {overflow: scro…

Transformer简单理解

目录 一、CNN存在的问题&#xff1a;二.Transformer整理架构分析&#xff1a;1.Linear Projection of Flattened Patches层形成Patch&#xff1a;2.对每个Patch进行位置编码Position Embedding&#xff1a;3.Transformer Encoder: 三.公式解读&#xff1a; 一、CNN存在的问题&a…

为什么使用 atan2(sin(z), cos(z)) 进行角度归一化?

文章目录 为什么使用 atan2(sin(z), cos(z)) 进行归一化&#xff1f;为什么归一化后的角度等于原始角度&#xff1f; atan2 方法返回 -π 到 π 之间的值&#xff0c;代表点 (x, y) 相对于正X轴的偏移角度。这个角度是逆时针测量的&#xff0c;以弧度为单位。关于 atan2 函数为…

【JAVA WEB】 Filter过滤器详解

目录 1&#xff0c;Filter 1.1 Filter概述 1.2 Filter快速入门 1.2.1 开发步骤 1.2.2 代码演示 1.3 Filter执行流程 1.4 Filter拦截路径配置 1.5 过滤器链 1.5.1 概述 1.5.2 代码演示 1.5.3 问题 1.6 案例 1.6.1 需求 1.6.2 分析 1.6.3 代码实现 1.6.3.1 创建Fi…

ERP系统怎么选 企业ERP管理系统选型建议

市面上有众多的ERP系统&#xff0c;而由于不同软件供应商的发展策略不同&#xff0c;导致不同ERP系统的侧重点也不同。例如有针对企业某一类管理需求的ERP系统&#xff0c;例如财务管理软件&#xff0c;进销存管理软件&#xff0c;仓库管理软件等。还有针对企业资源整合&#x…

element-ui表单验证同时用change与blur一起验证

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 当审批时不通过审批意见要必须输入&#xff0c; 1&#xff1a;如果用change验证的话删除所有内容时报错是massage的提示&#xff0c;但是在失去焦点的时候报错就成了英文&#xff0c;如下图&#xf…

【iOS】数据存储方式总结(持久化)沙盒结构

在iOS开发中&#xff0c;我们经常性地需要存储一些状态和数据&#xff0c;比如用户对于App的相关设置、需要在本地缓存的数据等等&#xff0c;本篇文章将介绍六个主要的数据存储方式 iOS中数据存储方式&#xff08;数据持久化&#xff09; 根据要存储的数据大小、存储数据以及…

计算机毕业设计 | SpringBoot宠物店管理系统(附源码)

1&#xff0c;绪论 项目背景 我国已经成为世界第二大经济体&#xff0c;经济实力高速发展以及百姓生活水平的普遍提高&#xff0c;不断地要求企业提供更加多元化的娱乐方式&#xff0c;更加快速和方便的服务&#xff0c;因此对宠物行业也提出了更加严格的要求&#xff0c;如管…

【NI国产替代】NI‑9232,3通道,102.4 kS/s/ch,±30 V,C系列声音与振动输入模块

3通道&#xff0c;102.4 kS/s/ch&#xff0c;30 V&#xff0c;C系列声音与振动输入模块 NI‑9232可以测量来自集成电子压电(IEPE)和非IEPE传感器的信号&#xff0c;例如加速度计、转速计和接近式探针。 NI‑9232还可兼容智能TEDS传感器。\n\nNI‑9232集成了软件可选的AC/DC耦合…

Window——安装nacos

1、Git拉取项目 官方地址&#xff1a;https://nacos.io/zh-cn/ git clone https://github.com/alibaba/nacos.git2、进入项目执行命令安装&#xff08;需要maven&#xff09; Maven下载指引&#xff1a;https://blog.csdn.net/qq812457115/article/details/117451334 mvn -Prel…

JRT核心竞争力

如果说JRT业务脚本化和发部署简单和打印导出客户端都不足以抵挡Spring用的人多的优势的话。那么这一篇让DolerGet给你一个选择JRT的理由&#xff0c;借助JRT自我实现的ORM&#xff0c;JRT有能力完全把控更新数据和删除数据的口径&#xff0c;和能够准确知道哪些是热点数据&…

UDP传输总丢包?常用的解决方式在这里!

UDP是一种无连接的协议&#xff0c;传输数据时不建立连接&#xff0c;因此可能导致数据包丢失。UDP丢包是指在传输过程中由于各种原因导致数据包未能到达目的地。UDP丢包会影响传输的质量和效率&#xff0c;导致数据损失、延迟&#xff0c;甚至导致传输失败。本文将分析UDP丢包…

guns项目 Failed to register @ServerEndpoint class 问题

问题发生所在 socket-business-websocket-7.2.4.jar tomcat发布测试的时候报Failed to register ServerEndpoint class &#xff0c;查询jar报主要是WebSocketServer 类加载有问题&#xff0c;把jar报中该类注掉&#xff0c;重新实现这个类&#xff0c;删除Component注解问题&…

Linux信号之信号的保存

(&#xff61;&#xff65;∀&#xff65;)&#xff89;&#xff9e;嗨&#xff01;你好这里是ky233的主页&#xff1a;这里是ky233的主页&#xff0c;欢迎光临~https://blog.csdn.net/ky233?typeblog 点个关注不迷路⌯▾⌯ 目录 一、阻塞信号 1.信号递达、未决、阻塞 2.内核…

yolov1:背景介绍与算法精讲

目录 一、背景介绍1.1 yolo发展历史1.2 作者介绍 二、算法精讲2.1 预测阶段2.2 训练阶段 三、论文细节 一、背景介绍 其实在写这篇博客的时候yolov1~yolov8的所有网络结构以及算法思想和源码都已经研究很久了&#xff0c;回过头继续读v1会发现有很多细节是自己没有留意的&#…

Linux上新部署的项目jar包没有生效

今天公司新安排了一个项目&#xff0c;这里简称项目A&#xff0c;需要新增两个功能&#xff0c;我这边完成之后&#xff0c;跟前端对接好了&#xff0c;调试也没有问题。 然后把项目打包上传到测试服务器上&#xff0c;重新启动项目&#xff0c;发现项目A新增的接口没有生效&a…

多变量线性回归

一、多维特征 目前为止&#xff0c;我们探讨了单变量/特征的回归模型&#xff0c;现在我们对房价模型增加更多的特征&#xff0c;例如房间数、楼层等&#xff0c;构成一个含有多个变量的模型&#xff0c;模型中的特征为。 增添更多特征后&#xff0c;我们引入一系列新的注释&am…