如何理解 Spring AOP 以及使用 AspectJ?

13、使用 Mathematica 撰写文本 本文详细介绍了如何使用 Mathematica 进行文本撰写与处理。内容涵盖文本输入、格式设置、结构化排版、超链接插入、翻译与拼写检查工具的使用,以及将笔记本导出为多种格式(如 PDF、HTML、LATEX 和 RTF)的方法。通过实例演示了创建专业文档的完整流程,包括样式设置、公式推导、标题编号、页眉页脚配置等操作。适合希望利用 Mathematica 编写学术论文、技术报告或教学资料的用户参考。 阅读详情

在 Spring 中 AOP 是一个非常非常重要的概念,那么什么是AOP呢?

AOP 即面向切面编程,也可以叫做面向方向编程,AOP不是一个新东西,它是OOP,即面向对象编程的一种补充,在当前已经成为一种成熟的编程方式。

1.为啥要使用 AOP


在学习AOP 之前,我们先了解下为啥我们要使用AOP?

那么,在传统的业务处理代码中,比如你要操作数据库,会进行事务的处理或者打印一些日志。虽然通过OOP 也可以实现,比如通过继承或组合的方式来达到代码的复用,但是如果实现某些功能,比如日志记录,相同的代码会分散到各个方法中,如果后面要想关闭某个功能或进行修改就必须要修改所有的方法,非常的不方便。

那么为了解决为了解决这个问题,AOP的思想随之产生。它采取了横向抽取机制。将分散在各个方法中的重复代码提取出来,然后在程序编译或运行时,再将这些提取出来的代码应用到需要执行的地方。这种采用横向提取机制的方式。是采用传统的AOP方式下无法办到的。因为传统的面向对象思想只能实现父子关系的纵向重用。

在AOP思想中,通过aspect(切面)可以分别在不同的类的方法中加入,例如事务日志权限和异常处理等功能。

使用切面这种横向方式。能够使开发人员在编写业务逻辑时专注于核心业务逻辑,而不用过度的关注与其他业务逻辑的实现。这样可以提高开发效率,同时还增强了代码的可维护性。

目前主流的AOP 框架有2个,分别是spring aop 和aspectJ,前者是纯Java 实现的,不需要专门的编译过程和类加载器,在运行期间可以通过代理的方式向目标内植入增强的代码。而AspectJ是一个基于Java语言的AOP框架。在Spring 2.0 开始,引入了对AspectJ 的支持,并提供了一个专门的编译器在编译时提供横向代码的植入。

2.相关术语


在了解AOP之前,首先要了解一下它的专业术语。这些术语包括Aspect、Joinpiont、Pointcut、Advice、Target Object、Proxy 和Weaving,对于这些专业术语具体的解释如下:

  • Aspect,切面在实际的应用中,切面通常是指封装的用于横向插入系统功能,比如事务日志的类,该类被spring容器识别为切面,需要在配置文件中通过\<bean\>来指定。
  • Joinpiont,连接点,在程序执行过程中的某个阶段点。它实际上是对象的一个操作,例如方法的调用或异常的抛出。在spring AOP中连接点就是指方法的调用。
  • Pointcut,切入点,切入点是指切面与程序流程的交叉点,即那些需要处理的连接点,通常在程序中切入点是指。类或者是方法名,比如说某个通知要应用到所有的以add开头的方法中。那么所有满足这一规则的方法都是切入点。
  • Adivce,通知增强处理,AOP 框架在特定的切入点执行增强处理,即在定义好的切入点处理所需要执行的程序代码,你可以理解其为切面类中的方法,它是切面的具体实现。
  • Target Object ,目标对象,是指所有通知的对象。也称为北增强对象。如果AOP框架采用的是动态的AOP实现,那么该对象就是一个被代理对象。
  • Proxy ,代理,将通知应用到目标对象之后被动态创建的对象。
  • Weaving, 织入,将切面代码插入目标对象上,从而生成代理对象的过程。

3.AspectJ 开发

使用AspectJ 实现AOP 的方式有

  • XML 声明
  • 注解

XML 声明

