【java】【springboot】启动方法注解详解

在Spring Boot中,启动方法通常是main方法,它位于应用程序的主类中,负责启动Spring应用上下文。

一、@SpringBootApplication

@SpringBootApplication 是 Spring Boot 中一个非常核心的注解,它是一个复合注解,包含了三个关键的注解:

@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan。这个注解的作用是启动 Spring Boot 应用程序,并且提供了一些自动配置的特性,使得开发者能够快速构建独立的,生产级别的基于 Spring MVC 的应用。

注解各部分的详细解释

1、@SpringBootConfiguration:
这个注解表示该类是一个 Spring 配置类。Spring Boot 使用 JavaConfig 方式来进行配置,这意味着不需要 XML 配置文件。在 @SpringBootConfiguration 类中,你可以定义 @Bean 方法来创建和配置 bean 对象。
2、@EnableAutoConfiguration:
这个注解会自动为你的应用配置许多 bean。Spring Boot 会根据你添加的 jar 依赖自动配置对应的 bean。例如,如果你的应用依赖了 Spring Data JPA 和 Hibernate,则 Spring Boot 会自动为你配置 DataSource 和 EntityManagerFactory 等 bean。
3、@ComponentScan:
这个注解会扫描标注它的类所在的包及子包下的所有 @Component, @Service, @Repository, 和 @Controller 注解的类,使得这些组件可以被 Spring 容器识别和管理。

@SpringBootApplication
public class MyApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

备注:

  • 当你使用 @SpringBootApplication 时,尽量不要在你的主配置类中添加额外的 @EnableAutoConfiguration 或者 @ComponentScan 注解,因为它们已经被 @SpringBootApplication 包含了。
  • 如果你需要排除某个自动配置,可以使用 @SpringBootApplication(exclude = { AutoConfig.class }) 来排除特定的自动配置类。
  • @SpringBootApplication 默认会扫描其所在类的同级及子级包,如果需要扫描其他包,可以通过 @ComponentScan 的 basePackages 或 basePackageClasses 属性进行指定。
 二、@SpringBootConfiguration

@SpringBootConfiguration是Spring Boot框架中的一个注解,它本质上是一个配置类注解,用于标记一个类作为Spring配置类。

@SpringBootConfiguration实际上继承自@Configuration注解,这意味着它具备所有@Configuration注解的功能,可以定义@Bean方法来注册bean到Spring IoC容器中。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
//@SpringBootConfiguration
public class AppConfig {

    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
}
三、@EnableAutoConfiguration

@EnableAutoConfiguration 负责激活 Spring Boot 的自动配置功能。当你在 Spring Boot 应用中使用这个注解,Spring Boot 会根据你添加的依赖和类路径上的 jar 文件自动配置很多 bean 和组件,而无需显式地定义和配置它们。

1、工作原理

@EnableAutoConfiguration 注解会触发 Spring Boot 自动配置机制,扫描所有可用的 AutoConfiguration 类。这些 AutoConfiguration 类会检查应用的环境(如类路径、属性配置等),并根据检测到的条件决定是否激活相关的配置。

例如,如果你的项目中包含了 Spring Data JPA 和 Hibernate 相关的依赖,Spring Boot 会自动配置 DataSource 和 JPA Repository 支持,包括事务管理、JPA 实体管理器工厂等,而无需你手动编写配置。

2、自动配置的原理

1)条件注解:自动配置类使用了一系列条件注解,如 @ConditionalOnClass、@ConditionalOnBean、@ConditionalOnMissingBean、@ConditionalOnProperty 等,这些注解会根据不同的条件决定是否应该激活配置。
2)自动配置元数据:每个 Spring Boot Starter 通常都会包含一个 META-INF/spring.factories 文件,其中列出了该 Starter 所提供的自动配置类。Spring Boot 会读取这些元数据文件,找到所有可用的自动配置类。
3)自动配置类:自动配置类通常是实现了 org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector 接口的配置类,它们可以根据应用的环境动态生成并注册需要的 bean。

