Spring源码-Bean的生命周期和模板方法

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

Bean的生命周期

之前我们提到过SpringApplication的run方法不光可以启动程序,还会返回一个容器,为了演示Bean的从创建到销毁的整个阶段,我们会关闭掉容器。

接下来我们来看想要加入到容器当中的类,映入眼帘的是这几个方法和其注解,先来解释一下这几个注解。

@PostConstruct注解是进行Bean初始化的方法,@PreDestroy的Bean销毁的方法,这里仅限于单例Bean,多例Bean销毁的时机还是和单例Bean不太一样的。

@Value是用来进行值注入的,可以注入配置里的信息或者系统环境变量。

再来说一下这几个方法执行的顺序。先执行构造,再执行依赖注入,再执行初始化,最后执行销毁方法。

接下来我们再针对Bean进行Bean的后处理器的讲解。

默认情况下Spring的BeanFactory只有一些核心的功能,如果想要扩展功能,就要通过后处理器完成,有一类后处理器叫作Bean工厂的后处理器,它主要是补充一些Bean的定义,方便BeanFactory去进行Bean的创建。另外一类就是Bean的后处理器,Bean的后处理器是针对于Bean的声明周期的各个阶段来提供扩展功能,也就是针对Bean的创建,依赖注入,初始化这些阶段。

这里我是实现了两个后处理器接口,并对方法进行重写,方法具体的流程已经写在日志里了。

一般来说第四个方法常用于进行方法的扩展。

第五个方法中的@ConfigurationProperies是用来将Bean的属性和配置文件中的键值对做绑定。而@PostConstruct注解会有那个CommonAnnotationBeanProcessor后处理器去进行解析。

模板方法

先从模板方法的作用说起,模板方法的作用就是提高现有代码的扩展能力。

先创建一个类和一个方法用于模拟BeanFactory当中的getBean方法,如下实现。

但是这样的的代码存在一个问题,就是它的可扩展性比较差,我们代码是直接写死的,比如说现在我们需要在依赖注入阶段去识别@Autowired和@Resource这两个注解,那么我们肯定需要对现有的代码做改写,去添加一些可以识别这两个注解的逻辑,如果我们后续还要添加新的功能,还需要进行改写,这样就会使方法越来越臃肿。

解决方法是这样的,我们创建了一个接口,如果我们想给哪个阶段去进行功能上的扩展,就在这个接口当中去定义相应的方法。

就是说如果是确定的,不变的逻辑,就放在我们的类里,这当然是没问题的,但是如果是不确定的,变化的逻辑,就抽象到接口当中。

当我们要进行扩展时,就在对应的阶段(依赖注入阶段)进行方法的调用,但是我们可能要做不同的扩展,添加不同的BeanPostPreocessor(当前接口不同的实现类),所以我们就创建一个集合去存储我们的后处理器(实现类),然后遍历所有的后处理器,让每一个后处理器都去执行inject的方法。

还有就是如果我们要完成原始对象的依赖注入,就要把原始对象当作参数传入到方法当中,只有有了原始对象,才能去分析原始分析,对原始对象做一些操作啊之类的。

然后我们还需要一个方法去添加我们的后处理器。

某个方法当中,会有一些固定不变的逻辑,而对于会变化的,具有不确定性的处理逻辑呢,就抽象成接口,将来如果要进行扩展了,就去进行具体的实现比如我们的解析那两个注解,再去进行遍历调用。这样的代码是动静结合的,具有高扩展性和很强的灵活性。

光斑大小控制【ZEMAX操作数】 在使用Zemax优化光学系统时,对成像的聚焦光斑大小进行限制,即弥散斑的大小; 一、RSCE(质心RMS光斑半径):二、RSCH(光线RMS光斑半径): 阅读详情

相关推荐

高效网络流量回放:使用tcpreplay实现多目标IP的pcap重放

本文详细介绍了如何使用tcpreplay工具高效回放网络流量pcap文件,并实现多目标IP发送。通过tcprewrite编辑报文和并行回放策略,可满足安全测试、负载测试等场景需求。文章涵盖安装、基础回放、核心技巧及性能优化,帮助读者构建真实流量压力测试环境。

weixin_29297127的博客 480

【Spring Framework 源码阅读与笔记】Bean 的生命周期管理

Bean 生命周期管理:Spring 通过管理 Bean 从创建到销毁的完整生命周期。拦截机制:允许在 Bean 初始化前后执行自定义逻辑,是 AOP 的基础。初始化方法调用:支持自动识别接口和自定义初始化方法,确保 Bean 正确初始化。销毁方法调用:支持通过和自定义方法进行销毁处理,释放资源。应用场景实现了代理模式,允许在 Bean 初始化前后加入自定义处理(如 AOP 增强)。优势:将增强逻辑与业务逻辑分离,实现无侵入式的 Bean 增强。