这种方式是通过XML文件来定义切面、切入点以及通知等,所有的切面、切入点和通知都必须定义在<aop:config>元素中,在<beans>元素中可以包含多个<aop:config>元素,一个 <aop:config> 中又可以包含子元素和属性,其子元素包含<aop:pointcut、<aop:advisor、<aop:aspect>,在配置时,需要严格按照顺序来定义,在<aop:aspect>下,同样包含属性和多个子元素,通过使用<aop:aspect>元素以及其子元素 可以在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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
    <!-- 1 目标类 -->
    <bean id="userDao" class="com.ssm.aspectj.UserDaoImpl" />
    <!-- 2 切面 -->
    <bean id="myAspect" class="com.ssm.aspectj.xml.MyAspect" />
    <!-- 3 aop编程 -->
    <aop:config>
        <!-- 1.配置切面 -->
        <aop:aspect id="aspect" ref="myAspect">
            <!-- 2.配置切入点 -->
            <aop:pointcut expression="execution(* com.ssm.aspectj.*.*(..))"    id="myPointCut" />
            <!-- 3.配置通知 -->
            <!-- 前置通知 -->
            <aop:before method="myBefore" pointcut-ref="myPointCut" />
            <!--后置通知-->
            <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="returnVal"/>
            <!--环绕通知 -->
            <aop:around method="myAround" pointcut-ref="myPointCut" />
            <!--异常通知 -->
            <aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e" />
            <!--最终通知 -->
            <aop:after method="myAfter" pointcut-ref="myPointCut" />
        </aop:aspect>
    </aop:config>
</beans>

但是 XML 的配置过于复杂,因为日常开发过程中,我们更倾向于使用注解的方式来进行AOP的开发

为了在应用中使用@AspectJ支持,Spring需要添加三个库:

  • aspectjweaver.jar
  • aspectjrt.jar
  • aopalliance.jar

因此,我们需要配置maven,如下所示

<dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.6.12</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.6.12</version>
    </dependency>

新建一个app.xml ,我们需要在Spring配置文件中做如下配置:

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd">
    <!-- 指定需要扫描的包,使注解生效 -->
    <context:component-scan base-package="com.ssm.aspectj" />
    <!-- 启动基于注解的声明式AspectJ支持 -->
    <aop:aspectj-autoproxy />
</beans>

然后,我们创建一个UserDao 的接口,如下所示

package com.ssm.aspectj;

public interface UserDao {
    // add user
    public void addUser();

    //delete user
    public void delUser();
}

将 UserDao 实例化,并加上注解@Repository("userDao"),方便后续进行调用具体的方法

package com.ssm.aspectj;

import org.springframework.stereotype.Repository;

@Repository("userDao")
public class UserDaoImpl implements UserDao{
    @Override
    public void addUser() {
        System.out.println("add user");
    }

    @Override
    public void delUser() {
        System.out.println("delete user");

    }
}

定义一个切面类,在该类中编写各种通知

package com.ssm.aspectj.xml;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
 * 切面类,在此类中编写通知
 */
@Aspect
@Component
public class MyAspect {
    //定义切入点表达式
    @Pointcut("execution(* com.ssm.aspectj.*.*(..))")
    //使用一个返回值为void、方法体为空的方法来命名切入点
    private void myPointCut(){}
    //前置通知
    @Before("myPointCut()")
    public void myBefore(JoinPoint joinPoint){
        System.out.print("前置通知:模拟执行权限检查..,");
        System.out.print("目标类是:"+joinPoint.getTarget());
        System.out.println(",被植入增强处理的目标方法为:"+joinPoint.getSignature().getName());
    }
    //后置通知
    @AfterReturning(value="myPointCut()")
    public void myAfterReturning(JoinPoint joinPoint) {
        System.out.print("后置通知:模拟记录日志..,");
        System.out.println("被植入增强处理的目标方法为:" + joinPoint.getSignature().getName());
    }
    /**
     * 环绕通知
     * ProceedingJoinPoint是JoinPoint的子接口,表示可执行目标方法
     * 1.必须是Object类型的返回值
     * 2.必须接收一个参数,类型为ProceedingJoinPoint
     * 3.必须throws Throwable
     */
    @Around("myPointCut()")
    public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
        //开始
        System.out.println("环绕开始:执行目标方法之前,模拟开启事务..,");
        //执行当前目标方法
        Object obj=proceedingJoinPoint.proceed();
        //结束
        System.out.println("环绕结束:执行目标方法之后,模拟关闭事务..,");
        return obj;
    }
    //异常通知
    @AfterThrowing(value="myPointCut()",throwing="e")
    public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
        System.out.println("异常通知:出错了"+e.getMessage());
    }
    //最终通知
    @After("myPointCut()")
    public void myAfter(){
        System.out.println("最终通知:模拟方法结束后释放资源..");
    }
}