示例:

@SpringBootApplication
//@EnableAutoConfiguration
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

在上面的示例中,@SpringBootApplication 注解隐式包含了 @EnableAutoConfiguration。如果要单独使用 @EnableAutoConfiguration,你可以像这样:

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

备注:

  • 当你使用 @EnableAutoConfiguration 时,确保你没有在类路径中添加不兼容的库,否则可能会导致冲突的自动配置。
  • 如果你需要禁用某些自动配置,可以使用 @SpringBootApplication(exclude = { AutoConfig.class }) 或者在 application.properties 或 application.yml 文件中设置相应的属性来关闭。
  • 自动配置是 Spring Boot 强大功能的关键之一,但它也可能带来一些复杂性和难以预料的行为,尤其是在处理第三方库时。因此,在遇到问题时,理解自动配置的工作原理是很重要的。
四、@ComponentScan: 

@ComponentScan 是 Spring 框架中的一个注解,用于自动发现和装配被标注为 Spring Bean 的组件。当在一个配置类上使用此注解时,Spring 会扫描指定的包及其子包,查找标记了 @Component, @Service, @Repository, 或 @Controller 等注解的类,并将它们注册为 Spring 容器中的 Bean。

@Configuration
@ComponentScan("com.example.myapp")
public class AppConfig {
}

在这个例子中,AppConfig 类配置了 Spring 容器去扫描 com.example.myapp 包及其子包内的组件。任何在这个包路径下的、被适当注解标记的类都将被注册为 Spring Bean。

其他示例:

1)指定多个基础包:

@ComponentScan({"com.example.service", "com.example.repository"})
public class AppConfig {
}

2)使用正则表达式:

@ComponentScan(basePackages = {"com\\.example.*"})
public class AppConfig {
}

3) 排除特定包:

@ComponentScan(basePackages = {"com.example"},
               excludeFilters = @Filter(type = FilterType.REGEX, pattern = "com\\.example\\.test.*"))
public class AppConfig {
}

4、包括特定的类:

@ComponentScan(basePackageClasses = {MyComponent.class})
public class AppConfig {
}

这会扫描 MyComponent 类所在的包及其子包。

5、使用自定义组件扫描器:

你可以实现 MergedAnnotation 和 TypeFilter 接口来自定义组件扫描的行为,然后通过 useDefaultFilters 属性控制是否使用默认过滤器。

@ComponentScan(
    basePackages = {"com.example"},
    useDefaultFilters = false,
    includeFilters = {
        @Filter(type = FilterType.CUSTOM, classes = MyCustomTypeFilter.class)
    }
)
public class AppConfig {
}

备注:

  • @ComponentScan 通常与 @Configuration 注解一起使用,以表明这是一个配置类。
  • 被扫描的类需要有无参构造函数,以便 Spring 可以实例化它们。
  • 在使用 @ComponentScan 时,应避免过度扫描,只扫描必要的包,以提高应用启动速度和减少内存消耗。
  • 如果使用 @SpringBootApplication 注解,它已经包含了 @ComponentScan,并且默认扫描该注解所在类的同级及子包。如果需要改变扫描范围,可以通过 @SpringBootApplication(scanBasePackages = {"com.example"}) 来指定。
     
五、@RestController、@Controller、@Service、@Repository: 

@RestController, @Controller, @Service, 和 @Repository 这四个注解用于标记不同的组件类型,它们是Spring IoC容器管理和自动装配的基础。下面是每个注解的详细说明和使用场景:

1、@RestController
@RestController 是一个组合注解,它等价于 @Controller 和 @ResponseBody 的组合。这意味着被此注解标记的类会处理HTTP请求,而且返回的数据会直接转化为响应体发送给客户端,而不是渲染视图。

示例:

@RestController
@RequestMapping("/api")
public class MyRestController {

    @GetMapping("/users")
    public List<User> getUsers() {
        // 返回用户列表的JSON数据
        return userService.getAllUsers();
    }
}


