Spring事务管理和代理模式

10分钟上手YOLOv11:最强姿态估计模型来了,代码开源,效果炸裂! 【10分钟玩转YOLOv11实时姿态估计】🚀 YOLOv11作为YOLO家族最新成员,在速度、精度和易用性上全面升级,尤其适用于姿态估计等复杂视觉任务。本文带您快速掌握: 1️⃣ 核心概念:姿态估计即识别人体17个关键点(如关节部位)并连接成数字骨架,是智能健身、体感游戏等应用的基础。 2️⃣ 技术优势: 超轻量级(最小仅2.9M参数) 极速推理(GPU仅1.7ms) 高精度(COCO mAP@50-95达50%) 3️⃣ 三步实操: ① 安装:pip install ultralytics ② 准备人物 阅读详情

前言

最近在开发业务代码的时候,犯了一个事务注解的错误:在同一个类的非事务方法中调用了另一个事务方法,导致事务没有生效,如下所示:

public ConfirmOrderResultVO batchConfirmPurchaseOrders(Long taobaoUserId, List<String> bizOrderIds) throws TCException {        ………………………………………………………………        for (String bizOrderId : bizOrderIds) {            // 推单成功进入successList,否则进入failedList            if (confirmPurchaseOrder(taobaoUserId, bizOrderId)){                successList.add(Long.valueOf(bizOrderId));            }else {                failedList.add(Long.valueOf(bizOrderId));            }        }        ………………………………………………………………    }

其中confirmPurchaseOrder()是一个事务方法:

@Transactionalpublic Boolean confirmPurchaseOrder(Long taobaoUserId, String bizOrderId) throws TCException {      logger.warn("|ConfirmPurchaseOrder|UserId:"+taobaoUserId+",orderId:"+bizOrderId);      …………………………      return ture;}

这样在直接调用
batchConfirmPurchaseOrders()方法时,如果confirmPurchaseOrder()方法发生了异常,是不会回滚的。原理在于Spring的事务管理依靠的动态代理模式,当在同一个类中调用一个非事务方法,是不会生成代理对象的,自然也不会触发事务。借此机会回顾一下代理模式和Spring事务管理的原理。

代理模式

网上讲解代理模式的文章千奇百怪,很多时候看完了也不明白讲的重点是什么。

事实上在生活中我们常常会遇到各种各样的代理模式,例如火车票代售点代理出售火车票,他在“帮忙”出售火车票的同时,收取了额外的手续费,记录了自己店里的流水等。

又比如班长代理老师来上交班费,他在“上交班费”的动作之前,还进行了检查班级同学是否到齐、向每一位同学收班费、核对班费金额,最后再上交班费。

总而言之,代理模式就是 代理其他对象,在完成原动作的基础上(前后)做一些额外的自定义的工作 。

聪明的朋友看到这里一定想到了:那我在一个方法中调用另一个方法不就是代理模式了吗?啊对对对,从功能上来讲是一样的,但是“模式”之所以为“模式”,以我拙见,其本质目的在于形成规范,以减少重复代码的编写。因此如果不能达到减少代码重复的本质目的,便不能称之为“模式”。

按照代理模式的实现方式,分为两种:静态代理和动态代理。那我们就拿刚刚说过的“写作业”这件事来做例子,讲解一下两种实现方式的区别。

▐静态代理

首先定义一个“作业”接口,里面有一个方法“做作业”

public interface Homework {    void doHomework();}

小红实现了这个接口。但是小红是一个不爱学习的小学生,又因为师从马掌门成为了学校的扛把子,所以为了不让老师发现,他决定自己随便做做,把剩下的部分交给小弟们来做。

public class XiaoHong implements Homework{    @Override    public void doHomework() {        System.out.println("XiaoHong did homework casually");    }}

其中小王、小张两个小弟成绩优异,一个负责数学作业,一个负责英语作业,于是他们两个自告奋勇实现了Homework接口,在代理完成作业的基础上,还不断学习提高自己的能力,并且对作业答案进行了校验。

小王:

public class XiaoWang implements Homework{    // 持有Homework属性    private Homework homework;    // 通过构造函数初始化Homework    public XiaoWang(Homework homework){        this.homework=homework;    }    //代理实现    @Override    public void doHomework() {        doStudy();        homework.doHomework();        System.out.println("XiaoWang helps with MathHomework");        doCheck();    }    // 额外方法     private void doCheck() {        System.out.println("XiaoWang is checking-----------------");    }    // 额外方法     private void doStudy() {        System.out.println("XiaoWang is studying---------------");    }}

小张:

public class XiaoZhang implements Homework{        // 持有Homework属性    private Homework homework;    // 通过构造函数初始化Homework    public XiaoZhang(Homework homework){        this.homework=homework;    }    //代理实现    @Override    public void doHomework() {        doStudy();        homework.doHomework();        System.out.println("XiaoZhang helps with EngHomework");        doCheck();    }    // 额外方法    private void doCheck() {        System.out.println("XiaoZhang is checking-----------------");    }    // 额外方法    private void doStudy() {        System.out.println("XiaoZhang is studying---------------");    }}

于是,小红可以放心地把作业交给小王和小张了:

 public static void main(String[] args) {        // 实例化一个目标对象        XiaoHong xiaoHong = new XiaoHong();        // 把目标对象通过构造函数传递给代理对象        XiaoZhang xiaoZhang =new XiaoZhang(xiaoHong);        XiaoWang xiaoWang =new XiaoWang(xiaoHong);        // 调用代理对象的方法        xiaoZhang.doHomework();        xiaoWang.doHomework();    }

输出:

XiaoZhang is studying---------------XiaoHong did homework casuallyXiaoZhang helps with EngHomeworkXiaoZhang is checking-----------------  XiaoWang is studying---------------XiaoHong did homework casuallyXiaoWang helps with MathHomeworkXiaoWang is checking-----------------

问题来了,如果老师又布置了一个Book接口和readBook方法,但是readBook前后的动作是一样的(都需要study和check),如何通过代理来实现呢?

一个方案是让小王和小张都实现Book接口和readBook方法,并持有新的Book对象;另一个方案是再找一个小赵实现Book接口和readBook方法。

这样两种方案实际上都能达到效果,但是如果接口和方法增多起来呢?如果让一个代理类实现一堆方法,并持有一堆不同的对象,这个类势必会变得臃肿不堪;如果每一个新的方法都创建一个新的代码类,引用不同的对象,又会造成代码的大量重复。因此,动态代理就出现了。

▐动态代理

前文所讲的静态代理之所以为“静态”,是因为每个接口的每个方法,我们都要显式地去实现、创建、调用,所有的操作都是写死的、是静态的。而动态代理的巧妙之处在于,可以在程序的运行期间,动态的生成不同的代理类,来完成相同的工作。也就是说,如果你想实现一个方法,在所有其他方法执行前后做一些额外的相同的动作,例如打印日志、记录方法执行时间等,你就需要动态代理了(是不是想到了什么?)。

事实上所有的动态代理思想都是一致的,而目前最常用的动态代理实现有两种:JDK原生实现和Cglib开源实现。

Spring在5.X之前默认的动态代理实现一直是JDK动态代理。但是从5.X开始,Spring就开始默认使用Cglib来作为动态代理实现。并且SpringBoot从2.X开始也转向了Cglib动态代理实现。

  • JDK实现动态代理

现在有一个牛X的机器人代理,可以帮所有人在完成老师布置的任何任务前后,进行学习和答案的核对,在JDK的动态代理实现中,他是这样编写的:

// 实现InvocationHandlerpublic class RobotProxy implements InvocationHandler {    // 持有一个Object类型的目标对象target    private Object target;      // 通过构造函数实例化目标对象target    public RobotProxy(Object target) {        this.target = target;    }      // 重写invoke方法    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        doStudy();        // 执行目标对象的方法        Object invoke = method.invoke(target, args);        doCheck();        return invoke;    }        // 额外动作    private void doStudy() {        System.out.println("Robot is studying------------");    }    // 额外动作    private void doCheck() {        System.out.println("Robot is checking------------");    }}

然后这样调用机器人代理:

public static void main(String[] args) {  // 实例化一个目标对象  XiaoHong xiaoHong = new XiaoHong();  // 传入实现的接口 new Class[]{Homework.class}  // 以及代理类 new RobotProxy(xiaoHong)  Homework homework = (Homework)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Homework.class}, new RobotProxy(xiaoHong));  homework.doHomework();}

输出:

Robot is studying------------XiaoHong did homework casuallyRobot is checking------------

可以看到,JDK实现动态代理必须要依赖接口,只有实现了接口的目标类才可以被代理,而Cglib动态代理就可以消除接口的限制。

  • Cglib实现动态代理

创建一个升级版的机器人RovotV2代理类:

// 实现MethodInterceptor方法(要引入cglib包)public class RobotV2Proxy implements MethodInterceptor {      // 重写intercept方法    @Override    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {        doStudy();        Object invoke = methodProxy.invokeSuper(o, objects);        doCheck();        return invoke;    }    // 额外动作    private void doStudy() {        System.out.println("RobotV2 is studying------------");    }    // 额外动作    private void doCheck() {        System.out.println("RobotV2 is checking------------");    }}

调用方式:

public static void main(String[] args) {    // 创建增强类    Enhancer enhancer = new Enhancer();    // 设置父类    enhancer.setSuperclass(XiaoHong.class);    // 设置回调    enhancer.setCallback(new RobotV2Proxy());    // 创建目标对象    XiaoHong xiaoHong = (XiaoHong)enhancer.create();    // 调用目标方法    xiaoHong.doHomework();}

输出:

RobotV2 is studying------------XiaoHong did homework casuallyRobotV2 is checking------------

Cglib动态代理相比于JDK代理实现有几个优势:

  1. 基于字节码,生成真实对象的子类。
  2. 运行效率高于JDK代理
  3. 不需要实现接口

可以看到,动态代理只需要一个代理类,就可以代理所有需要同一种处理(如上文所述的study()、check())的类和方法,这就是动态代理与静态代理最大的区别。

Spring事务管理

OK,了解到了代理模式的好处之后,就可以自然而然的想到Spring事务管理的基本原理了。无非是借助动态代理,做一些额外的操作:在真正的方法执行之前开启事务,在方法顺利执行完成之后提交事务,如果方法执行过程中发生异常,要执行回滚操作。

一般有两种方法使用Spring的事务管理,一种是利用注解,一种是手动编程。本文因为使用的是注解型的事务管理,因此只对注解型事务的使用和原理进行探究,以找到事务没有生效的原因。

▐注解型事务

  • 注解型事务使用

注解型事务的使用非常简单,只需要在需要事务管理的类或方法上加上@Transactional(rollbackFor = Exception.class),其中rollbackFor指定的是遇到什么情况下执行回滚。

当然这个注解还有传播级别、隔离级别等我们背过的八股文属性,就不一一展开了。

解锁Vscode:C/C++环境配置超详细指南 本文详细介绍如何在 VSCode 中配置 C/C++ 开发环境,帮助开发者快速搭建高效的编码调试环境。内容涵盖前期准备、软件下载安装、环境变量配置、工作区文件设置及测试运行全流程:首先需准备 VSCode 编辑器、MinGW-w64 编译器及 C/C++ 插件;接着完成工具下载与安装,配置系统环境变量以确保编译器可全局调用;然后通过创建.vscode工作区文件夹,配置核心文件,实现代码智能提示与调试功能;最后通过编写 Hello World 示例验证环境可用性,并附上常见问题排查方案。 阅读详情

相关推荐

MQTT在智能家居中的实战:用Android手机控制ESP8266设备(基于EMQX)

本文详细介绍了如何利用MQTT协议构建一个完整的智能家居控制系统,通过Android手机App远程操控ESP8266设备。文章提供了从EMQX服务器部署、ESP8266端Arduino固件开发到Android客户端搭建的完整实战指南,并深入探讨了系统联调、稳定性优化与安全加固等关键环节,为物联网开发者提供了一套可复用的解决方案。

ujm567890的博客 457

Spring事务实现的方式及底层原理

先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。当调用这个代理对象的方法时,如果有事务处理,则会先关闭事务的自动功能,然后执行方法的具体业务逻辑,如果业务逻辑没有异常,那么代理逻辑就会直接提交,如果出现任何异常,那么直接进行回滚操作。...

m0_52789121的博客 550

LangGraph实战:用Plan-and-Execute模式5步搭建智能问答机器人(附Tavily搜索集成)

本文详细介绍了如何利用LangGraph的Plan-and-Execute模式,通过规划、执行、动态调整三个核心阶段,构建一个能够处理复杂多步骤问题的智能问答机器人。文章提供了从环境配置、状态管理到核心节点(规划、执行、重新规划)实现的完整实战指南,并集成了Tavily搜索工具,展示了如何将智能任务规划应用于实际信息查询场景。

weixin_29258297的博客 342

Spring事务如何基于SpringAOP来实现事务代理?

通常我们要开启spring的事务我们需要加上@EnableTransactionManagement这个注解,那么肯定的这个注解的作用就是往容器里面去import了一个组件从而使得方法上面的@Transaction注解生效,而且spring事务的原理也是基于代理去实现事务回滚,事务隔离等功能的,那么既然是基于代理的原理,spring的事务与springAOP在实现这方面上有何异曲同工之处呢? 首先来看看@EnableTransactionManagement这个注解做了什么事 @Override .

我神级欧文的博客 1616

两轮差速小车循线控制原理分析

硬件资料设定:小车驱动来自于两个相同的电机,转向依靠两轮差速实现,小车前后左右安装超声波传感器,前后各一个,左右各两个; 功能目标:假设小车左侧有墙壁,通过超声波测距实现按指定距离沿墙行驶 参数设定:车轮半径r=3cm,车轮间距wd=10cm,车身长length=16cm,侧边超声波传感器前后各一个,假设一个在车头一个在车尾,间距=车身=length=16cm,小车线速度恒定v = 0.2m/s,距离墙d=10cm,假设超声波传感器以10Hz的频率采集距离。 在以上条件下,设定小车出发点,方向与墙平行

aibingjin的博客 1万+

【若依(ruoyi)】BootstrapTable列宽定制实战:突破width属性限制的两种方案

本文针对若依(RuoYi)框架中BootstrapTable组件列宽设置失效的常见问题,提供了两种实战解决方案。通过CSS样式覆盖法强制定义列宽,或利用formatter函数进行动态HTML包裹,有效突破width属性限制,实现精准的表格列宽定制。

weixin_29013129的博客 175

关于Spring的两种代理方式

代理方式: 1、jdk自带的动态代理。 2、Spring框架自己提供的CGLIB的方式。 什么是代理呢? 从字面意思来看,代理比较好理解,无非就是代为处理的意思。举个例子,你在上大学的时候,总是喜欢逃课。因此,你拜托你的同学帮你答到,而自己却窝在宿舍玩游戏... 你的这个同学恰好就充当了代理的作用,代替你去上课。 什么是动态代理呢? 就从上面代课的来讲,...

Tina优快云的博客 1356

elevation mapping算法3之使用D435i相机离线或在线订阅点云和tf关系生成高程图

本文主要学习使用D435i相机发出的点云作为高程图的点云输入,如何离线输入点云生成高程图,进一步学习如何在线订阅点云生成高程图。

重点记录机器人和自动驾驶相关领域的技术,尤其是计算机视觉,视觉SLAM等,不仅有前言文献或必备算法的学习,也会有实际应用的点滴经验 3490

Spring实现事务的原理

Spring是通过AOP实现事务的,我们都知道,Spring的AOP是基于代理实现的,代理分两种,一种是JDK,一种是CGlib,JDK动态代理要求代理类必须实现一个接口,因为具体实现的时候,需要根据接口类型动态构造代理类对象。而Spring就是在代理类调用invoke方法之前或之后加上一些公共的代码进行实现事务的管理的。 Spring对事务支持的本质也是基于数据库对事务的支持 一般事务操作步...

kris_lh123的博客 581

NVIDIA Isaac Sim 联合 VS Code 开发调试环境配置

在 Visual Studio Code (VS Code) 中打开 Isaac Sim 软件包主文件夹,即可打开该工作区。注意建议在学习教程和示例时使用 Visual Studio Code。另请参见有关 VS Code 工作区的详细信息,请参阅 Visual Studio Code (VS Code) 文档。

2506_90492529的博客 3106

OMAPL138使用UPP读写测试

UPP测试代码 #include "hw_types.h" // 宏命令 #include "hw_syscfg0_OMAPL138.h" // 系统配置模块寄存器 #include "soc_OMAPL138.h" // DSP C6748 外设寄存器 #include "psc.h" // 电源与睡眠控制宏及设备抽象层函数声明 #include "interrupt.h" // DSP C6748 中断相关应用程序接...

wangjie36的博客 1193

spring

Spring事务失效的原因有以下几种:非代理对象调用事务方法,异常类型不能被Spring事务感知,try-catch导致异常被捕获,多线程下事务失效。

little_sc的博客 349

解读(DivideMix)DIVIDEMIX: LEARNING WITH NOISY LABELS AS SEMI-SUPERVISED LEARNING

这是Salesforce在今年年初出的一篇关于半监督学习的文章被ICLR 2020收录,目前还保持在SOTA状态。 文章主要做了两点工作: • 提出了一个co-divide方法。 • 利用label co-refinement 和co-guessing 改善之前的谷歌提出的MixMatch方法 1.co-divide方法 大概思路:同时训练两个网络,让每个网络在样本损失分布上去拟合GMM模型,并利用GMM模型,将训练数据分为标签数据和未标签数据,co-divide 使前面分的标签与未标签数据分别在

so 5042

Spring设计模式,事务管理和代理模式的应用

被调用到的dao层语句,都拿着同一个对象,这个对象可以实现锁的功能。那么就要在dao层query和update语句中,增加一个Connection对象。threadLocal可以充当sql语句的锁对象因为threadlocal有一个线程们的公共区域,完全可以实现当公共区有一个connection的时候,线程们完全不需要再考虑在去造很多connection。

weixin_51704612的博客 502

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

浅入浅出的代理模式与Spring事务管理

前文所讲的静态代理之所以为“静态”,是因为每个接口的每个方法,我们都要显式地去实现、创建、调用,所有的操作都是写死的、是静态的。因此,动态代理就出现了。其中小王、小张两个小弟成绩优异,一个负责数学作业,一个负责英语作业,于是他们两个自告奋勇实现了Homework接口,在代理完成作业的基础上,还不断学习提高自己的能力,并且对作业答案进行了校验。可以看到,动态代理只需要一个代理类,就可以代理所有需要同一种处理(如上文所述的study()、check())的类和方法,这就是动态代理与静态代理最大的区别。

z1ztai的博客 558

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

浅入浅出代理模式与Spring事务管理

本文回顾了代理模式和Spring事务管理的原理。前言最近在开发业务代码的时候,犯了一个事务注解的错误:在同一个类的非事务方法中调用了另一个事务方法,导致事务没有生效,如下所示:public ConfirmOrderResultVO batchConfirmPurchaseOrders(Long taobaoUserId, List<String> bizOrd...

淘系技术 550

浅入浅出代理模式与 Spring 事务管理

前言最近在开发业务代码的时候,犯了一个事务注解的错误:在同一个类的非事务方法中调用了另一个事务方法,导致事务没有生效,如下所示: 其中confirmPurchaseOrder()是一个事务方法: 这样在直接调用batchConfirmPurchaseOrders()方法时,如果confirmPurchaseOrder()方法发生了异常,是不会回滚的。原理在于Spring的事务管理依靠的动态代理模式,当在同一个类中调用一个非事务方法,是不会生成代理对象的,自然也不会触发事务。借此机会回顾一下代理模式和

m0_67698950的博客 206

Spring 在什么时候开启代理模式创建bean的 需要主动开启吗 还是默认的

在Spring中,代理模式通常在AOP和声明式事务管理中自动启用。你不需要主动开启代理模式,除非你需要明确配置代理类型或启用特定功能。Spring默认使用JDK动态代理,除非需要使用CGLIB代理。通过合适的配置,你可以确保代理行为符合你的需求。

小雨点的博客 491

Spring第二天

Spring第二天代理模式代理模式的分类JDK动态代理cglib代理Spring AOP事务管理 代理模式 什么是代理模式: 一种设计模式,提供间接对目标对象进行访问的方式,通过代理对象访问目标对象,从而在在目标对象现有的功能能上,增加额外的功能补充,实现扩展目标对象的功能。 代理模式主要包含三个角色:主题角色,目标类角色,代理类角色 主题类角色:可以是接口,也可以是抽象类 目标类角色:也叫委托类,真实主题角色,业务逻辑的具体执行者 代理类角色:内部含有对真实目标对象的引用,负责对目标对象方法的调用,

我的博客 215

代理模式的实现

代理模式就像是生活中的中介或代理人,他们代表我们处理一些事务,让我们能够更方便、更高效地完成任务。想象一下,你想要买一套房子,但你没有时间或者不熟悉购房流程,这时候你可能会找一个房产中介来帮你处理这些事情。房产中介就是这个场景中的“代理”,而你则是“客户端”,房子和卖家则是“真实对象”。

Hardy Army的博客 1013

Spring Boot中的代理模式:揭秘AOP背后的核心魔法

你是否好奇Spring Boot如何实现无侵入式的日志、事务和安全控制?本文将揭开代理模式的神秘面纱,展示其如何成为Spring生态的"隐形引擎"!

专注分享原创技术干货。大厂资深架构师,多年技术架构与技术管理经验,多年面试官经验。一对一技术指导培训,带你从小白到入门到架构设计到技术管理。关注我,免费领取学习资料。一对一免费面试指导,快速拿offer。 1189

代理模式,Spring AOP介绍

1. 代理模式 package com.jt.service; public interface UserService { void addUser(); // void delUser(); } package com.jt.service; import org.springframework.stereotype.Service; @Service //被代理者 public class UserServiceimpl implements UserService {

weixin_43762083的博客 180

java设计模式学习之【代理模式】

这篇教程不仅提供了代理模式的理论基础,还通过具体的Java代码示例展示了如何实现和应用这种模式。简单理解,通俗易懂

qq_33129875的博客 1291

代理模式及其在spring与struts2中的体现

代理模式及其在spring与struts2中的体现

qiuleng2002的专栏 4519

spring的代理模式、AOP、spring-mybatis、声明式事务

Spring 代理模式 为什么要学习代理模式?因为这就是SpringAOP的底层!【SpringAOP和SpringMVC】 代理模式的分类: 静态代理 动态代理 静态代理 角色分析: 抽象角色:一般会使用接口或者抽象类来解决 真实角色:被代理的角色 代理角色:代理真实角色,代理后一般会做一些附属操作 客户:访问代理对象的人 代码步骤: 接口 真实角色 代理角色 客户端访问代理角色 Rent.java /** * @author zhuxianglong * @version

ZXLzhuzhu的博客 192

【沉浸式求职学习day54】【Spring补充】【代理模式】

spring补充and代理模式详解

贺函不是涵的博客 1204

深入源码解读Spring AOP设计思想:代理模式的应用场景

设计思想的核心:通过代理模式实现逻辑解耦,提升代码复用性和可维护性。技术选型建议优先使用JDK动态代理(目标对象实现接口时)。对于无接口的类,选择CGLIB动态代理。性能优化:减少不必要的切面,避免过度使用Around通知。源码调试技巧:通过的方法跟踪代理生成过程,结合Advisor和Pointcut的配置理解逻辑织入机制。通过深入源码分析,Spring AOP的设计充分体现了代理模式在解耦横切关注点中的价值,其灵活性和扩展性使其成为企业级应用开发的核心工具之一。

m0_73762612的博客 499
上一篇: RabbitMQ 搭建完之后怎么做?
下一篇: RocketMQ 的用法,你懂吗?
Java_ttcd
博客等级 码龄4年 198粉丝 190原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值