srping 的通知包括五种通知工作:

在上述代码中,其中 @Pointcut("execution(* com.ssm.aspectj.*.*(..))") 表示定义切入点,使用注解@Pointcut 后面的execution(* com.ssm.aspectj.*.*(..)) 表示匹配所有目标类的所有方法。第一个*代表返回类型,第二个*代表方法名,而..代表任意入参的方法,他的格式如下:

语法:execution(修饰符 返回值 包.类.方法(参数) throws 异常)

最后编写个测试类从
ClassPathXmlApplicationContext 读取xml 文件,然后调用getBean 获取userDao并执行addUser方法。

package com.ssm.aspectj;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestXmlAspectJ {
    @Test
    public void testAnnotation() {
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("app.xml");
        //从容器中获得内容
        UserDao userDao= (UserDao) applicationContext.getBean("userDao");
        //执行方法
        userDao.addUser();
    }
}

结果如下:

对了,在这里说一下,我目前是在职Java开发,如果你现在正在学习Java,了解Java,渴望成为一名合格的Java开发工程师,在入门学习Java的过程当中缺乏基础入门的视频教程,可以关注并私信我:01。获取。我这里有最新的Java基础全套视频教程。

【数据集8】全球人口数据WorldPop详解 全球人口数据WorldPop详解 阅读详情

相关推荐

EWF写保护功能详解:从安装到实战操作指南

本文详细介绍了EWF写保护功能的安装与实战操作指南。EWF(Enhanced Write Filter)通过重定向写入操作保护硬盘分区,特别适合需要长期稳定运行的系统场景。文章涵盖从安装准备、图形界面操作到命令行高级管理的全流程,并提供了常见问题的解决方案,帮助用户轻松掌握这一实用工具。

weixin_28710999的博客 448

Spring学习(7)—— AOP(使用注解方式通过AspectJ实现AOP)

利用AOP可以对业务逻辑的各个部分进行隔离,从而使得各部分之间的耦合度降低。 Spring框架一般都是基于AspectJ实现AOP操作。 1. AOP中的术语 (1)连接点:类中可以被增强的方法; (2)切入点:类中实际被增强的方法; (3)通知(增强):给类中某个方法编写的实际增强的逻辑部分;通知有多种类型:①前置通知、②后置通知、③环绕通知、④异常通知、⑤最终通知 (4)切面:把通知应用到切入点的过程 2. 切入点表达式 切入点表达式的作用:指明对哪个类里的哪个方法进行增强 语法...

Archer__13的博客 1830

0009 用VisualStudio设计Max工具

这次分享个独家专利^)^:在Visual Studio中设计3dsMax脚本工具界面。 某次做原型设计时,需求改来改去,实在懒得搞GUI;虽然也尝试在Axure RP里画原型,但还是Visual Studio更顺手,也更容易测试一些交互,就直接在VS里做了。后来突发奇想,想实验一把能否直接用到Max里去,结果没想到成功了,效果还挺好。发现了新大陆,记录一下。   开始: 在VS里新建W...

whwst的专栏 770

springboot项目中引入Aspectj并使用

环境 springboot:2.4.4 aspectjweaver: 1.8.7 前言 今天调试接口时,遇到的aop拦截,做权限校验,但是有个参数总是没有传,又因为以前这块代码逻辑有问题,总报null指针。所以回家后,研究了aspectj包。 这里网上有一句这样的概括: spring-aop:AOP核心功能,例如代理工厂等等 aspectjweaver:简单理解,支持切入点表达式等等 aspectjrt:简单理解,支持aop相关注解等等 但是aspectjweaver是包含aspectjrt的,所以上面那句

山鬼谣的专栏 1万+

SAP 货币类型和公司代码的货币设置

货币类型分为公司代码和集团货币,一般FI 10类型和集团货币 30,事务代码是8KEM; 设置货币类型的事务代码是OB22 在S/4 1809版本里编辑功能统合到事务代码FINSC_LEDGER 中了,这里集中了分类账和公司代码的设置; 设置多账簿的币种(会出现在BSEG和FAGLFLEXA表中) 汇率维护在TCURR表中,可通过BAPI_EXCHANGERATE_GETDETAIL函数获取。 CO货币的事务代码是成本控制范围货币:OKKP ,一般设置为货币码20和30; 另外, SCC4设置集团货币,

