天天用SpringBoot居然还不知道它的自动装配的原理?

SpringBoot自动装配与启动流程原理深度解析:从源码到实战踩坑 在Java后端开发中,SpringBoot凭借“约定大于配置”的理念大幅降低了项目搭建成本,其核心机制包括自动装配、启动流程、内嵌容器与配置加载。自动装配通过@EnableAutoConfiguration与spring.factories实现按需注入Bean,而启动流程则围绕SpringApplication.run()完成容器初始化与内嵌Web服务器启动。理解这些原理不仅有助于解决日常开发中的Bean覆盖、配置不生效等疑难问题,更是自定义Starter、优化多环境配置、进行源码级排障的基础。本文结合实际 阅读详情

引言

最近有个读者在面试,面试中被问到了这样一个问题“看你项目中用到了springboot,你说下springboot的自动配置是怎么实现的?”这应该是一个springboot里面最最常见的一个面试题了。下面我们就来带着这个问题一起解剖下springBoot的自动配置原理吧。

SpringMvc和SpringBoot对比

首先我们回顾下原来搭建一个springmvc的hello-word的web项目(xml配置的)我们是不是要在pom中导入各种依赖,然后各个依赖有可能还会存在版本冲突需要各种排除。当你历尽千辛万苦的把依赖解决了,然后还需要编写web.xml、springmvc.xml配置文件等。我们只想写个hello-word项目而已,确把一大把的时间都花在了配置文件和jar包的依赖上面。大大的影响了我们开发的效率,以及加大了web开发的难度。为了简化这复杂的配置、以及各个版本的冲突依赖关系,springBoot就应运而生。我们现在通过idea创建一个springboot项目只要分分钟就解决了,你不需要关心各种配置(基本实现零配置)。让你真正的实现了开箱即用。SpringBoot帮你节约了大量的时间去陪女朋友,不对程序员怎么会有女朋友呢?(没有的话也是可以new一个的)它的出现不仅可以让你把更多的时间都花在你的业务逻辑开发上,而且还大大的降低了web开发的门槛。所以SpringBoot还是比较善解人衣的,错啦错啦是善解人意,知道开发人员的痛点在哪。

天天用SpringBoot居然还不知道它的自动装配的原理?

SpringBoot自动配置加载

既然Springboot尽管这么好用,但是作为一个使用者,我们还是比较好奇它是怎么帮我们实现开箱即用的。Spring Boot有一个全局配置文件:application.properties或application.yml。在这个全局文件里面可以配置各种各样的参数比如你想改个端口啦server.port 或者想调整下日志的级别啦通通都可以配置。更多其他可以配置的属性可以参照官网。
https://docs.spring.io/spring-boot/docs/2.3.0.RELEASE/reference/htmlsingle/#common-application-properties

天天用SpringBoot居然还不知道它的自动装配的原理?


这么多属性,这些属性在项目是怎么起作用的呢?SpringBoot项目看下来啥配置也没有,配置”(application.properties或application.yml除外),既 然从配置上面找不到突破口,那么我们就只能从启动类上面找入口了。启动类也就一个光秃秃的一个main方法,类上面仅有一个注SpringBootApplication
这个注解是Spring Boot项目必不可少的注解。那么自动配置原理一定和这个注解有着千丝万缕的联系!我们下面来一起看看这个注解吧。
@SpringBootApplication注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

这里最上面四个注解的话没啥好说的,基本上自己实现过自定义注解的话,都知道分别是什么意思。

  • @SpringBootConfiguration继承自@Configuration,二者功能也一致,标注当前类是配置类。
  • @ComponentScan用于类或接口上主要是指定扫描路径,跟Xml里面的<context:component-scan base-package="" />配置一样。springboot如果不写这个扫描路径的话,默认就是启动类的路径。
  • @EnableAutoConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

这个注解我们重点看下
AutoConfigurationImportSelector这个类
getCandidateConfigurations
这个方法里面通过
SpringFactoriesLoader.loadFactoryNames()扫描所有具有META-INF/spring.factories的jar包( spring.factories 我们可以理解成 Spring Boot 自己的 SPI 机制)。

spring-boot-autoconfigure-x.x.x.x.jar里就有一个spring.factories文件。spring.factories文件由一组一组的Key = value的形式,其中一个key是EnableAutoConfiguration类的全类名,而它的value是一个以AutoConfiguration结尾的类名的列表,有redis、mq等这些类名以逗号分隔。

天天用SpringBoot居然还不知道它的自动装配的原理?

天天用SpringBoot居然还不知道它的自动装配的原理?


