Spring Bean的生命周期

Spring Bean生命周期源码详解 之后child需要根据BeanDefinition来生成Bean对象之前,需要进行BeanDefinition的合并,得到完整的child的BeanDefinition,也就是RootBeanDefinition。我们知道BeanPostProcessor接口的作用是在bean初始化前和初始化后执行一些方法,Spring提供了该接口的子接口来进行实例化前后执行的一些方法。可以在这个步骤中,对Bean最终进行处理,Spring中的AOP就是基于初始化后实现的,初始化后返回的对象才是最终的Bean对象。 阅读详情

今天来看下spring中bean的生命周期问题:主要是对以下几篇博文的整理:在此感谢下列几位博主:
1:Spring Bean生命周期本博文给出了下面第一个生命周期执行流程图;并且其中的示例很不错;
2:Spring Bean 初始化过程本博文给出了BeanFactory的简单继承结构;
3:Spring面试题:Spring Bean 生命周期
4:从源码看Spring Bean的生命周期本博文很好的介绍了springbean的生命周期尤其是对AbstractAutowireCapableBeanFactory类初始化bean的过程和AbstractApplicationContext的refresh方法;以及相应的BeanPostProcess合适注入问题给出了展示;
5:BeanFactory和ApplicationContext的区别


首先我们来看下Spring Framework4.3.9 的Document中是如何说的;在 BeanFactory接口中有这样的描述:
这个根接口 Interface BeanFactory主要是为了访问Spring的bean 容器;它是 bean 容器一个最基本的客户端视图;该接口有持有许多bean定义的对象实现,每个都通过 string name进行唯一的标识;根据这些 bean 的定义中 scope 的范围,在spring 2.0 scope只有 singleton prototype 两个类型,在2.0以后为了更好的支持web应用增加了 request, session,global session,来确定bean的范围;
注意到,通常依赖于通过使用setter或者构造器的依赖注入(push 配置)要比传统的“pull”配置例如beanfactory查找要好的多;Spring的依赖注入功能是通过这个BeanFactory接口及其子接口实现的。
BeanFactory的实现应该尽可能支持标准的Bean生命周期接口,完整的初始化方法和它们的标准顺序如下:

  1. BeanNameAware ==> setBeanName
  2. BeanClassLoaderAware ==> setBeanClassLoade
  3. BeanFactoryAware ==> setBeanFactory
  4. EnvironmentAware ==> setEnvironment
  5. EmbeddedValueResolverAware ==> setEmbeddedValueResolver
  6. ResourceLoaderAware ==> setResourceLoader (only applicable when running in an application context)
  7. ApplicationEventPublisherAware ==> setApplicationEventPublisher (only applicable when running in an application context)
  8. MessageSourceAware ==> setMessageSource (only applicable when running in an application context)
  9. ApplicationContextAware ==> setApplicationContext (only applicable when running in an application context)
  10. ServletContextAware ==> setServletContext (only applicable when running in a web application context)
  11. BeanPostProcessors ==> postProcessBeforeInitialization
  12. InitializingBean ==> afterPropertiesSet
  13. a custom init-method definition
  14. BeanPostProcessors ==>postProcessAfterInitialization

    在关闭bean工厂时,下列生命周期方法适用:

  15. DestructionAwareBeanPostProcessors ==> postProcessBeforeDestruction

  16. DisposableBean ==> destroy
  17. a custom destroy-method definition

Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:

1、Bean自身的方法:这个包括了Bean本身调用的方法和通过配置文件中的init-method和destroy-method指定的方法

<bean id="demoBean" class="com.bean.DemoBean" init-method="initMethod">
  .......
 </bean>
 <bean id="demoBean" class="com.bean.DemoBean" destory-method="destroyMethod">
  .......
</bean>

2、Bean级生命周期接口方法:这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法;

3、容器级生命周期接口方法:这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。

4、工厂后处理器接口方法:这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。


