第十五章 Spring基于注解的配置(Spring Framework3.1教程)

从Spring2.5可以使用基于注解的依赖注入。因此可以替代XML去描述bean的包装,你可以在组建类上使用注解在相关的类,方法或域声明上。

注解的注入在XML注入之前执行,然而后者的配置将覆盖前者的包装属性通过两种方式。

基于注解的包装Spring容器不是默认打开的。因此,在你可以使用注解包装之前,你需要在Spring配置文件中开启它。因此考虑如下的配置文件如果你想使用任何注解在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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
 http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	<context:annotation-config />
	<!-- bean definitions go here -->
</beans>

一旦<context:annotation-config/>配置了,你可以开始注解你的代码指明Spring将会自动的包装值到属性、方法、构造函数。让我们看看几个重要的注解去理解他们如何工作的:

序号 

注解&描述

1

@Required

@Required注解使用在bean的属性setter方法上。

2

@Autowired

@Autowired注解可以使用在bean属性setter方法、非setter方法、构造函数、属性上。

3

@Qualifier

Qualifier注解总是跟着@Autowired可以消除装配的混乱通过指明确切的bean来装配。

4

JSR-250 Annotations

Spring支持基于JSR-250标准的注解包括@Resource,@PostConstruct和@PreDestroy注解。

Spring @Required注解

@Required注解应用于bean的属性setter方法并且它指明影响的bean属性必须陪hi在XML配置文件中否则容器会抛出BeanInitializationException异常。如下展示了@Required注解的用法。

示例

让我们使用Eclipse IDE按如下的步骤创建一个Spring应用:

步骤 

描述

1

创建一个SpringExample的项目并在src目录下创建com.tutorialspoint包。

2

在Add External JARs选项卡中添加Spring库如在Spring Hello World章节中所讲。

3

在com.tutorialspoint包下创建Student、 MainApp类。

4

在src目录下创建bean的配置文件Beans.xml

5

最后一步在Java类中和Bean配置文件中添加内容,并运行应用。

如下是Student的源代码:

package com.tutorialspoint;

import org.springframework.beans.factory.annotation.Required;
public class Student {
    private Integer age;
    private String name;

    @Required
    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getAge() {
        return age;
    }

    @Required
    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

如下是MainApp的源代码:

package com.tutorialspoint;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");

        Student student = (Student) context.getBean("student");
        System.out.println("Name : " + student.getName());
        System.out.println("Age : " + student.getAge());
    }
}

如下是配置文件Beans.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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
 http://www.springframework.org/schema/context 
 http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<context:annotation-config />

	<!-- Definition for student bean -->
	<bean id="student" class="com.tutorialspoint.Student">
		<property name="name" value="Zara" />

		<!-- try without passing age and check the result -->
		<!-- property name="age" value="11" -->
	</bean>
</beans>

一但你创建成功源代码和配置文件,运行应用。如果一切正常,这将会抛出BeanInitializationException异常并且打印如下异常和其他log信息:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'student' defined in class path resource[Beans15.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanInitializationException: Property 'age' is required for bean 'student'
 ……………

接下来,你可以移除例子中注释掉的“age”属性如下:

<?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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
 http://www.springframework.org/schema/context 
 http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<context:annotation-config />
	<!-- Definition for student bean -->
	<bean id="student" class="com.tutorialspoint.Student">
		<property name="name" value="Zara" />
		<property name="age" value="11" />
	</bean>

</beans>

现在上面的例子将会输出如下结果:

Name : Zara
Age : 11

Spring @Autowired注解

@Autowired注解提供了更细粒度的控制在何处和如何自动完成装配上。@Autowired注解可以使用在自动装配bean的setter方法上就像@Required注解、构造函数、属性、和任意名字或多参数的方法上。

@Autowired在setter方法上

你可以使用@Autowired注解在setter方法上去摆脱<property>元素在XML配置文件中。当Spring发现@Autowired注解使用在setter方法上时,它会尝试在方法上根据类型自动包装。

示例

让我们使用Eclipse IDE按如下的步骤创建一个Spring应用:

步骤 

描述

1

创建一个SpringExample的项目并在src目录下创建com.tutorialspoint包。

2

在Add External JARs选项卡中添加Spring库如在Spring Hello World章节中所讲。

3

在com.tutorialspoint包下创建TextEditor、SpellChecker 、 MainApp类。

4

在src目录下创建bean的配置文件Beans.xml

5

最后一步在Java类中和Bean配置文件中添加内容,并运行应用。

如下是TextEditor源代码:

package com.tutorialspoint;
import org.springframework.beans.factory.annotation.Autowired;

public class TextEditor {
    private SpellChecker spellChecker;
    @Autowired
    public void setSpellChecker(SpellChecker spellChecker) {
        this.spellChecker = spellChecker;
    }

    public SpellChecker getSpellChecker() {
        return spellChecker;
    }

    public void spellCheck() {
        spellChecker.checkSpelling();
    }
}

如下是依赖类SpellChecker的源代码:

package com.tutorialspoint;

public class SpellChecker {
    public SpellChecker() {
        System.out.println("Inside SpellChecker constructor.");
    }

    public void checkSpelling() {
        System.out.println("Inside checkSpelling.");
    }
}

如下是MainApp的源代码:

package com.tutorialspoint;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");

        TextEditor te = (TextEditor) context.getBean("textEditor");

        te.spellCheck();
    }
}