我们在回到getAutoConfigurationEntry这个方法当执行完
getCandidateConfigurations这个方法的时候我们可以看到此时总共加载了127个自动配置类。

天天用SpringBoot居然还不知道它的自动装配的原理?


这些类难道都要加载进去吗?springboot还是没有那么傻的,它提倡的话是按需加载。

  • 它会去掉重复的类
  • 过滤掉我们配置了exclude注解的类下面配置就会过滤掉RestTemplateAutoConfiguration这个类
  • 经过上面的处理,剩下的这写自动配置的类如果要起作用的话,是需要满足一定的条件的。这些条件的满足的话spring boot是通过条件注解来实现的。

@ConditionalOnBean:当容器里有指定Bean的条件下
@ConditionalOnClass:当类路径下有指定的类的条件下
@ConditionalOnExpression:基于SpEL表达式为true的时候作为判断条件才去实例化
@ConditionalOnJava:基于JVM版本作为判断条件
@ConditionalOnJndi:在JNDI存在的条件下查找指定的位置
@ConditionalOnMissingBean:当容器里没有指定Bean的情况下
@ConditionalOnMissingClass:当容器里没有指定类的情况下
@
ConditionalOnWebApplication:当前项目时Web项目的条件下
@
ConditionalOnNotWebApplication:当前项目不是Web项目的条件下
@ConditionalOnProperty:指定的属性是否有指定的值
@ConditionalOnResource:类路径是否有指定的值
@
ConditionalOnOnSingleCandidate:当指定Bean在容器中只有一个,或者有多个但是指定首选的Bean

这些注解都组合了@Conditional注解,只是使用了不同的条件组合最后为true时才会去实例化需要实例化的类,否则忽略过滤掉。我们在回到代码可以看到经过了条件判断过滤后我们剩下符合条件的自动配置类只剩23个了。其他的都是因为不满足条件注解而被过滤了。

天天用SpringBoot居然还不知道它的自动装配的原理?


如果我们想知道哪些自动配置类被过滤了,是由于什么原因被过滤了,以及加载了哪些类等。spring boot都为我们记录了日志。还是非常贴心的。我们可以调整下我们日志的级别改为debug。然后我们就能看到以下日志了

天天用SpringBoot居然还不知道它的自动装配的原理?

天天用SpringBoot居然还不知道它的自动装配的原理?


这里就截取了部分日志。总共分别有下面四部分日志:

  • Positive matches:@Conditional条件为真,配置类被Spring容器加载。
  • Negative matches: @Conditional条件为假,配置类未被Spring容器加载。
  • Exclusions: 我们明确了不需要加载的类。比如在上面启动类配置的RestTemplateAutoConfiguration类
  • Unconditional classes: 自动配置类不包含任何类级别的条件,也就是说,类始终会被自动加载。

自动配置生效

我们以ServletWebServerFactoryAutoConfiguration配置类为例,解释一下全局配置文件中的属性如何生效,比如:server.port=88,是如何生效的(当然不配置也会有默认值,这个默认值来自于org.apache.catalina.startup.Tomcat)。