鸿蒙初开 1096

Innovus Function ECO实战:5步搞定数字后端设计中的网表修正(含Calibre LVS验证技巧)

本文提供了一份完整的Innovus Function ECO实战指南,详细解析了数字后端设计中网表修正的五步流程。从理解Function ECO概念、准备关键文件,到在Innovus中执行逻辑比对、自动布线及GUI检查,并重点攻克了ECO后Calibre LVS验证的难点与调试技巧,帮助工程师高效、精准地完成流片前的设计微调。

day7的博客 950

一文读懂 Spring Bean 的生命周期

欢迎大家关注我的微信公众号【老周聊架构】,Java后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。 一、前言 今天我们来说一说 Spring Bean 的生命周期,小伙伴们应该在面试中经常遇到,这是正常现象。因为 Spring Bean 的生命周期是除了 IoC、AOP 几个核心概念之外最重要概念,大家务必拿下。可 Spring 源代码又比较复杂,跟着跟着就不知道跟到哪里去了,不太好拿下呀。这倒是真的,而且网上一上来就各种贴流程源码,对初学者来说是真的一脸懵逼,就像字.

riemann_的博客 12万+

CocosCreator 面试题(十五)Cocos Creator如何内置protobuf JS版本?

接着,它创建了一个 Player 对象,并使用 protobuf.js 提供的 API 对其进行序列化和反序列化操作。其中,name 和 level 是普通的字段,items 是一个 repeated 字段,表示它可以包含多个值。在 Cocos Creator 中使用 protobuf.js,我们需要先加载 .proto 文件,然后使用 protobuf.js 提供的 API 进行序列化和反序列化操作。JSON和XML是文本格式,更易于阅读和调试,而且在对人类友好的接口和数据交换上更为常见和广泛支持。

w风雨无阻w的专栏 2628

1999年-2022年 上市公司-企业劳动生产率数据(原始数据、代码、最终结果、参考文献)

上市公司企业劳动生产率数据集为企业和市场参与者提供了一个深入分析企业生产效率和劳动效益的工具。通过这些数据,企业可以不断探索创新的发展模式和管理方式,努力提高生产效率,为提升市场竞争力和盈利能力做出贡献。数据名称:上市公司-企业劳动生产率数据数据年份:1999-2022年数据来源:国泰安数据库1999年-2022年 上市公司-企业劳动生产率数据(原始数据、代码、最终结果、参考文献)

2401_84585615的博客 882

【Spring】Spring的Bean的生命周期

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

qq_46096136的博客 1万+

从 Non-Unicode 到 Unicode:ABAP 程序切换的坑、原理与工程化落地指南

摘要 老SAP系统中ABAP程序员常假设1字符=1字节,导致大量代码依赖单字节处理逻辑。Unicode系统的引入彻底改变了字符长度、偏移量等底层认知,强制要求程序遵循Unicode规则。关键问题包括:字符/字节语义混淆、结构体访问风险、以及ABAP语言版本的门槛限制。迁移时需要重点关注字符串处理、二进制协议解析等场景,利用UCCHECK、RSUNISCAN_FINAL等工具扫描风险,并通过持续集成机制确保代码质量。建议在Non-Unicode阶段就启用unicode_check参数模拟严格模式,分批次修复问

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 3458

深度解析 Spring 源码:探寻Bean的生命周期

深度解析 Spring 源码是一项庞大的任务,其中探究 Bean 的生命周期是其中一个重要的方面。在 Spring 框架中,Bean 的生命周期包括创建、初始化、使用和销毁等多个阶段。通过深入研究 Spring 源码,我们可以了解到 Spring 是如何管理这些生命周期的。在 Spring 中,Bean 的生命周期由容器管理,而容器在初始化 Bean 时会遵循一定的流程。这个流程包括实例化 Bean、设置 Bean 的属性、调用 Bean 的初始化方法以及在容器关闭时销毁 Bean。

忆~遂愿的博客 6269

Debezium报错处理系列之二十一:Unable to connect: Communications link failure.The driver has not received any

Debezium报错系列之二十一:Unable to connect: Communications link failure.The driver has not received any。

zhengzaifeidelushang的博客 547

DLMS/COSEM协议的理解体会

DLMS是通信协议,COSEM是电表建模规范。HDLC帧基本格式为0x7e......

一个bug是bug,多个bug能work 8314

Spring深度学习:Bean生命周期及源码解析

本文小豪将带大家深度学习Spring Bean相关知识,包括Bean的生命周期及Bean创建过程的底层源码,学习过程中不仅仅是了解Spring Bean的工作原理,更重要的是学会理解框架的底层逻辑,从而提升我们的思维能力。

Code豪客 2039

LangGraph教程8:LangGraph流式处理

