Spring笔记(正,)

spirng

1.什么是spring?

Spring框架是一个开放源代码的J2EE应用程序框架,由Rod Johnson发起,是针对bean的生命周期进行管理的轻量级容器(lightweight container)。 Spring解决了开发者在J2EE开发中遇到的许多常见的问题,提供了功能强大IOC、AOP及Web MVC等功能

IOC控制反转

AOP面向切面编程

1.1spirng的优点

1.方便解耦,简化开发

通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。

2.AOP编程的支持

通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。

3.声明式事务的支持

在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。

4.方便程序的测试

可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便的测试Spring程序。

5.方便集成各种优秀框架

Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。

6.降低Java EE API的使用难度

Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低。

1.2spring体系结构

1589898827992

核心容器

核心容器由spring-core,spring-beans,spring-context,spring-context-support和spring-expression(SpEL,Spring表达式语言,Spring Expression Language)等模块组成,它们的细节如下:

  • spring-core模块提供了框架的基本组成部分,包括 IoC 和依赖注入功能。
  • spring-beans 模块提供 BeanFactory,工厂模式的微妙实现,它移除了编码式单例的需要,并且可以把配置和依赖从实际编码逻辑中解耦。
  • context模块建立在由corebeans 模块的基础上建立起来的,它以一种类似于JNDI注册的方式访问对象。Context模块继承自Bean模块,并且添加了国际化(比如,使用资源束)、事件传播、资源加载和透明地创建上下文(比如,通过Servelet容器)等功能。Context模块也支持Java EE的功能,比如EJB、JMX和远程调用等。ApplicationContext接口是Context模块的焦点。spring-context-support提供了对第三方库集成到Spring上下文的支持,比如缓存(EhCache, Guava, JCache)、邮件(JavaMail)、调度(CommonJ, Quartz)、模板引擎(FreeMarker, JasperReports, Velocity)等。
  • spring-expression模块提供了强大的表达式语言,用于在运行时查询和操作对象图。它是JSP2.1规范中定义的统一表达式语言的扩展,支持set和get属性值、属性赋值、方法调用、访问数组集合及索引的内容、逻辑算术运算、命名变量、通过名字从Spring IoC容器检索对象,还支持列表的投影、选择以及聚合等。
数据访问/集成

数据访问/集成层包括 JDBC,ORM,OXM,JMS 和事务处理模块,它们的细节如下:

(注:JDBC=Java Data Base Connectivity,ORM=Object Relational Mapping,OXM=Object XML Mapping,JMS=Java Message Service)

  • JDBC 模块提供了JDBC抽象层,它消除了冗长的JDBC编码和对数据库供应商特定错误代码的解析。
  • ORM 模块提供了对流行的对象关系映射API的集成,包括JPA、JDO和Hibernate等。通过此模块可以让这些ORM框架和spring的其它功能整合,比如前面提及的事务管理。
  • OXM 模块提供了对OXM实现的支持,比如JAXB、Castor、XML Beans、JiBX、XStream等。
  • JMS 模块包含生产(produce)和消费(consume)消息的功能。从Spring 4.1开始,集成了spring-messaging模块。。
  • 事务模块为实现特殊接口类及所有的 POJO 支持编程式和声明式事务管理。(注:编程式事务需要自己写beginTransaction()、commit()、rollback()等事务管理方法,声明式事务是通过注解或配置由spring自动处理,编程式事务粒度更细)

Web

Web 层由 Web,Web-MVC,Web-Socket 和 Web-Portlet 组成,它们的细节如下:

  • Web 模块提供面向web的基本功能和面向web的应用上下文,比如多部分(multipart)文件上传功能、使用Servlet监听器初始化IoC容器等。它还包括HTTP客户端以及Spring远程调用中与web相关的部分。。
  • Web-MVC 模块为web应用提供了模型视图控制(MVC)和REST Web服务的实现。Spring的MVC框架可以使领域模型代码和web表单完全地分离,且可以与Spring框架的其它所有功能进行集成。
  • Web-Socket 模块为 WebSocket-based 提供了支持,而且在 web 应用程序中提供了客户端和服务器端之间通信的两种方式。
  • Web-Portlet 模块提供了用于Portlet环境的MVC实现,并反映了spring-webmvc模块的功能。