执行流程图:来源于网上

这里写图片描述

这里写图片描述


了解几个关键的类:

1.AbstractApplicationContext

容器AbstractApplicationContext中有个方法是refresh()这个里面包含了整个Bean的初始化流程实现过程

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                // Destroy already created singletons to avoid dangling resources.
                beanFactory.destroySingletons();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }
        }
    }

这里写图片描述

2. AbstractAutowireCapableBeanFactory

AbstractBeanFactory 和 AbstractAutowireCapableBeanFactory 是两个模 板抽象工厂类。AbstractBeanFactory 提供了 bean 工厂的抽象基类,同时提供 了 ConfigurableBeanFactory 的完整实现。AbstractAutowireCapableBeanFactory 是继承 了 AbstractBeanFactory 的抽象工厂,里面提供了 bean 创建的支持,包括 bean 的创建、依赖注入、检查等等功能,是一个 核心的 bean 工厂基类。
在AbstractAutowireCapableBeanFactory 的 initializeBean方法中:

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, bean);
        }
    //关键方法1 invokeAwareMethods(beanName,bean);
        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }
    //关键方法2 :applyBeanPostProcessorsBeforeInitialization
        try {
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
    //关键方法3:invokeInitMethods(beanName, wrappedBean, mbd)
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }

        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        //关键方法4:applyBeanPostProcessorsAfterInitialization
        return wrappedBean;
    }

上面四个方法都干了什么工作:
1.可以看到先调用invokeAwareMethods,在这个方法中依次调用了setBeanName –> setBeanClassLoader –> setBeanFactory 三个方法,用于在需要的时候设置对应值;
2.然后调用applyBeanPostProcessorsBeforeInitialization,依次执行所有BeanPostProcess 的postProcessBeforeInitialization方法。注意:这里的processors除了包括我们自定义的processors,还包括spring自身添加的processors.如:ApplicationContextAwareProcessor; ServletContextAwareProcessor;
3.接着调用invokeInitMethods方法:也即处理InitializingBean接口中的afterPropertiesSet方法,然后调用用户自定义的初始化方法,也即通过init-method配置的方法。InitializingBean的afterPropertiesSet需要相应类实现该接口,会使对应类与Spring耦合,而通过init-method则不会.
4.最后调用applyBeanPostProcessorsAfterInitialization处理bean post processor的postProcessAfterInitialization切入点.

具体源码阅读:
1.可以看到先调用invokeAwareMethods,具体如下:
可以看到依次调用了setBeanName –> setBeanClassLoader –> setBeanFactory 三个方法,用于在需要的时候设置对应值

private void invokeAwareMethods(final String beanName, final Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware) bean).setBeanName(beanName);
            }
            if (bean instanceof BeanClassLoaderAware) {
                ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
            }
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
            }
        }
    }

2.然后调用applyBeanPostProcessorsBeforeInitialization,依次执行所有BeanPostProcessors 的postProcessBeforeInitialization方法。
注释:由于processors是在一个ArrayList中维护,因此会按照顺序来执行,也就是说ApplicationContextProcessor和ServletContextAwareProcessor会先于其他spring后面添加或者我们自定义的处理器

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        //从list中循环遍历执行beforeInitialization方法;
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            result = beanProcessor.postProcessBeforeInitialization(result, beanName);
            if (result == null) {
                return result;
            }
        }
        return result;
    }