2、 @Controller
@Controller 注解用于标记处理HTTP请求的控制器类。与 @RestController 不同,@Controller 类型的控制器通常会返回视图名,由视图解析器将视图名转换为实际的视图模板。

示例:

@Controller
public class MyViewController {

    @GetMapping("/")
    public String homePage(Model model) {
        // 返回视图名,通常会与视图模板文件对应
        return "home";
    }
}

3、 @Service
@Service 注解用于标记业务逻辑层的服务组件。这些组件通常处理应用的业务逻辑,与数据访问层和表现层相分离。它们通常在控制器中被注入,用于处理业务逻辑。

示例:

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public List<User> getAllUsers() {
        // 业务逻辑处理
        return userRepository.findAll();
    }
}

4、 @Repository
@Repository 注解用于标记数据访问层的组件,如DAO(Data Access Object)。这些组件通常用于与数据库交互,如查询、更新、删除等操作。

示例:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

    List<User> findByLastName(String lastName);
}

总结来说,@RestController 和 @Controller 用于处理HTTP请求,区别在于返回数据的格式;@Service 用于封装业务逻辑;@Repository 用于数据访问和持久化。这些注解帮助Spring框架自动装配组件,并提供依赖注入、事务管理等高级特性,简化了应用的开发过程。

六、@Configuration:

@Configuration是Spring框架中的一个注解,用于标记一个类作为Java配置类,它可以替代XML配置文件来定义和管理Spring应用中的bean。使用@Configuration注解的类通常包含一个或多个@Bean方法,这些方法用于定义和配置应用中的各个组件。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}

在这个例子中,AppConfig类被标记为@Configuration,并且包含了一个@Bean方法,该方法返回一个MyService的实例。当Spring容器启动时,它会调用这个方法来创建MyService的bean实例,并将其注册到容器中。

@Configuration注解的高级用法:

1、嵌套配置:

你可以在一个@Configuration类中导入另一个@Configuration类,这称为嵌套配置或导入配置。

@Configuration
@Import(AnotherConfig.class)
public class RootConfig {
}

2、条件化的bean定义:

你可以使用条件注解,如@ConditionalOnClass、@ConditionalOnMissingClass、@ConditionalOnProperty等,来控制@Bean方法的执行,从而实现更灵活的配置。

@Bean
@ConditionalOnClass(name = "com.example.MyDependency")
public MyService myService() {
    return new MyServiceImpl();
}

 3、使用@Autowired自动装配bean:

在@Bean方法中,你可以使用@Autowired注解来自动装配其他bean。

@Bean
public MyService myService(@Autowired MyDependency dependency) {
    return new MyServiceImpl(dependency);
}

4. 使用@EnableMBeanExport等注解激活额外的功能:
有些注解可以与@Configuration结合使用,以激活Spring框架的额外功能,如JMX监控等。

@Configuration与@SpringBootApplication的关系:
在Spring Boot应用中,@SpringBootApplication注解隐含了@Configuration、@EnableAutoConfiguration和@ComponentScan注解。这意味着在Spring Boot应用中,你不需要显式地使用@Configuration注解来标记配置类,因为@SpringBootApplication已经涵盖了配置类的定义。

总结:
@Configuration注解是Spring框架中用于Java配置的关键注解,它使得开发者可以以面向对象的方式定义bean和它们之间的依赖关系,从而避免了XML配置的繁琐和不直观。通过@Configuration和@Bean注解,开发者可以创建更清晰、更模块化的配置逻辑,同时也便于测试和维护。

七、@Bean:

@Bean 是 Spring 框架中的一个注解,用于在配置类中定义和注册一个 Spring Bean。当一个方法被 @Bean 注解时,该方法的返回值将被注册到 Spring 应用上下文中,成为 Spring IoC 容器管理的对象。这样,其他 Spring Beans 就可以通过依赖注入的方式使用这个 Bean。

@Bean 注解的基本用法:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}