其他

还有其他一些重要的模块,像 AOP,Aspects,Instrumentation,Web 和测试模块,它们的细节如下:

  • AOP 模块提供了面向方面的编程实现,允许你定义方法拦截器和切入点对代码进行干净地解耦,从而使实现功能的代码彻底的解耦出来。使用源码级的元数据,可以用类似于.Net属性的方式合并行为信息到代码中。
  • Aspects 模块提供了与 AspectJ 的集成,这是一个功能强大且成熟的面向切面编程(AOP)框架。
  • Instrumentation 模块在一定的应用服务器中提供了类 instrumentation 的支持和类加载器的实现。

1.3spring-framework下载

官方网址:https://spring.io/projects/spring-framework

下载地址:https://repo.spring.io/libs-release-local/org/springframework/spring/5.0.2.RELEASE/

解压之后如下图

1589899338777

docs 文件为说明文档

libs 为依赖jar包

schema 为spring约束

2.spirng核心容器

Spring容器会负责控制程序之间的关系,而不是由程序代码直接控制。Spring为我们提供了两种核心容器,分别为BeanFactory和ApplicationContext

1.BeanFactory

创建BeanFactory实例时,需要提供Spring所管理容器的详细配置信息,这些信息通常采用XML文件形式来管理,其加载配置信息的语法如下:

 BeanFactory beanFactory = 
           new XmlBeanFactory(new FileSystemResource("F: /applicationContext.xml"));

2.ApplicationContext

ApplicationContext是BeanFactory的子接口,是另一种常用的Spring核心容器。它由org.springframework.context.ApplicationContext接口定义,不仅包含了BeanFactory的所有功能,还添加了对国际化、资源访问、事件传播等方面的支持。创建ApplicationContext接口实例,通常采用两种方法。

1通过ClassPathXmlApplicationContext创建
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(String configLocation);

ClassPathXmlApplicationContext会从类路径classPath中寻找指定的XML配置文件,找到并装载完成ApplicationContext的实例化工作

2.通过FileSystemXmlApplicationContext创建
 ApplicationContext applicationContext = new FileSystemXmlApplicationContext(String configLocation);

FileSystemXmlApplicationContext会从指定的文件系统路径(绝对路径)中寻找指定的XML配置文件,找到并装载完成ApplicationContext的实例化工作。

3.获取Bean实例

创建Spring容器后,就可以获取Spring容器中的Bean。Spring获取Bean的实例通常采用以下两种方法:

  • Object getBean(String name);

根据容器中Bean的id或name来获取指定的Bean,获取之后需要进行强制类型转换。

  • T getBean(Class requiredType);

根据类的类型来获取Bean的实例。由于此方法为泛型方法,因此在获取Bean之后不需要进行强制类型转换。

3.spring入门程序

1.创建maven工程引入以下依赖

<properties>
        <!--在当前pom 或者父类pom 中声明属性  -->
        <spirng.version>5.0.16.RELEASE</spirng.version>
    </properties>


    <dependencies>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spirng.version}</version>
        </dependency>


    </dependencies>

2.创建配置文件application.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <!-- 声明一个 id 为student的 实例 -->
    <bean id="student" class="com.wgz.spring.entity.Student">
        <property name="name" value="xiaoming"/>
        <property name="age" value="18"/>
    </bean>



</beans>

3.测试

public class Test {

    public static void main(String[] args) {

        // 获取容器方式1
      //  BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource("C:\\Users\\Admin\\Desktop\\假期\\spring\\spring\\spring01\\springdemo\\src\\main\\resources\\application.xml"));
//        Student student =  beanFactory.getBean(Student.class);
//        System.out.println("student:"+student);

        // 获取容器方式2
//        classpath:  加不加都可以
//        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:application.xml");

        // 获取容器方式3
        ApplicationContext applicationContext = new FileSystemXmlApplicationContext("C:\\Users\\Admin\\Desktop\\假期\\spring\\spring\\spring01\\springdemo\\src\\main\\resources\\application.xml");


//        Student student =  applicationContext.getBean(Student.class);
        Student student = (Student) applicationContext.getBean("student");
        System.out.println("student:"+student);

    }

}