如下是配置文件Beans.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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context-3.0.xsd">
 
    <context:annotation-config />
 
    <!-- Definition for textEditor bean withoutconstructor-arg -->
    <bean id="textEditor" class="com.tutorialspoint.TextEditor">
    </bean>
 
    <!-- Definition for spellChecker bean -->
    <bean id="spellChecker" class="com.tutorialspoint.SpellChecker">
    </bean>
 
</beans>

一旦你完成了上面源代码和配置文件,运行应用,如果一切正常,会打印如下消息:

Inside SpellChecker constructor.
Inside checkSpelling.

@Autowired在属性上

你可以使用@Autowired注解在属性上去摆脱setter方法。当你使用<property>标签传递自动装配的值时,Spring将会自动的指派传递的值或引用给属性。因此是哦那个@Autowired在属性上,你的TextEditor源代码将会是下面这个样子:

package com.tutorialspoint;
import org.springframework.beans.factory.annotation.Autowired;
public class TextEditor {

    @Autowired
    private SpellChecker spellChecker;

    public void setSpellChecker(SpellChecker spellChecker) {
        this.spellChecker = spellChecker;
    }
    public SpellChecker getSpellChecker() {
        return spellChecker;
    }

    public void spellCheck() {
        spellChecker.checkSpelling();
    }
}

如下是配置文件:

<?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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
 http://www.springframework.org/schema/context 
 http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	<context:annotation-config />
	<!-- Definition for textEditor bean -->
	<bean id="textEditor" class="com.tutorialspoint.TextEditor">
	</bean>
	<!-- Definition for spellChecker bean -->
	<bean id="spellChecker" class="com.tutorialspoint.SpellChecker">
	</bean>
</beans>

一旦你完成了上面源代码和配置文件,运行应用,如果一切正常,会打印如下消息:

Inside SpellChecker constructor.
Inside checkSpelling.

构造函数使用@Autowired

你也可以使用@Autowired到构造函数。@Autowired使用在构造函数上表明构造函数将会自动包装当创建bean时,尽管配置文件没有使用<constructor-arg>元素。让我们检查一下下面的例子。

如下是TextEditor的源代码:

package com.tutorialspoint;
import org.springframework.beans.factory.annotation.Autowired;

public classTextEditor {

   privateSpellChecker spellChecker;

 

   @Autowired

   publicTextEditor(SpellChecker spellChecker) {

       System.out.println("Inside TextEditor constructor.");

        this.spellChecker = spellChecker;

   }

 

   publicvoidspellCheck() {

        spellChecker.checkSpelling();

   }

}

如下是Bean配置文件:

<?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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
 http://www.springframework.org/schema/context 
 http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	<context:annotation-config />
	<!-- Definition for textEditor bean without constructor-arg -->
	<bean id="textEditor" class="com.tutorialspoint.TextEditor">
	</bean>
	<!-- Definition for spellChecker bean -->
	<bean id="spellChecker" class="com.tutorialspoint.SpellChecker">
	</bean>
</beans>

一旦你完成了上面源代码和配置文件,运行应用,如果一切正常,会打印如下消息:

Inside SpellChecker constructor.
Inside TextEditor constructor.
Inside checkSpelling.

@Autowired带有选项(required=false)

默认,@Autowired注解意味着依赖是必须的类是@Required注解,然而,你可以关闭这个默认的行为通过使用@Autowired的(required=false)选项。

这个例子将会工作尽管你没有传递任何值给age属性,但name属性是必须的。你可以试着练习这个例子,它和@Required注解实例类似,只是更改了Student类。

package com.tutorialspoint;

import org.springframework.beans.factory.annotation.Autowired;

public class Student {
    private Integer age;
    private String name;

    @Autowired(required = false)
    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getAge() {
        return age;
    }

    @Autowired
    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

Spring @Qualifier注解

或许有一种情况,同一个类型你可以创建多个bean对象,只想使用一个包装属性,这种情况你可以使用@Qualifier注解跟着@Autowired注解,通过指明确定的包装bean消除混乱。如下例子展示了@Qualifier注解。

示例

让我们使用Eclipse IDE按如下的步骤创建一个Spring应用:

步骤 

描述

1

创建一个SpringExample的项目并在src目录下创建com.tutorialspoint包。

2

在Add External JARs选项卡中添加Spring库如在Spring Hello World章节中所讲。

3

在com.tutorialspoint包下创建Student、 Profile、 MainApp类。

4

在src目录下创建bean的配置文件Beans.xml

5

最后一步在Java类中和Bean配置文件中添加内容,并运行应用。

如下是Student的源代码:

package com.tutorialspoint;

public class Student {
    private Integer age;
    private String name;

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

如下是Profile的源代码:

package com.tutorialspoint;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

public class Profile {
    