在这个例子中,myService() 方法返回一个 MyServiceImpl 实例,这个实例将被注册为 myService 这个名字的 Bean。

@Bean 注解的高级用法:
1、命名 Bean:
你可以通过 name 属性为 Bean 指定一个或多个名称。

@Bean(name = {"myService", "service"})
public MyService myService() {
    return new MyServiceImpl();
}


2、依赖注入:
@Bean 方法可以接受参数,这些参数可以是其他 Bean,Spring 会自动进行依赖注入。

@Bean
public MyService myService(@Qualifier("myDataSource") DataSource dataSource) {
    return new MyServiceImpl(dataSource);
}

3、作用域:
你可以使用 scope 属性来定义 Bean 的作用域,例如 singleton(默认)、prototype、request 等。

@Bean(scope = "prototype")
public MyService myService() {
    return new MyServiceImpl();
}

4. 懒加载:
使用 lazy 属性可以使 Bean 懒加载,默认情况下,Bean 是在容器启动时创建的,但你可以设置 lazy="true" 来延迟 Bean 的创建直到第一次被请求。

@Bean(lazy = true)
public MyService myService() {
    return new MyServiceImpl();
}

5、初始化和销毁方法:
你还可以指定初始化和销毁方法,这些方法将在 Bean 创建和销毁时调用。

@Bean(initMethod = "init", destroyMethod = "cleanup")
public MyService myService() {
    return new MyServiceImpl();
}


6、条件化 Bean:
你可以使用 @Conditional 注解来控制 Bean 是否被注册,这基于一定的条件。

@Bean
@ConditionalOnClass(name = "com.example.MyDependency")
public MyService myService() {
    return new MyServiceImpl();
}

总结:
@Bean 注解是 Spring 框架中非常强大的工具,它允许开发者以声明式的方式定义和配置 Bean,从而提供更灵活、更可读和更易于维护的配置方式。通过使用 @Bean,你可以充分利用 Spring 的依赖注入和生命周期管理功能,构建出复杂且高度解耦的系统架构。

八、@Profile:

@Profile 是 Spring 框架中的一个注解,用于指示特定的 bean 或配置仅在指定的环境(profile)中激活。Spring profiles 提供了一种在不同的运行环境中(如开发、测试、生产等)使用不同配置的方式,而无需修改代码或重新编译。

如何使用 @Profile:
1、定义 Profiles:
首先,你需要在你的 Spring 应用中定义 profiles。这通常在 application.properties 或 application.yml 配置文件中完成,也可以在 Java 配置类中通过 @ActiveProfiles 注解激活特定的 profile。 在 properties 文件中:
深色版本

spring.profiles.active=dev

或者在 Java 配置类中:

@SpringBootApplication
@ActiveProfiles("dev")
public class MyApp {
    // ...
}

2、使用 @Profile 注解:
使用 @Profile 注解来标记哪些 bean 或配置应该在哪个 profile 下激活。

@Configuration
@Profile("dev")
public class DevConfig {
    // 只在 dev profile 下激活的配置
}

或者在 bean 方法上使用:

@Bean
@Profile("dev")
public DataSource devDataSource() {
    // 返回一个适合开发环境的 DataSource 实例
    return new EmbeddedDatabaseBuilder()
        .setType(EmbeddedDatabaseType.HSQL)
        .addScript("classpath:schema.sql")
        .build();
}

3、多 Profile 支持:
@Profile 注解可以接受多个 profile 名称,以逗号分隔,这意味着 bean 或配置可以在多个 profile 中激活。

@Profile("dev,test")
public class DevTestConfig {
    // 在 dev 和 test profile 下激活的配置
}

备注:

  • 如果没有指定任何 profile,那么默认 profile 将被激活。在 Spring Boot 中,如果没有显式设置 spring.profiles.active,则默认 profile 会被激活。
  • @Profile 注解可以与 @ConditionalOnProperty 结合使用,以实现更复杂的条件化配置。
  • 当使用 @Profile 注解时,确保你的应用能够正确地识别和切换 profile,特别是在部署到不同的环境中时。