4.控制反转&依赖注入

控制反转IOC

控制反转,IOC。在使用Spring框架之后,**对象的实例不再由调用者来创建,而是由Spring容器来创建,**Spring容器会负责控制程序之间的关系,而不是由调用者的程序代码直接控制。这样,控制权由应用代码转移到了Spring容器,控制权发生了反转,这就是控制反转。

依赖注入

DI的全称是Dependency Injection,中文称之为依赖注入

从Spring容器的角度来看,Spring容器负责将被依赖对象赋值给调用者的成员变量,这相当于为调用者注入了它依赖的实例,这就是Spring的依赖注入。

示例
1.分别创建Student对应的Dao,Service实现类
2.创建配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">



    <!-- 声明一个 id 为studentDao的 实例 -->
    <bean id="studentDao" class="com.wgz.spring.dao.impl.StudentDaoImpl">

    </bean>
    <!-- 声明一个 id 为studentService的 实例,并将id为 studentDao的实例注入给StudentServiceImpl-->
    <bean id="studentService" class="com.wgz.spring.service.StudentServiceImpl">
        <property name="studentDao" ref="studentDao"></property>
    </bean>


</beans>
3.测试
public class Test2 {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:application.xml");

       StudentService studentService =   applicationContext.getBean(StudentService.class);

       Student student =  studentService.findStudentById(10);
        System.out.println("student:"+student);

    }
}

5.Bean的配置

1.什么是Bean?

如果把Spring看做一个大型工厂,则Spring容器中的Bean就是该工厂的产品。要想使用这个工厂生产和管理Bean,就需要在配置文件中告诉它需要哪些Bean,以及需要使用何种方式将这些Bean装配到一起。

Bean的本质就是Java中的对象,而Spring中的Bean其实就是对实体类的引用,来生产Java类对象,从而实现生产和管理Bean 。

2.Bean的属性

Bean的配置使用xml配置,XML配置文件的根元素是,中包含了多个子元素,每一个子元素定义了一个Bean,并描述了该Bean如何被装配到Spring容器中。关于元素的常用属性如下表所示:

image-20200520230325929

注意:

id必须是Bean中唯一的,而name可以有多个

3.bean的实例化

在Spring中,要想使用容器中的Bean,也需要实例化Bean。实例化Bean有三种方式,分别为构造器实例化、静态工厂方式实例化和实例工厂方式实例化(其中最常用的是构造器实例化)。

构造器实例化

最普通的实例化

静态工厂方式实例化
1.创建对应的静态实例工厂
import com.wgz.spring.entity.Student;

public class StaticBeanFactory {

    public static Student createStudent(){
        return new Student();
    }
}

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



    <bean id="student" class="com.wgz.spring.instance.staticfactory.StaticBeanFactory" factory-method="createStudent"></bean>


</beans>
3.测试
public class Test {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:factory/staticbeanfactory.xml");

        Student student =   applicationContext.getBean(Student.class);

        System.out.println(student);

    }
}
实例工厂方式实例化
1.创建实例工厂
public class BeanFactory {

    public BeanFactory(){
        System.out.println("静态工厂实例化");
    }


    public Student createStudent(){
        return new Student();
    }


}

2.创建配置文件beanfactory.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--实例工厂-->
    <bean id="factoryBean" class="com.wgz.spring.instance.factory.BeanFactory">

    </bean>

    <!--引用实例工厂-->
    <bean id="student" factory-bean="factoryBean" factory-method="createStudent"></bean>

</beans>
3.测试
public class Test {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:factory/beanfactory.xml");

        Student student =   applicationContext.getBean(Student.class);
        System.out.println(student);
    }

}

4.bean的做用域

bean的作用域有7种,最常用的有单例和原型

image-20200520232155741

  • singleton