// 标记为配置类
@Configuration(proxyBeanMethods = false)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
// 如果有ServletRequest.class 才会生效
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
// 把@ConfigurationProperties注解的类注入为Spring容器的Bean。
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
		ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
		ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
		ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {

我们可以发现EnableConfigurationProperties注解里面配置的ServerProperties.class

@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {

	/**
	 * Server HTTP port.
	 */
	private Integer port;

在这个类上有一个注解:@ConfigurationProperties,它的作用就是从配置文件中绑定属性到对应的bean上(也就是把我们application.properties对应的server.port映射到ServerProperties 类中的port属性)而@EnableConfigurationProperties这个注解就是把已经绑定了属性的bean(ServerProperties)注入到spring容器中(相当于@Component注解一样)。
所有在配置文件中能配置的属性都是在xxxxPropertites类中封装着,配置文件能配置什么就可以参照某个功能对应的这个属性类。
到现在为止应该能回答文章开头的那个问题了,面试的时候应该不需要回答的这么详细可以参考下以下答案:

Spring Boot启动的时候会通过@EnableAutoConfiguration注解找到META-INF/spring.factories配置文件中的所有自动配置类,并对其进行加载,而这些自动配置类都是以AutoConfiguration结尾来命名的,它实际上就是一个JavaConfig形式的Spring容器配置类,它能通过以Properties结尾命名的类中取得在全局配置文件中配置的属性如:server.port,而XxxxProperties类是通过@ConfigurationProperties注解与全局配置文件中对应的属性进行绑定的。

在网上找了一张图,基本上把自动装配的流程给说清楚了。

天天用SpringBoot居然还不知道它的自动装配的原理?

总结

  • SpringBoot启动会加载大量的自动配置类(通过“SPI”的方式),然后会根据条件注解保留一些需要的类。
  • 我们新引入一个组件,可以先看看springBoot是否已经有默认的提供。
  • SpringBoot基本实现了“零配置“,并且开箱即用。

结束

  • 由于自己才疏学浅,难免会有纰漏,假如你发现了错误的地方,还望留言给我指出来,我会对其加以修正。
  • 如果你觉得文章还不错,你的转发、分享、赞赏、点赞、留言就是对我最大的鼓励。
  • 感谢您的阅读,十分欢迎并感谢您的关注。
    站在巨人的肩膀上摘苹果
无人机VS地面机器人:用AirSim和Gazebo玩转ROS2仿真的5个实战场景对比 本文深度对比了ROS2生态中两大仿真工具AirSim和Gazebo在无人机与地面机器人应用中的表现。通过电力巡检、仓库调度、SLAM建图等5个实战场景,分析了两者在视觉保真度、物理精度、开发效率等方面的差异,并提供了跨平台协作的实用技巧,帮助开发者根据项目需求选择合适的仿真工具。 阅读详情

相关推荐

手把手复现金蝶云星空V8.1文件上传漏洞(附完整POC与修复方案)

本文深度解析金蝶云星空V8.1文件上传漏洞,提供详细的漏洞复现步骤与完整POC,涵盖技术原理、测试环境搭建及验证流程。同时给出多维防护方案,包括官方补丁部署、临时缓解措施和长期安全加固建议,帮助企业有效防范任意文件上传风险。

weixin_30505225的博客 184

SpringBoot自动配置(Auto-Configuration)原理(附面试快速答法)

Spring Boot 通过@EnableAutoConfiguration开启自动装配,通过 SpringFactoriesLoader 最终加载META-INF/spring.factories中的自动配置类实现自动装配,自动配置类其实就是通过@Conditional按需加载的配置类,想要其生效必须引入spring-boot-starter-xxx包实现起步依赖

fengxiandada的博客 6983

游戏经济数值模型的搭建过程——以标准卡牌游戏为例

一、总体规划 1.玩家分类 首先我们按照下表对玩家进行分类 付费能力即为充值额度;充值行为比如购买月卡/购买钻石;消费行为比如用钻石抽卡 在这里我们假设玩家是理性的,即玩家会以追求更高的性价比为目标进行充值与消费(即小R会优先买首冲+月卡,而不是买一个无用的无属性皮肤) 不同类型玩家之间的差异,实际上就主要由这些行为的差异而决定。 注:早期游戏制作的时候,活跃程度也是区分玩家类型的一个重要依据。不过目前现在游戏中有各种手段抹平了不同活跃玩家的差异(体力限制,活跃时间长的收益递减)..

dudu3332的博客 4230

Spring Boot自动装配(必面问题详解)

Spring Boot自动装配问题详解。

FGY_u的博客 3477

macOS 27下PlayCover“没有权限打开”的完整修复指南

macOS系统通过Gatekeeper、TCC(透明、同意与控制)和安全启动等机制,对第三方应用进行层层校验,以防范恶意代码。这些机制会检查应用的隔离属性、签名状态以及所需系统权限,当任一环节不满足时,就会出现“没有权限打开”的提示。对于开发者工具或未上架App Store的开源软件,这类拦截尤为常见。尤其在macOS 27上,系统进一步收紧了绕过策略,导致PlayCover等工具无法正常启动。本文以PlayCover为例,详细解析权限链路上的三道关卡,并给出清除隔离属性、调整SIP状态、重置TCC记录等完

weixin_32612263的博客 756

解密HDMI热插拔检测电路:从HPD引脚到EDID读取的全流程避坑

本文深入解析HDMI热插拔检测与EDID读取的全流程,从HPD引脚信号特性、DDC通道I2C协议到EDID数据结构,系统剖析了硬件电路设计、信号完整性和软件协议中的常见陷阱与解决方案,为消费电子设备开发者提供了一套完整的实战避坑指南。

weixin_29291069的博客 650

Spring Boot 面试题——自动装配

本文介绍了 Spring Boot 中与自动装配相关的面试题。

代码星辰的博客 1609

别再只会调速度了!用STM32的定时器中断精准控制伺服电机转角(避坑指南)

本文详细介绍了如何利用STM32的定时器中断和PWM输出实现伺服电机的精准转角控制,避免常见的速度控制误区。通过硬件配置、脉冲计数逻辑和优化技巧的实战讲解,帮助开发者掌握高精度位置控制方法,适用于工业自动化和机器人控制等场景。

weixin_42531163的博客 418

阿里面试:问springBoot自动装配我这样回答的,面试官对我竖起了大拇指

上周一个读者面试刚刚遇到的,新鲜出炉的面试题。

root 2444

Python爬虫实战:逆向解析天猫商品详情API,精准捕获规格、SKU与促销活动

及浏览器开发者工具),绕过前端渲染的复杂性,直接逆向分析并调用其内部数据接口,从而高效、稳定地抓取商品的关键信息,包括商品规格、多维度SKU信息以及复杂的促销活动。print(f"SKU ID: {sku.sku_id}, 价格: ¥{sku.price}, 库存: {sku.stock}, 规格: {sku.props}")当你访问一个商品链接时,浏览器首先会加载一个几乎为空的HTML骨架,然后通过执行大量的JavaScript代码,向后台服务器发起多个异步请求,最终将获取到的数据填充到页面中。

2201_76125261的博客 1129

uniapp - 最新实现hbuilder项目运行到ios基座或苹果ios真机设备详细教程,如何在ios苹果手机上真机运行测试,IOS自定义基座在线打包调试(uniapp项目如何在苹果手机上运行调试)

uni-app,苹果,app,ios,设备,自定义基座,运行app到苹果手机,mac电脑,Xcode,hbuilderX,运行ios基座调试Uniapp,无需打包,苹果证书,ipa,运行失败,报错,无法启动,连接失败,出错,详细教程,如何解决这个问题,怎么办,申请iOS证书,运行项目到iOS基座,打包ios自定义基座,在iOS真机上运行,新手小白,超级详细的教程,dcloud如何苹果ios系统真机测试,调试基座失败,真机调试ios app,App基座安装后无法打开问题,真机运行时检测不到手机的问题或者基座安

✅ 精选推荐文章 1万+

SpringBoot常见面试题

AutoConfigurationImportSelector组件SpringFactoriesLoader读取(1)META-INF/spring.factories 或者(2)org.springframework.boot.autoconfigure.AutoConfiguration.imports 中的所有自动配置类;条件注解进行过滤 ImportSlector接口实例化Bean对象,放入Spring的IOC容器中;

青山猿的博客 1317

嵌入式软考必备知识点:嵌入式系统开发中的重要概念和示例代码

在嵌入式软考中,有一些重要的知识点需要掌握,包括嵌入式系统的基本概念、编程语言、实时操作系统和硬件接口等。实时操作系统是一种专门设计用于嵌入式系统的操作系统,可以提供对任务调度、中断处理和资源管理等方面的支持。GPIO(通用输入输出):GPIO是嵌入式系统中常用的硬件接口,用于连接外部设备和嵌入式系统。以上是嵌入式软考中的一些必备知识点,包括嵌入式系统的基本概念、编程语言、实时操作系统和硬件接口。通过配置串口的波特率、数据位数和校验位等参数,可以实现与其他设备的可靠通信。一、嵌入式系统的基本概念。

PixeGO的博客 314

天天都在用SpringBoot自动装配,你居然还不知道它的原理?

引言 最近有个读者在面试,面试中被问到了这样一个问题“看你项目中用到了springboot,你说下springboot的自动配置是怎么实现的?”这应该是一个springboot里面最最常见的一个面试题了。下面我们就来带着这个问题一起解剖下springBoot的自动配置原理吧。 SpringMvc和SpringBoot对比 首先我们回顾下原来搭建一个springmvc的hello-word的web项目(xml配置的)我们是不是要在pom中导入各种依赖,然后各个依赖有可能还会存在版本冲突需要各种排除。当你历尽千

罗翔 313

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

SpringBoot 自动装配的原理分析

关于 SpringBoot 的自动装配功能,相信是每一个 Java 程序员天天都会用到的一个功能,但是它究竟是如何实现的呢?今天阿粉来带大家看一下。 自动装配案例 首先我们通过一个案例来看一下自动装配的效果,创建一个 SpringBoot 的项目,在 pom 文件中加入下面的依赖。   <dependency>   <groupId>org.springframework.boot</groupId> &nbsp

Java极客技术 198

IDEA的使用指南

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

java中SpringBoot 自动装配的原理分析

从上面的分析我们就可以看的出来,之所以很多时候我们使用SpringBoot是如此的简单,全都是依赖约定优于配置的思想,很多复杂的逻辑,在框架底层都帮我们做了默认的实现。虽然用起来很爽,但是很多时候会让程序员不懂原理,我们需要做的不仅是会使用,而更要知道底层的逻辑,才能走的更远。基于上面的分析,我们还可以知道,如果我们要实现一个自己的starter其实也很简单,只要安装上面的约定,编写我们自己的配置类和配置文件即可。后面的文章阿粉会带你手写一个自己的starter来具体实现一下。

不定时分享最优质的网络技术与教程,满满的干货。 157

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

一文搞懂SpringBoot自动装配:手写Starter深入@Conditional与@EnableAutoConfiguration原理

你是不是也经历过:引入一个starter,啥都没干,它居然自己“活”了?Web容器启了,数据源配了,连Redis都连上了。这到底是魔法,还是阴谋?别急,今天咱们就掀开SpringBoot自动装配的底裤。从@SpringBootApplication的三大马甲,到@EnableAutoConfiguration背后的“内鬼”AutoConfigurationImportSelector;从spring.factories的“注册表”玄学,到@Conditional系列注解的精准狙击——我们不讲虚的,直接手写一

m0_72340523的博客 844

SpringBoot 自动装配的原理分析,嘎嘎细节

从上面的分析我们就可以看的出来,之所以很多时候我们使用 SpringBoot 是如此的简单,全都是依赖约定优于配置的思想,很多复杂的逻辑,在框架底层都帮我们做了默认的实现。虽然用起来很爽,但是很多时候会让程序员不懂原理,我们需要做的不仅是会使用,而更要知道底层的逻辑,才能走的更远。基于上面的分析,我们还可以知道,如果我们要实现一个自己的 starter 其实也很简单,只要安装上面的约定,编写我们自己的配置类和配置文件即可。后面的文章阿粉会带你手写一个自己的 starter 来具体实现一下。

Cr1556648487的博客 116

SpringBoot - 天天在用 SpringBoot,这些启动参数你知道么?

SpringBoot - 天天在用 SpringBoot,这些启动参数你知道么?

1695

天天用SpringBoot写代码,结果连Starter是什么都不知道?

前言我们都知道,Spring的功能非常强大,但也有些弊端。比如:我们需要手动去配置大量的参数,没有默认值,需要我们管理大量的jar包和它们的依赖。为了提升Spring项目的开发效率,简化一些配置,Spring官方引入了SpringBoot。当然,引入SpringBoot还有其他原因,在这里就不过多描述了。本文重点跟大家一起聊聊SpringBoot的starter机制,因为它太重要了。1 为什么要用...

架构师小秘圈 225

SpringBoot自动装配:从入门到源码的完整指南

文章摘要: SpringBoot的自动装配机制是其成为Java后端开发标准的核心特性。本文从传统Spring开发的痛点切入,详细解析了自动装配的价值和原理。通过剖析@SpringBootApplication注解的三层结构,揭示了自动装配"一个注解、三次筛选"的工作机制。文章还通过实战案例,展示了如何开发自定义Starter,包括创建配置属性类、业务服务类和自动装配类。全文完整呈现了从自动装配原理理解到自定义实现的完整路径,帮助开发者深入掌握这一SpringBoot核心技术。

ywl470812087的博客 285

300行Java手写SpringBoot核心原理:自动装配与内嵌Tomcat

SpringBoot作为Java后端的主流开发框架,其“自动装配”机制一直是理解框架原理的关键。自动装配本质上通过SPI机制读取如spring.factories或AutoConfiguration.imports等配置文件,再配合条件注解按需注册Bean。而内嵌Tomcat让应用可经由main方法直接启动,摆脱外部容器。然而许多开发者日常使用SpringBoot,却对启动链路缺乏直观认知。通过300行Java代码手写一个mini框架,从组件扫描、单例Bean容器、DispatcherServlet请求分发

weixin_32306957的博客 271

SpringBoot进阶:自动装配原理、配置治理与部署实战

Java后端开发中,SpringBoot凭借“自动装配”大幅降低了项目搭建成本,但其背后隐藏的条件注解、配置优先级等机制,恰恰是开发者从“会用”迈向“懂用”的关键。理解自动装配如何通过SPI加载配置类、如何用@Conditional系列注解实现默认与自定义的平衡,能有效解决配置不生效、Bean冲突、版本升级兼容性等高频问题。同时,中间件整合、数据一致性、分布式锁、Docker镜像构建与jar反编译等工程实践,也是进阶必备技能。本文围绕这些核心知识点,梳理SpringBoot进阶路径,帮助开发者系统掌握底层原

weixin_30582943的博客 302
上一篇: 从JVM底层原理分析数值交换那些事·Java大数据高级架构师
下一篇: 今年java面试为何越来越难?春招如何能拿offer
Javaesandyou
博客等级 码龄5年 742粉丝 563原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值