注意:这里的processors除了包括我们自定义的processors,还包括spring自身添加的processors.
这里罗列几个和spring bean生命周期相关的processor和其添加时机.
ApplicationContextAwareProcessor:主要用于处理ApplicationContextAware接口的setApplicationContext方法,具体参见ApplicationContextAwareProcessor的postProcessBeforeInitialization方法,在该方法中,调用了ApplicationContextAwareProcessor 的 invokeAwareInterfaces方法,具体代码如下:

    private void invokeAwareInterfaces(Object bean) {  
      if (bean instanceof Aware) {  
        if (bean instanceof EnvironmentAware) {  
          ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());  
        }  
        if (bean instanceof EmbeddedValueResolverAware) {  
          ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(  
              new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));  
        }  
        if (bean instanceof ResourceLoaderAware) {  
          ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);  
        }  
        if (bean instanceof ApplicationEventPublisherAware) {  
          ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);  
        }  
        if (bean instanceof MessageSourceAware) {  
          ((MessageSourceAware) bean).setMessageSource(this.applicationContext);  
        }  
        if (bean instanceof ApplicationContextAware) {  
          ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);  
        }  
      }  
    }  

可以看到这里会依次处理EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware , ApplicationEventPublisherAware , MessageSourceAware , ApplicationContextAware.

另一个:ServletContextAwareProcessor:主要用于处理Servlet 上下文相关的信息感知.其postProcessBeforeInitialization方法具体如下:

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {  
      if (getServletContext() != null && bean instanceof ServletContextAware) {  
        ((ServletContextAware) bean).setServletContext(getServletContext());  
      }  
      if (getServletConfig() != null && bean instanceof ServletConfigAware) {  
        ((ServletConfigAware) bean).setServletConfig(getServletConfig());  
      }  
      return bean;  
    }  
3. ApplicationContext VS BeanFactory

这里写图片描述

ApplicationContext接口,它由BeanFactory接口派生而来,因而提供BeanFactory所有的功能。其次,原始的BeanFactory无法支持spring的许多插件,如AOP功能、Web应用等。所以ApplicationContext对BeanFactory做了如下扩展:
1.利用MessageSource进行国际化 ;
2.强大的事件机制(Event)
3.ResourceLoader(资源加载器)接口进行底层资源的访问
4.BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,这样,我们就不能发现一些存在的Spring的配置问题。而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误。
5.BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册

Fofa API高阶玩法:用Python批量获取漏洞资产(含OA系统扫描实战) 本文详细介绍了如何利用Python结合Fofa API实现自动化漏洞资产收集的高阶实战技巧。通过构建健壮的客户端、设计精准查询语法、实现多线程批量采集,并以OA系统漏洞扫描为例,演示了从资产发现、过滤验证到报告生成的全流程,旨在提升安全运维与应急响应的效率。 阅读详情

相关推荐

金蝶K3系统物料主数据后台表对应字段一览

我们说到物料表,一般是指t_icitem,但正确的说t_icitem并不是一张有,而是一张视图,不过我们对于数据库物料表中的大部分操作,都是通过此视图来完成。比如经常通过此视图,来成批修改数量,单价精度,是否启用批次等一些字段,有的时候,对于账套已经启用,并且已经有业务发生的物料,有一些关键属性也需要通过修改物料表t_icitem来进行。 当然修改的时候,需要考虑一些前提条件的。 比如说我有一个客户新建的账套,在月底结账时发现,要改一种成本核算方法,启用时用的是加权平法,现在想改成移动平均法,这样的情况,

hzfw2008的博客 1万+

SpringBean生成流程详解 —— 由浅入深(附超精细流程图)

(全网最细,原创)硬核解释SpringBean生成的流程,同时分析网上一些常见错误结论

战斧的博客 1万+

python 携程登陆_Python 学习练习之用户登录接口

目的:用python实现简单用户注册,登陆,加黑功能,放个流程图吧。以下内容仅为练习 执行流程:[root@zabbix login]# python user_login.pyusername:tompassword:123456Are you want to register ? [y/n]yRegister successful,Please relogin ![root@zabbix lo...

weixin_28679635的博客 515

spring的核心技术---bean的生命周期加案例分析详细易懂

将Bean解析成Spring内部的BeanDefinition结构;扩展接口。

YZZdear的博客 1109

基于OpenCV实现暗通道先验去雾算法及改进,效果惊人

深度技术文,前方高能

公号:一条coding 2万+