singleton是Spring容器默认的作用域,当Bean的作用域为singleton时,Spring容器就只会存在一个共享的Bean实例。singleton作用域对于无会话状态的Bean(如Dao 组件、Service组件)来说,是最理想的选择。

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


    <!-- 声明一个 id 为student的 实例 -->
    <bean id="student1" class="com.wgz.spring.entity.Student" scope="singleton" >

    </bean>

    <bean id="student2" class="com.wgz.spring.entity.Student" scope="prototype">

    </bean>
</beans>
2.测试
public class ScopeTest {

    public static void main(String[] args) {

        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:scopebean.xml");

        Student student1_a = (Student) applicationContext.getBean("student1");
        Student student1_b = (Student) applicationContext.getBean("student1");

        // 单例的作用域对象得到 只有一个
        System.out.println("student1_a == student1_b:"+(student1_a==student1_b));

        // 原型的作用域 得到的对象 有多个
        Student student2_a = (Student) applicationContext.getBean("student2");
        Student student2_b = (Student) applicationContext.getBean("student2");

        System.out.println("student2_a == student2_b:"+(student2_a==student2_b));



    }


}

5.bean的生命周期

Spring容器可以管理Bean部分作用域的生命周期。有关说明具体如下

  • singleton

Spring容器可以管理singleton作用域的Bean的生命周期,在此作用域下,Spring能够精确的知道该Bean何时被创建,何时初始化完成,以及何时被销毁。

  • prototype

prototype作用域的Bean,Spring只负责创建,当容器创建了Bean实例后,Bean的实例就交给客户端代码来管理,Spring容器将不再跟踪其生命周期。

示例:

1.在Student增加声明周期相关的方法

 /**
     * 初始化方法
     */
    public void  init(){

        System.out.println("对象初始化");
    }

    /**
     * 销毁方法
     */
    public void destroy(){
        System.out.println("对象销毁了");
    }

2.创建lifebean.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <!-- 声明一个 id 为student的 实例 -->
    <bean id="student1" class="com.wgz.spring.entity.Student" scope="singleton" init-method="init" destroy-method="destroy">

    </bean>

    <bean id="student2" class="com.wgz.spring.entity.Student" scope="prototype" init-method="init" destroy-method="destroy">

    </bean>
</beans>

3.测试

import com.wgz.spring.entity.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class LifeTest {

    public static void main(String[] args) {

        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("lifebean.xml");

        Student student1_a = (Student) applicationContext.getBean("student1");



        // 原型的作用域
        Student student2_a = (Student) applicationContext.getBean("student2");


        applicationContext.destroy();

    }

}

6.什么是Bean的装配?

Bean的装配可以理解为依赖关系注入,Bean的4装配方式就是Bean依赖注入的方式。

Spring容器支持多种形式的Bean的装配方式,如

1、基于XML的装配、

2、基于注解(Annotation)的装配

3、自动装配(其中最常用的是基于注解的装配)

1基于XML的装配

  • 设值注入

使用setter方法注入,必备条件:

Bean类必须有一个无参构造方法,Bean类必须为属性提供setter方法

xml配置

    <bean id="student1" class="com.wgz.spring.entity.Student">
        <property name="name" value="xiaoming"/>
        <property name="age" value="18"/>
        <property name="id" value="10"/>
        <property name="sex" value="F"></property>
        <property name="courseList" >
            <list>
                <value>"语文"</value>
                <value>"数学"</value>
            </list>
        </property>

    </bean>
  • 构造方法注入

对应构造方法的每一参数,index为下标,从0开始

 
 <bean id="student2" class="com.wgz.spring.entity.Student">
        <constructor-arg index="0" value="10"></constructor-arg>
        <constructor-arg index="1" value="xiaoming"></constructor-arg>
        <constructor-arg index="2" value="18"></constructor-arg>

        <constructor-arg index="3" value="F"></constructor-arg>
        <constructor-arg index="4">
                <list>
                    <value>"语文"</value>
                    <value>"数学"</value>
                </list>
        </constructor-arg>
    </bean>

2.基于Annotation的装配