流式处理可显著提升基于LLM应用的响应性。LangGraph支持两种流式模式:values模式返回每一步的完整结果,适合需要完整上下文处理的场景;updates模式仅返回增量变化,适用于实时更新需求。示例代码展示了如何用create_react_agent实现这两种模式,其中values模式完整记录处理流程,updates模式逐步输出结果。通过异步迭代输出流,开发者可以灵活选择适合应用场景的流式处理方式。

Cachel Wood的博客 620

spring bean生命周期源码剖析

spring bean生命周期记不住?看完这篇源码剖析就会了,根本不用背诵

stay_the_course的博客 2958

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

IEM模型,地表粗糙度模拟

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

详解Spring原理之Bean的生命周期

详解Bean的生命周期,并结合源码进行验证Bean的生命周期。

. 1万+

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Spring Bean生命周期

Spring框架的核心能力之一是Bean的生命周期管理。通过容器对Bean的创建、初始化、使用到销毁的全生命周期进行管控,可以专注于业务逻辑,而无需手动处理对象的创建与资源释放。

weixin_44289947的博客 2715

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

spring中bean的生命周期

一、简介 理解spring中bean的生命周期,对于学习和使用spring很有帮助。本文将从两个角度对spring中bean 的生命周期进行介绍,一是bean定义生成;二是bean在初始化、使用、销毁的生命周期中经历的阶段。二、bean定义生成 bean定义生成主要分为三个步骤,即bean定义的获取、bean定义的注册。1、bean定义的获取 bean的定义来源各种各样,如xml定义、java注解...

panda-star的博客 3万+

Spring的Bean初始化过程和生命周期

Spring中Bean生命周期真的不难

初心不忘、始终方得 3528

spring源码学习 三:Bean的生命周期

这一篇文章我们来看看Bean的生命周期,以及从Bean的生命周期中可以学到的设计模式。

nichilemei的博客 1374

一文搞懂 Spring Bean 的生命周期,从理论到源码

一文搞懂 Spring Bean 的生命周期,从理论到源码。

Balance 850

Spring Bean生命周期源码篇

本文深入解析了Spring框架的核心原理,主要涵盖Bean生命周期、依赖注入、AOP实现和循环依赖处理机制。文章详细介绍了Bean的创建过程:从类加载、构造方法推断、依赖注入到初始化阶段,并重点分析了AOP的实现原理和事务管理机制。针对循环依赖问题,文章阐述了三级缓存(singletonObjects、earlySingletonObjects、singletonFactories)的解决方案。此外,还通过手写模拟代码展示了Spring底层工作机制,包括注解扫描、Bean创建、依赖注入和AOP代理等核心流程

qq_43649937的博客 2302

Spring源码 - 这才是Spring Bean生命周期

生命周期回调部分其实讲的很透彻,就是实现 InitializingBean#afterPropertiesSet()、DisposableBean#destroy() 就可以实现生命周期的初始化阶段、销毁阶段 控制,而 @PostConstruct、@PreDestroy 与以上两个是等价的,只不过解耦了(毕竟这两个注解是 javax.annotation 包下的,我们甚至可以不依赖 Spring 模块也能实现)。首先,研究是有先后顺序、前置知识的,要了解生命周期,得先知道 Bean 是如何被创建的。

GDUT_xin的博客 1303

spring bean生命周期详解,源码分析

目录如何获取beanClassPathXmlApplicationContext方法refresh源码分析finishBeanFactoryInitialization(beanFactory):spring bean的完整生命周期进阶版spring bean的完整生命周期 如何获取bean 首先,我们在代码中是怎样获取bean的,方式有以下几种,但不局限于这两种: @Test public void run1(){ //加载配置文件 ApplicationCont

李晨璐的博客 3575

Spring bean生命周期的源码分析(超级详细)

文章目录一. 问题背景二. 储备知识三. 问题引入3.1 循环依赖3.2 对循环依赖的分析3.3 两个小结论3.4 验证两个小结论 一. 问题背景 遇到面试题“Spring Bean的生命周期是怎么样?”,很多网上的博客博文都有总结性的阐述,但是笔者想知道是从哪里开始切入到Spring Bean的生命周期,从什么时候开始,从哪句代码开始研究。因此今天研究一下Spring源码分析Spring Bean的生命周期。 此笔记仅供自己参考,如有错误请指正 参考自: 请别再问Spring Bean的生命周期了! 【

Android_la的博客 3684

深入理解 Spring Bean 生命周期(附源码分析)

Spring Bean 的生命周期是面试中 Spring 系列的一个高频问题,本篇我们将从源码方面来剖析 Spring Bean 的生命周期。

weixin_42118323的博客 1378

【Spring】关于Spring中Bean的生命周期

简单记录Spring中Bean的生命周期

qq_53070263的博客 1834
上一篇: Spring源码-ApplicationContext容器实现
下一篇: Spring源码 - Bean的后处理器
Ged.phoenix
博客等级 码龄12年 117粉丝 39原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值