【AI智能体】基于Coze 制作高质量PPT实战操作详解

基于Coze 制作高质量PPT实战操作详解

congge 6099

11 张流程图帮你搞定 Spring Bean 生命周期 (核心)

在网上已经有跟多Bean的生命周期的博客,但是很多都是基于比较老的版本了,最近把整个流程化成了一个流程图。待会儿使用流程图,说明以及代码的形式来说明整个声明周期的流程。注意因为代码比较多,这里的流程图只画出了大概的流程,具体的可以深入代码。 一、获取Bean 第一阶段获取Bean 这里的流程图的入口在 AbstractBeanFactory类的 doGetBean方法,这里可以配合前面的 getBean方法分析文章进行阅读。主要流程就是 1、先处理Bean 的名称,因为如果以“&”开头的

李虹柏的博客 970

海思SD3403/SS928V100开发(6)单路GMSL-MIPI-YUV相机视频输入调试

硬件连接:森云GMSL相机 -> GMSL 解串器 -> SD3403 MIPI0暂时先进行单路视频输入通路调试。

jzwjzw19900922的博客 1930

Spring容器初始化过程

一、Spring 容器高层视图 Spring 启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相应的Bean配置注册表,然后根据这张注册表实例化Bean,装配号Bean之间的依赖关系,为上层应用提供准备就绪的运行环境。 二、内部工作机制 该图描述了Spring容器从加载配置文件到创建出一个完整Bean的作业流程: 1、ResourceLoader从存储介质中...

weixin_33937778的博客 2408

通俗易懂的Harris 角点检测

点击上方“3D视觉工坊”,选择“星标”干货第一时间送达Harris 角点检测 认为特征点具有局部差异性。如何描述“特征点具有局部差异性”:以每一个点为中心,取一个窗口,窗口大小为5*5...

3D视觉工坊 1472

Dify 本地插件安装失败?别慌,这篇教程手把手教你解决(解决 the plugin you want to install has a bad signature 报错的问题)

🤯dify安装本地插件报错 PluginDaemonBadRequestError: plugin verification has been enabled, and the plugin you want to install has a bad signature。的解决方案!

XiaoqiangClub的博客 3984

【Spring】Spring的Bean的生命周期

在Java中,Bean是一个重要的概念,它代表了应用程序中的一个对象。在开发中,我们经常使用Bean来管理对象的生命周期。本文将介绍Bean的生命周期,并详细讲解如何在Spring框架中管理Bean的生命周期。Spring其实就是一个管理Bean对象的工厂。它负责对象的创建,对象的销毁等。所谓的生命周期就是:对象从创建开始到最终销毁的整个过程。Spring为每个Bean定义了若干个回调方法,使得开发人员可以在某个特定的时间点对Bean进行特定的操作。

qq_46096136的博客 1万+

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Spring 中Bean 的生命周期

Spring 中Bean 的生命周期 文章目录Spring 中Bean 的生命周期前言一、Bean 的完整生命周期二、Bean 的生命周期验证 前言 ​ 这其实是一道面试题,是我在面试百度的时候被问到的,当时没有答出来(因为自己真的很菜),后来在网上寻找答案,看到也是一头雾水,直到看到了《Spring in action》这本书,书上有对Bean声明周期的大致解释,但是没有代码分析,所以就自己上...

程序员cxuan的个人主页 7678

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Spring bean生命周期详解

Spring Bean的完整生命周期从创建Spring容器开始,直到最终Spring容器销毁Bean,这其中包含了一系列关键点。 Spring bean生命周期 四个阶段 Bean的实例化阶段 Bean的设置属性阶段 Bean的 初始化阶段 Bean的销毁阶段 Spring bean生命周期13个环节 阶段1:Bean元信息配置阶段 阶段2:Bean元信息解析阶段 阶段3:将Bean注册到容器中 阶段4:BeanDefinition合并阶段 阶段5:Bean Class加载阶段 阶段6:Bean实例化阶