RichardYang2020的博客 1万+

HTML入门(详细教程),前端入门从这里开始

HTML基础教程,网页框架搭建,表单制作,了解HTML标签的基本用法,每个标签具备哪些属性。

wandertp的博客 1286

android- AspectJ 的接入使用

AspectJ 作为aop的著名工具,现在就让我们进行使用他,不逼逼。 接入有两种方式,一种是组件化式接入,一种是非组件化接入。组件化接入,就是当我们的项目是组件化开发时,有多个moudle。 非组件化接入: 第一步:在项目gradle中添加aspectJ的依赖 classpath 'org.aspectj:aspectjtools:1.8.6' 第二步:在app gradle中...

BunnyCoffer的博客 2962

AIGC实战——基于Transformer实现音乐生成

Transformer 是最流行的音乐生成技术之一,因为音乐可以视为一个序列预测问题,Transformer 模型将音符视为一个个符号的序列(类似于句子中的单词),从而用于生成音乐。Transformer 模型基于先前音符预测下一个音符,生成音乐作品。在本节中,将学习如何处理音乐数据,并应用 Transformer 生成与给定训练集风格相似的音乐。

盼小辉丶的博客 1万+

Spring AOP与AspectJ的对比及应用

AOP,即面向切面编程是很常用的技术,特别是在Java Web开发中。而最流行的AOP框架分别是Spring AOP和AspectJ。AOP场景应用特别多,还是需要掌握的。代码请看GitHub:标签:Java。

woaimx_1314的博客 1197

GEE:面对对象土地利用分类(结合SNIC、GLCM 和机器学习算法)

本文将介绍在Google Earth Engine中结合SNIC、GLCM和机器学习算法的的土地利用/土地覆盖(LULC)分类方法。结果如下图所示,

养乐多的博客 5619

2025年全国青少年信息素养大赛初赛真题(算法创意实践挑战赛C++初中组:文末附答案)

2025年全国青少年信息素养大赛初赛真题(算法创意实践挑战赛C++初中组:文末附答案)

王老师青少年编程 3398

ssm 实现日志 用aspectj_如何理解 Spring AOP 以及使用 AspectJ?

作者 | 阿文责编 | 屠敏出品 | 优快云(ID:优快云news)在 Spring 中 AOP 是一个非常非常重要的概念,那么什么是AOP呢?AOP 即面向切面编程,也可以叫做面向方向编程,AOP不是一个新东西,它是OOP,即面向对象编程的一种补充,在当前已经成为一种成熟的编程方式。为啥要使用 AOP在学习AOP 之前,我们先了解下为啥我们要使用AOP?那么,在传统的业务处理代码中,比如你要...

weixin_34567079的博客 161

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Spring Aop(二)——基于Aspectj注解的Aop简单实现

2 基于Aspectj注解的Spring Aop简单实现Spring Aop是基于Aop框架Aspectj实现的,它不是完完全全的对Aspectj框架进行扩展和改造,而是利用Aspectj里面的一些功能来实现自己的Aop框架,其中就包括对Aspectj提供的注解的解析。之前已经提过Spring Aop和Aspectj实现的Aop之间的差别,这里就不再赘述。本文主要描述的是如何利用Aspectj提供

Elim的博客 3636

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

不依赖Spring使用AspectJ达到AOP面向切面编程

网上大多数介绍AspectJ的文章都是和Spring容器混用的,但有时我们想自己写框架就需要抛开Spring造轮子,类似使用原生AspectJ达到面向切面编程。步骤很简单,只需要两步。 1.导入依赖 <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjwea...

weixin_33976072的博客 2906

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Spring---AOP与Annotation

Spring---AOP面向切面编程AOP相关术语AOP通知类型AOP Schema通知类环绕通知(Around Advice)AspectJ中的Execution表达式 AOP相关术语 切面(Aspect):一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是J2EE应用中一个关于横切关 注点的很好的例子。在Spring AOP中,切面可以使用基于模式)或者基于@Aspect注解的方式来实现。 连接点(Joinpoint):在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时

weixin_44889526的博客 955

java spring aop实例_Spring AOP+AspectJ注解实例