九、@ConditionalOnClass、@ConditionalOnMissingClass、@ConditionalOnProperty等:

在Spring框架中,@ConditionalOnClass、@ConditionalOnMissingClass和@ConditionalOnProperty是用于条件性bean注册和自动配置的重要注解。这些注解允许开发者基于不同的条件来决定是否激活某个配置或bean定义。下面详细介绍这些注解的用途和用法:

@ConditionalOnClass
@ConditionalOnClass注解用于检查类路径中是否存在给定的类。如果类路径中存在指定的类,那么带有此注解的配置或bean定义才会被激活。这通常用于检查依赖库的存在,以确定是否应该启用相关的配置。

@Configuration
@ConditionalOnClass(name = "com.example.MyLibraryClass")
public class MyLibraryConfig {

    @Bean
    public MyLibraryBean myLibraryBean() {
        return new MyLibraryBean();
    }
}

在这个例子中,如果com.example.MyLibraryClass存在于类路径中,MyLibraryConfig配置类和myLibraryBean bean定义才会被激活。

@ConditionalOnMissingClass
与@ConditionalOnClass相反,@ConditionalOnMissingClass用于检查类路径中是否不存在给定的类。如果指定的类不存在,那么带有此注解的配置或bean定义才会被激活。

示例:

@Configuration
@ConditionalOnMissingClass(name = "com.example.MyLibraryClass")
public class FallbackConfig {

    @Bean
    public FallbackBean fallbackBean() {
        return new FallbackBean();
    }
}


在这个例子中,如果com.example.MyLibraryClass不在类路径中,FallbackConfig配置类和fallbackBean bean定义才会被激活。

@ConditionalOnProperty
@ConditionalOnProperty注解用于检查Spring配置属性的存在或值。如果满足指定的属性条件,那么带有此注解的配置或bean定义才会被激活。这通常用于基于环境配置或用户偏好来启用或禁用某些功能。

示例:

@Configuration
@ConditionalOnProperty(name = "feature.enabled", havingValue = "true", matchIfMissing = false)
public class FeatureConfig {

    @Bean
    public FeatureBean featureBean() {
        return new FeatureBean();
    }
}

在这个例子中,只有当feature.enabled属性被设置为true时,FeatureConfig配置类和featureBean bean定义才会被激活。如果属性未设置,且matchIfMissing属性设置为false,则配置不会被激活。

这些条件注解使得Spring Boot应用能够更加智能和动态地配置自身,根据不同的环境和依赖情况来调整行为。它们是实现“约定优于配置”原则的关键部分,有助于简化开发流程并提高应用的可维护性和可扩展性。

十、@PostConstruct:

@PostConstruct 是一个由 JSR-250 规范定义的生命周期回调注解,用于标记一个非静态方法,该方法在依赖注入完成后由容器调用。在 Spring 框架中,@PostConstruct 注解可以被用来确保在对象初始化完毕、依赖关系已经注入之后执行某些操作。

1、主要用途
@PostConstruct 主要用于以下场景:

初始化资源:例如,打开文件、建立数据库连接、初始化缓存等。
配置对象状态:在依赖注入完成后对对象的状态进行进一步的配置或校验。
执行一次性的设置:执行一次性的设置或计算,如计算常量、初始化数据结构等。
2、示例
在 Java 类中,你可以在任何非静态方法上添加 @PostConstruct 注解。

import javax.annotation.PostConstruct;

public class MyComponent {

    private Connection connection;

    public void setConnection(Connection connection) {
        this.connection = connection;
    }

    @PostConstruct
    public void initialize() {
        // 确保连接已建立
        if (connection != null) {
            // 执行初始化操作
            // ...
        } else {
            throw new IllegalStateException("Connection must not be null");
        }
    }
}

在这个例子中,initialize 方法将在依赖注入完成后由 Spring 调用。如果依赖注入失败,initialize 方法将不会被调用。