weixin_44145478的博客 1万+

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Spring中bean的生命周期

Spring中的bean的生命周期主要包含四个阶段:实例化Bean --> Bean属性填充 --> 初始化Bean -->销毁Bean 首先是实例化Bean,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚末初始化的依赖时,容器就会调用doCreateBean()方法进行实例化,实际上就是通过反射的方式创建出一个bean对象 Bean实例创建出来后,接着就是给这个Bean对象进行属性填充,也就是注入这个Bean依赖的其它bean对象 属性填充完成后,进行...

kykangyuky的博客 3万+

Spring Bean 的生命周期

目录 一、BeanFactory实例化Bean相关接口 二、BeanFactory的bean生命周期相关代码 三、关于BeanFactory的Bean生命周期接口的总结 四、ApplicationContext的Bean生命周期 五、ApplicationContext的Bean生命周期代码演示 六、总结 Spring的生命周期是指实例化Bean时所经历的一系列阶段,即通过getBe...

实践是最好的方法 3万+

Spring——Bean 的生命周期

目录一、Bean 的生命周期二、代码演示三、主要步骤简述 一、Bean 的生命周期   对于普通的 Java 对象,new 的时候会去创建对象,而当它没有任何引用的时候则被垃圾回收机制回收。相较于前者,由Spring IoC 容器托管的对象,它们的生命周期完全由容器控制。Spring 中每个 Bean 的生命周期如下: 对于 ApplicationContext 容器,当容器启动结束后,实例化所有的 Bean。 设置对象属性,即依赖注入,动态将依赖关系注入到对象中。 紧接着,Spring 会检测该对象

浪漫不死的博客 1万+

spring中bean的生命周期

1、spring中bean的生命周期 (1)概念 在spring框架中,所有的bean对象都有生命周期,就是指bean的创建、初始化、服务、销毁的一个过程。 (2)bean的生命周期 bean的定义 在spring中通常是通过配置文档的方式来定义Bean的,在一个配置文件中可以定义多个Bean bean的初始化 默认在IOC容器加载的时候实例化对象(ApplicationContext是,Beanfactory只有在调用getBean的时候才进行实例化):生命周期(初始化、销毁方法、BeanPos

to_real的博客 4052

Spring中Bean的生命周期

Bean生命周期: Bean的创建-----初始化-----销毁的过程 1、@Bean注解指定初始化和销毁方法 @Bean(initMethod="initMethod" ,destoryMethod="destoryMethod") @Scope("singleton") @Bean(name = "person", initMethod = "initM" , destroyMeth...

zhoushimiao1990的博客 5830

Spring Bean生命周期详解

文章目录Spring bean生命周期13个环节阶段1:Bean元信息配置阶段阶段2:Bean元信息解析阶段阶段3:Spring Bean注册阶段 Spring bean生命周期13个环节 阶段1:Bean元信息配置阶段 阶段2:Bean元信息解析阶段 阶段3:将Bean注册到容器中 阶段4:BeanDefinition合并阶段 阶段5:Bean Class加载阶段 阶段6:Bean实例化阶段(...

永无止境 6607

Spring Bean生命周期总结

1、简要说明 1)本文基于spring5.1.7版本,采用ApplicationContext获取bean对象。 2)BeanFactory和ApplicationContext对于bean后置处理器还有所不同,需要注意,ApplicationContext会自动检测在配置文件中实现了BeanPostProcessor接口的所有bean,并把它们注册为后置处理器,然后在容器创建bean的适当时候调......

欢迎来到【战羽】的博客 4770

Spring 中Bean的生命周期

Spring 中Bean的生命周期 是怎样的,五大阶段都做了什么。

trigger的博客 4580
上一篇: 数据库基础知识复习
下一篇: Java方法的参数传递机制详解
Coder-Qian
博客等级 码龄11年 63粉丝 73原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值