    @Autowired
    @Qualifier("student1")
private Student student;

    public Profile() {
        System.out.println("Inside Profile constructor.");
    }
 public void printAge() {
        System.out.println("Age : " + student.getAge());
    }

    public void printName() {
        System.out.println("Name : " + student.getName());
    }
}

如下是MainApp的源代码:

package com.tutorialspoint;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");

        Profile profile = (Profile) context.getBean("profile");

        profile.printAge();
        profile.printName();
    }
}

考虑示例如下的配置文件Beans.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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
 http://www.springframework.org/schema/context 
 http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	<context:annotation-config />
	<!-- Definition for profile bean -->
	<bean id="profile" class="com.tutorialspoint.Profile">
	</bean>
</bean>
	<!-- Definition for student1 bean -->
	<bean id="student1" class="com.tutorialspoint.Student">
		<property name="name" value="Zara" />
		<property name="age" value="11" />
	</bean>
	<!-- Definition for student2 bean -->
	<bean id="student2" class="com.tutorialspoint.Student">
		<property name="name" value="Nuha" />
		<property name="age" value="2" />
	</bean>
</beans>

一旦你完成了上面源代码和配置文件,运行应用,如果一切正常,会打印如下消息:

Inside Profile constructor.
Age : 11
Name : Zara

Spring JSR-250注解

基于JSR-250的注解包括@PostConstructor、@PreDestroy、@Resource。尽管这些注解不是一定需要的因为你有其他的替代但还是让我简单讲述一下他们。

@PostConstruct 和 @PreDestroy注解

定义装配和卸载一个bean,我们简单的通过声明bean带有<init-method>和<destroy-method>参数。这个init-method属性指明这个方法必须在bean实例化后立即调用。相同,destroy-method指明容器在销毁这个bean之前调用这个方法。

         你可以使用@PostConstruct注解作为可选的初始化回调,@PreDestroy注解作为可选的销毁回调方法,如下示例解释。

      示例

让我们使用Eclipse IDE按如下的步骤创建一个Spring应用:

步骤 

描述

1

创建一个SpringExample的项目并在src目录下创建com.tutorialspoint包。

2

在Add External JARs选项卡中添加Spring库如在Spring Hello World章节中所讲。

3

在com.tutorialspoint包下创建HelloWorld 、 MainApp类。

4

在src目录下创建bean的配置文件Beans.xml

5

最后一步在Java类中和Bean配置文件中添加内容,并运行应用。

如下是HelloWorld源代码:

package com.tutorialspoint;

import javax.annotation.*;

public class HelloWorld {
    private String message;

    public void setMessage(String message) {
        this.message = message;
    }

    public String getMessage() {
        System.out.println("Your Message : " + message);
        return message;
    }

    @PostConstruct
    public void init() {
        System.out.println("Bean is going through init.");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("Bean will destroy now.");
    }
}

如下是MainApp的源文件,这里你需要注册一个关闭的钩子registerShutdownHook()方法这个方法在AbstractApplicationContext类中声明。这将确保完美的关闭和调用销毁相关的方法。

package com.tutorialspoint;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApper5veree {
    public static void main(String[] args) {
        AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans15.xml");
        HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
        obj.getMessage();
        context.registerShutdownHook();
    }
}

如下是需要init和destroy方法的配置文件Beans.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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
      http://www.springframework.org/schema/context 
 http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	<context:annotation-config />
	<bean id="helloWorld" class="com.tutorialspoint.HelloWorld"
		init-method="init" destroy-method="destroy">
		<property name="message" value="Hello World!" />
	</bean>
</beans>

  一旦你完成了上面源代码和配置文件,运行应用,如果一切正常,会打印如下消息:

Bean is going through init.
Your Message : Hello World!
Bean will destroy now.

@Resource注解

你可以使用@Resource注解在域上或setter方法上,它同样可以在Java EE 5下工作。@Resource注解带有“name”属性,它将会解释相同名字的bean注入。你可以说,它和根据名字装配的语义相同,如下所示。

示例

package com.tutorialspoint;
import javax.annotation.Resource;
public class TextEditor {
    private SpellChecker spellChecker;
    @Resource(name = "spellChecker")
    public void setSpellChecker(SpellChecker spellChecker) {
        this.spellChecker = spellChecker;
    }
    public SpellChecker getSpellChecker() {
        return spellChecker;
    }
    public void spellCheck() {
        spellChecker.checkSpelling();
    }
}

如果没有“name”被精确的指明,这个默认的名字是从域名或setter方法推断得来。如果是域,它就是域名;如果是setter方法,它就是bean的属性名。





























  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值