常见AspectJ的注解:@Before–方法执行前运行@After–运行在方法返回结果后@AfterReturning–运行在方法返回一个结果后,在拦截器返回结果。@AfterThrowing–运行方法在抛出异常后,@Around–围绕方法执行运行,结合以上这三个通知。注意SpringAOP 中没有 AspectJ 支持,请阅读内置 SpringAOP 例子。1. 目录...

weixin_39669761的博客 226

这题年年考:Spring AOP 与 AspectJ 的区别,你真的答对了吗?

在回答区别之前,必须搞清楚AOP 到底是什么,为什么需要它?把跟业务无关但又很重要的逻辑(比如日志、事务、安全校验)统一抽取出来,集中处理。我们以前做法:逻辑和日志耦合在一起,不好维护。引入 AOP 后可以变成:切面代码专门记录执行时间、打印日志等。这就是 AOP 的价值!AOP 是一把双刃剑。用得好,它可以让你的业务代码干净清晰、关注分离;用不好,容易造成:隐性逻辑,排查困难性能问题(代理链太长)忽略内部调用问题所以建议你:用在日志、异常监控、权限校验、限流等“横切关注点”

cnzzs的博客 825

Spring学习笔记:Spring AOP入门以及基于Spring AOP配置的深入学习与使用

AOP面向切面编程,通过提供一种程序结构的思考方式来补充面向对象的编程。(面向对象编程 OOP)首先代码是面向业务的,业务也有轻重缓急,也就是有的业务是核心业务,有的业务是非核心业务。比如说消息系统,接受和发送消息是核心业务,对于日志,异常报错处理,以及具体的校验就是非核心业务。这些业务是在一起的,这样让系统运作起来,只有核心业务可能系统最起码的安全性和稳定性都提供不了。但是没有核心业务,这些非核心业务也没有什么必要。

FeiChangWuRao的博客 1158

Spring——AOP面向切面编程&SpringAOP与AspectJ比较

​最近跟着源码研究了下Spring使用三级缓存处理循环依赖的原理,里面涉及到Spring AOP的概念;本篇介绍AOP相关的知识点,AOP下的概念名词比较多,尽量使用通俗的概念来逐个解释,内容包括:对AOP(面向切面编程)的理解、AOP下的名词概念、Spring AOP与AspectJ的比较等;这部分知识对于学习Spring框架或者面试,都非常重要,需要掌握; ​...

娜娜米的博客 1285

aop aspectj autoproxy / 的作用

aop aspectj autoproxy / 的作用

hgffhh的博客 1616

spring-AOP框架(基于AspectJ注解配置AOP)

基于AspectJ注解配置AOP 1、加入jar包: 要在Spring应用中使用AspectJ注解,必须在classpath下包含AspectJ类库:aopalliance.jar、aspectj.weaver.jar、spring-aspects.jar和spring-aop.jar。 2、在配置文件中加入aop的命名空间:   1)将aop Schema添加到<bean...

deni2000的博客 236

Spring学习(十八)----- Spring AOP+AspectJ注解实例

Spring学习(十八)----- Spring AOP+AspectJ注解实例 我们将向你展示如何将AspectJ注解集成到SpringAOP框架。在这个SpringAOP+AspectJ示例中,让您轻松实现拦截方法。 常见AspectJ的注解: @Before–方法执行前运行 @After–运行在方法返回结果后 @AfterReturning–运行在方法返回一个结...

go_pkqL00的博客 272

【Spring】(6)AOP面向切面编程:使用AspectJ 实现 AOP(干货收藏!)

两个月前跟着b站动力节点王鹤老师的Spring框架教程视频学习完了Spring框架,在学习过程中我将视频中涉及的代码都一行一行手敲了一遍,并且把Spring入门相关的资料整理了一下,在这里记录一下我在Spring框架学习过程中的笔记和一些心得,希望能帮助到想要通过文字教程入门Spring这一框架的小伙伴哦! 视频地址:2020最新Spring框架教程【IDEA版】-Spring框架从入门到精通 文章目录AspectJ 实现 AOP1. AspectJ 的通知类型2. AspectJ 的切入点表达式3. .

aaa_hao的博客 1244
上一篇: 程序员吐槽朋友放弃阿里去当公务员,年纪轻轻就选择养老,好难受
下一篇: 华为程序员月薪27万,什么级别?吃瓜群众:我也是月入上万的
Javaesandyou
博客等级 码龄5年 742粉丝 563原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值