SpringAOP实现的两种方式-JDK动态代理和CGLIB动态代理

前言

想要了解SpringAOP的实现方式,需要先了解什么是AOP

OOP和AOP的区别

  • OOP 面向对象,允许开发者定义纵向的关系,但并适用于定义横向的关系,导致了大量代码的重复,而不利于各个模块的重用。

  • AOP,一般称为面向切面,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证.日志.事务处理。

AOP的核心

        AOP 实现的关键在于 代理模式,AOP 代理主要分为静态代理动态代理。静态代理的代表为 AspectJ;动态代理则以 Spring AOP 为代表

 什么是动态代理?

        Spring AOP 使用的动态代理,所谓的动态代理就是说 AOP 框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个 AOP 对象,这个 AOP 对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。

Spring AOP 中的动态代理主要有两种方式,JDK 动态代理CGLIB 动态代理

 JDK 动态代理

        JDK 动态代理只提供接口的代理,不支持类的代理。核心 InvocationHandler 接口和 Proxy 类,InvocationHandler 通过 invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy利用 InvocationHandler 动态创建一个符合某一接口的的实例, 生成目标类的代理对象。

 CGLIB 动态代理

        如果代理类没有实现 InvocationHandler 接口,那么 Spring AOP 会选择使用 CGLIB 来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现 AOP。CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为 final,那么它是无法使用 CGLIB 做动态代理的。

 JDK 动态代理和 CGLIB 动态代理区别 

  • Spring默认使用JDK动态代理实现AOP代理,主要用于代理接口
  • CGLIB代理,实现类的代理,而不是接口

也就是说,JDK的动态代理是对接口的代理,而CGLIB的代理是对类的代理

 实例分析

JDK动态代理

我们创建一个电冰箱接口,和它的实现类,观察使用JDK代理和CGLIB代理的区别

FridgeBiz

public interface FridgeBiz {/*** 购买电冰箱* @param num*/public void buy(int num,int stock);
}

FridgeBizImpl 

@Component(value = "fridgeBiz")
public class FridgeBizImpl implements FridgeBiz {private int stock;/*** 购买电冰箱** @param num*/@Overridepublic void buy(int num,int stock) {this.stock=stock;System.out.println("顾客购买了"+num+"台电冰箱");}
}

 创建Aspect切面类:

LogAspect

@Aspect
@Component
public class LogAspect {@Pointcut("execution(void com.csx.service.impl.FridgeBizImpl.buy(int,int))")public void pt(){}@Around("pt()")public Object around(ProceedingJoinPoint pjp) throws Throwable {String methodName=  pjp.getSignature().getName();//获取请求方法的参数Object[] args = pjp.getArgs();System.out.println("电冰箱大折扣!,每人限购一台");try {return pjp.proceed();} finally {if ((Integer)args[1]<=(Integer) args[0]){System.out.println("电冰箱数量为"+args[1]+",电冰箱数量不足,请订购");}if ((Integer) args[0]!=1){System.out.println("顾客购买台数为"+args[0]+",超过1台,已限购");}}}}

 配置spring.xml:

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.csx"/><!--启用注解aop--><aop:aspectj-autoproxy/>
</beans>	

在测试类中:

APPTest

在使用JDK的动态代理时,使用的是接口接收aop创建的代理对象

public class AppTest extends TestCase
{@Testpublic void testBefore(){ApplicationContext context =new ClassPathXmlApplicationContext("spring.xml");FridgeBiz fridgeBiz =(FridgeBiz) context.getBean("fridgeBiz");fridgeBiz.buy(2,1);
//获取当前代理对象的全名System.out.println(fridgeBiz.getClass().getName());}
}

 查看结果:

CGLIB动态代理

如果想要使用CGLIB实现动态代理,根据以下步骤操作:

更新spring.xml:

spring.xml

设置 :

proxy-target-class="true"

 修改AppTest,使用实体类接收代理对象

public class AppTest extends TestCase
{@Testpublic void testBefore(){ApplicationContext context =new ClassPathXmlApplicationContext("spring.xml");
//     FridgeBiz fridgeBiz =(FridgeBiz) context.getBean("fridgeBiz");FridgeBizImpl fridgeBiz =(FridgeBizImpl) context.getBean("fridgeBiz");fridgeBiz.buy(2,1);System.out.println(fridgeBiz.getClass().getName());}
}

出现结果:

总结

spring的动态代理主要有两种:

  • JDK 动态代理:生成接口的实现类对象
  • CGLIB 动态代理:生成实现类的子类对象

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

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

相关文章

解决Cloudflare 521错误的四种方法

在使用Cloudflare进行网站加速时&#xff0c;错误521是一个常见的问题&#xff0c;表示“Web服务器关闭”。当你访问某个使用Cloudflare的网站时&#xff0c;如果原始服务器拒绝了Cloudflare的连接请求&#xff0c;浏览器就会显示此错误信息。本文将详细介绍导致错误521的原因&…

如何将list嵌套的list的[]去掉

如果list里里面的元素是数字&#xff0c;‘1’也是可以的&#xff0c;那么我们可以使用np.ravel a [[1,2,3], [5, 2, 8], [7,8,9]]list(np.ravel(a)) #[1, 2, 3, 5, 2, 8, 7, 8, 9]对于不规则List c[[‘云阳站’], [‘双江’, ‘木古’], [‘滨双线’], [‘滨双线’, ‘云田线…

CRM在客户生命周期管理中的高效应用

企业要想在市场中持续增长并脱颖而出&#xff0c;就必须深刻理解并有效管理客户生命周期。客户生命周期&#xff0c;简而言之&#xff0c;是指从客户首次接触企业到最终与企业关系终止的全过程&#xff0c;它涵盖了多个关键阶段&#xff0c;每个阶段都蕴含着不同的机遇与挑战。…

无线领夹麦克风哪个牌子好?2024年口碑最好的领夹麦克风品牌推荐

举国同庆的国庆节快要到了&#xff0c;相信不少朋友都想趁此机会多拍摄一些Vlog来记录美好节日&#xff0c;想要音质效果好&#xff0c;领夹麦克风少不了&#xff01;但是无线领夹麦克风行业看似繁荣的背后&#xff0c;却隐藏着一些不为人知的黑幕。从夸大信号稳定性到忽视音质…

0代码、自动化,让AI视觉算法赋能千行百业(含源代码)

AI视频卫士通过自动化机器学习技术&#xff0c;降低AI开发和训练的门槛&#xff0c;让更多行业能够轻松接入AI&#xff0c;解决实际问题。 例如一个不懂AI的产品经理&#xff0c;但是他知道他想要能够检测到垃圾桶是否装满溢出&#xff0c;那么他只需要上传垃圾桶装垃圾溢的场景…

LangChain进阶技巧:提高聊天机器人性能的策略[第三课]

LangChain应运而生&#xff0c;为开发者们提供了一种高效、便捷的工具&#xff0c;助力他们构建出功能强大的大型语言模型应用。本文将带您走进LangChain的世界&#xff0c;揭秘其背后的技术原理&#xff0c;探讨如何利用这一利器来拓展语言模型的无限可能。通过丰富的实例分析…

“DNA亲和纯化测序:汇智生物的精准分析“

&#x1f331; 汇智生物 | 专注农业&植物基因组分析 &#x1f331; &#x1f393; 教授【优青】团队亲自指导&#xff01;提供专业实验设计、数据分析、SCI论文辅助等全方位服务。精准高效&#xff0c;为农植物科研保驾护航&#xff01; &#x1f52c; 专业实验外包服务&am…

正点原子阿波罗STM32F429IGT6移植zephyr rtos(二)---使用I2C驱动MPU6050

硬件平台&#xff1a;正点原子阿波罗STM32F429IGT6 zephyr版本&#xff1a;Zephyr version 3.7.99 开发环境&#xff1a;ubuntu 24.4 zephyr驱动开发与之前接触到的开发方式可能都不一样&#xff0c;更像是linux驱动开发&#xff0c;zephyr源码里边其实已经有写好的I2C和MPU60…

ST-GCN模型实现花样滑冰动作分类

加入深度实战社区:www.zzgcz.com&#xff0c;免费学习所有深度学习实战项目。 1. 项目简介 本项目实现了A042-ST-GCN模型&#xff0c;用于对花样滑冰动作进行分类。花样滑冰作为一项融合了舞蹈与竞技的运动&#xff0c;其复杂的动作结构和多变的运动轨迹使得动作识别成为一个具…

CRM如何实现对客户信息的全局管理?

在知识产权与科技服务领域中&#xff0c;企业如何精准把握客户需求&#xff0c;高效管理知识产权资产&#xff0c;成为了决定其竞争力的关键因素。传统的CRM虽在一定程度上提升了客户管理效率&#xff0c;但在面对知识产权这一复杂且多变的领域时&#xff0c;往往显得力不从心。…

Html jquery下拉select美化插件——selectFilter.js

1. Html jquery下拉select美化插件——selectFilter.js jQuery是一个广泛使用的JavaScript库&#xff0c;它简化了DOM操作、事件处理、动画以及Ajax交互&#xff0c;使得开发者能更高效地构建交互式网页。在本案例中&#xff0c;jquery.selectlist.js插件正是基于jQuery构建的&…

滑动窗口->dd爱框框

1.题目&#xff1a; 2.题解&#xff1a; 2.1为什么用滑动窗口优化&#xff1a; 因为元素都是大于0的 所以&#xff1a;当找到大于等于x的值时&#xff0c;right可以不用返回 两个指针都往后走&#xff1b;因此可以使用滑动窗口优化暴力解法 2.2&#xff1a;滑动窗口具体使用步…

python flask实现mock接口

在 Flask 中实现模拟&#xff08;mock&#xff09;接口通常是为了在没有实际后端服务的情况下进行前端开发、单元测试或集成测试。你可以创建一个简单的 Flask 应用来模拟特定的 API 行为&#xff0c;返回预设的数据。以下是如何使用 Flask 实现一个 mock 接口的示例&#xff1…

NAT模式 LVS负载均衡群集部署

目录 NAT模式 LVS负载均衡群集部署 1.关闭所有虚拟机的防火墙和核心防护 2.部署共享存储nfs&#xff08;ip:192.168.110.20&#xff09; 3.配置nginx节点服务器&#xff08;192.168.110.70&#xff0c;192.168.110.80&#xff09; 4.配置tomcat节点服务器&#xff08;192.…

c++第十二章续(队列结构类模拟)

队列类 设计类&#xff0c;需要开发公有接口和私有实现 Queue类接口 公有接口&#xff1a; 默认初始化&#xff0c;和可以用显式初始化覆盖默认值 Queue类的实现 如何表示队列数据&#xff1a; 一种方法是使用new动态分配一个数组&#xff0c;它包含所需的元素数。不过&…

知乎信息流广告营销获客投放策略!

知乎内容营销已成为品牌吸引目标客户、提升品牌知名度的重要手段&#xff0c;吸引了众多企业的关注。为了更好地利用知乎这一平台进行品牌推广&#xff0c;越来越多的企业开始关注知乎信息流广告的投放。云衔科技通过知乎信息流广告实现高效的营销获客&#xff0c;为企业提供知…

如何实现一个优秀的散列表!

文章内容收录到个人网站&#xff0c;方便阅读&#xff1a;http://hardyfish.top/ 文章内容收录到个人网站&#xff0c;方便阅读&#xff1a;http://hardyfish.top/ 文章内容收录到个人网站&#xff0c;方便阅读&#xff1a;http://hardyfish.top/ 前言 假设现在有一篇很长的…

锦囊妙计系列:没有项目支撑的情况下怎么从java到Python平稳过度并就业成功

从Java转向Python&#xff0c;并在没有项目支撑的情况下平稳过渡并实现就业&#xff0c;尽管有挑战&#xff0c;但完全可以通过系统学习、项目积累、技能展示和策略性求职来达成目标。以下是详细的步骤和策略&#xff0c;帮助你在不依赖现有项目的情况下实现从Java到Python的成…

24.9.29

星期一&#xff1a; 补 cf round974 div3 H cf传送门 题意&#xff1a;给一数组&#xff0c;q次询问&#xff0c;每次询问l-r区间内是否每个数字都出现偶数次 终于找到了梦中的随机数函数&#xff0c;这随机数真是非常顶级口牙 思路&a…

在线SQL模拟器

前言 有时候我们想学习下SQL&#xff0c;但是缺少数据库环境&#xff0c;多种数据库类型&#xff0c;MySQL&#xff0c;SQL server&#xff0c;Oracle&#xff0c;PostgreSQL等等&#xff0c;自己安装&#xff1f;耗时费力&#xff0c;占用电脑资源&#xff0c;要是有一个在线…