基于XML的装配可能会导致XML配置文件过于臃肿,给后续的维护和升级带来一定的困难。为此,Spring提供了对Annotation(注解)技术的全面支持。

注入的注解

@Autowired:用于对Bean的属性变量、属性的setter方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动配置工作。

@Qualifier:与@Autowired注解配合使用,

会将默认的按Bean类型装配修改为按Bean的实例名称装配,

Bean的实例名称由@Qualifier注解的参数指定。

@Resource:其作用与Autowired一样。@Resource中有两个重要属性:name和type。Spring将name属性解析为Bean实例名称,type属性解析为Bean实例类型。

//    @Autowired  // 根据类型进行注入若有,多个类型的实例,需要配合   @Qualifier("studentDaoImpl2")
//    @Qualifier("studentDaoImpl2")

    @Resource()  // 默认按照注解的字段名称进行装配,  若没有找到根据类型装配,如果对应类型的实例有多个需要限定
    private StudentDao studentDao ;
生成实例的注解

@Component:用于描述Spring中的Bean,它是一个泛化的概念,仅仅表示一个组件。

@Repository:用于将数据访问层(DAO)的类标识为Spring中的Bean 。

@Service:用于将业务层(Service)的类标识为Spring中的Bean。

@Controller:用于将控制层(Controller)的类标识为Spring中的Bean 。

1.半自动注解装配 annotation-config

开启注解处理器 @Autowired @ Resource 、@ PostConstruct、@ PreDestroy 相关注解注入生效

        <!--开启注解处理器    @Autowired    @Resource 相关注解注入  -->
       <context:annotation-config></context:annotation-config>
        <bean id="studentDaoImpl" class="com.wgz.spring.dao.impl.StudentDaoImpl"></bean>
        <bean id="studentDaoImpl2" class="com.wgz.spring.dao.impl.StudentDaoImpl"></bean>


        <bean id="studentServiceImpl" class="com.wgz.spring.service.StudentServiceImpl"></bean>
        <bean id="studentController" class="com.wgz.spring.controller.StudentController"></bean>

2.自动注解 context:component-scan

扫描 当前包下面的注解@Component @Controller @Service @Repository,生成实例,并装配 @Autowired @Resource

<!-- 扫描 当前包下面的注解 @Controller @Service @Repository,生成实例并装配  @Autowired    @Resource -->
<context:component-scan base-package="com.wgz.spring"/>
总结:

context:component-scan 具有annotation-config的功能,并且能够申城实例

<?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.xsd
         http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd">


        <!--开启注解处理器    @Autowired    @     -->
<!--        <context:annotation-config></context:annotation-config>
        <bean id="studentDaoImpl" class="com.wgz.spring.dao.impl.StudentDaoImpl"></bean>
        <bean id="studentDaoImpl2" class="com.wgz.spring.dao.impl.StudentDaoImpl"></bean>


        <bean id="studentServiceImpl" class="com.wgz.spring.service.StudentServiceImpl"></bean>
        <bean id="studentController" class="com.wgz.spring.controller.StudentController"></bean>-->

        <!-- 扫描 当前包下面的注解 @Controller @Service @Repository,生成实例并装配  @Autowired    @Resource -->
        <context:component-scan base-package="com.wgz.spring"/>



</beans>

3.基于xml的自动装配

所谓自动装配,就是将一个Bean自动的注入到到其他Bean的Property中。 Spring的元素中包含一个autowire属性,我们可以通过设置autowire的属性值来自动装配Bean。autowire属性有5个值,其值及说明下表所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rstneMvC-1603530033860)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20200522123456580.png)]

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 声明一个 id 为studentDao的 实例 -->
    <bean id="studentDao" class="com.wgz.spring.dao.impl.StudentDaoImpl">

    </bean>
    <!--
    autowire="byType"  此时容器中只能有一个对象
    autowire="byName" 使用 studentService内部的变量作为id 去获取
    autowire="constructor"  必须有构造函数
     -->

    <bean id="studentService" class="com.wgz.spring.service.StudentServiceImpl" autowire="constructor">

    </bean>

</beans>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值