注意:

  • 非静态方法:@PostConstruct 只能用于非静态方法。
  • 无参数:@PostConstruct 方法不能接受任何参数。
  • 执行顺序:如果有多个 @PostConstruct 方法,它们的执行顺序取决于方法的定义顺序。
  • 异常处理:如果 @PostConstruct 方法抛出异常,Spring 会将 bean 标记为异常,并从应用上下文中移除该 bean。
十一、@PreDestroy:

@PreDestroy 是一个由JSR-250规范定义的注解,用于标记在Java对象销毁之前应该调用的方法。在Spring框架中,@PreDestroy 注解被用来确保在Spring管理的bean被销毁之前,可以执行一些必要的清理操作,比如关闭打开的资源、释放锁、清理缓存等。

1、使用场景

@PreDestroy 注解通常用于以下场景:

  • 关闭数据库连接或释放数据库资源。
  • 清理临时文件或目录。
  • 释放系统资源,如线程池、网络连接等。
  • 执行日志记录,记录对象销毁的时刻。
  • 清除缓存或执行任何必要的清理工作。

2、示例

import javax.annotation.PreDestroy;

public class MyResource {

    // ... 其他代码 ...

    @PreDestroy
    public void cleanup() {
        // 执行清理操作,例如关闭资源
        if (resource != null) {
            resource.close();
        }
    }
}

要在Spring中使用@PreDestroy,只需在你希望在bean销毁前调用的方法上添加此注解即可。

注意事项

  • 调用时机:@PreDestroy 方法会在bean的所有依赖关系被解除后调用,但在bean完全从Spring容器中移除之前。
  • 依赖于Spring容器:@PreDestroy 的行为依赖于Spring容器的管理。如果你的对象不是由Spring容器管理的,或者容器未正确关闭,那么@PreDestroy 方法可能不会被调用。
  • 非静态方法:@PreDestroy 注解只能应用于非静态方法。
  • 方法签名:@PreDestroy 方法不能接受任何参数,并且通常不返回任何值(即void类型)。
  • 异常处理:如果@PreDestroy 方法抛出异常,Spring容器会记录异常,但不会阻止bean的销毁过程。
十二、@Scheduled:

用于在Spring应用中定义定时任务。它允许你以声明的方式在Spring管理的bean中定义周期性的任务,而无需使用外部的调度工具如Quartz或cron。

1、基本语法

@Scheduled注解可以应用于任何非私有方法上,支持以下几种配置属性:

  • fixedRate: 从上一次任务执行结束起,等待固定的时间后再次执行。
  • fixedDelay: 与fixedRate类似,但是等待时间从上一次任务开始执行时计算。
  • initialDelay: 在第一次执行前等待的时间。
  • cron: 使用cron表达式来定义任务执行的时间表。

2、示例

以下是一个使用@Scheduled注解的简单示例:

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTasks {

    @Scheduled(cron = "0 0/1 * * * ?") // 每分钟执行一次
    public void runEveryMinute() {
        System.out.println("Running task every minute at: " + LocalDateTime.now());
    }

    @Scheduled(fixedRate = 5000) // 每5秒执行一次
    public void runEveryFiveSeconds() {
        System.out.println("Running task every five seconds at: " + LocalDateTime.now());
    }
}

3、配置定时任务

为了使@Scheduled注解生效,你需要在Spring配置中启用定时任务的支持。这可以通过在配置类上添加@EnableScheduling注解来实现:

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

@Configuration
@EnableScheduling
public class AppConfig {
}

备注:

  • 定时任务的执行并不保证是精确的,尤其是当任务执行时间较长时,可能会出现累积延迟。
  • 如果多个定时任务同时触发,Spring会确保它们不会并发执行,除非你显式地配置线程池来支持并发执行。
  • 在分布式环境中,使用@Scheduled可能导致多个实例同时执行相同的定时任务。为了解决这个问题,你可能需要实现某种形式的任务锁定机制或使用集中式的任务调度解决方案。

  • 36
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值