SpringIOC(DI)依赖注入

一、Spring IOC手动注入(装配)

1.set方法注入(掌握)
1.1属性字段提供set方法
public class UserService {

    /*set手动注入*/
    //注入UserDao 提供set方法
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    //注入SxtStudent
    private SxtStudent sxtStudent;
    public void setSxtStudent(SxtStudent sxtStudent) {
        this.sxtStudent = sxtStudent;
    }
    //常对象String 注入set
    private String str;
    public void setStr(String str) {
        this.str = str;
    }
    //基本类型 Integer
    private Integer id;
    public void setId(Integer id) {
        this.id = id;
    }
    //list集合
    private List<String> list;
    public void setList(List<String> list) {
        this.list = list;
    }
    //遍历list的值
    public void printList(){
        list.forEach(s -> System.out.println(s));
    }
    //set集合注入
    private Set<String> set;
    public void setSet(Set<String> set) {
        this.set = set;
    }
    //遍历set集合
    public void printSet(){
        set.forEach(s -> {
            System.out.println(s);
        });
    }
    //map
    private Map<String,String> map;
    public void setMap(Map<String, String> map) {
        this.map = map;
    }
    //遍历map
    public void printMap(){
        map.forEach((k,v)->{
            System.out.println(k+","+v);
        });
    }
    // Properties set注入(提供set方法)
    private Properties properties;
    public void setProperties(Properties properties) {
        this.properties = properties;
    }
    // Properties输出
    public  void printProperties(){
        properties.forEach((k,v) -> System.out.println(k + ","+ v ));
    }

    public void test(){

        System.out.println("UserService test.......");

        //调用userDao
        userDao.test();

        //调用sxtStudent
        sxtStudent.test();

        //调用对象String
        System.out.println("str:"+str);

        //基本类型 Integer
        System.out.println("编号:"+id);

        //list集合
        printList();

        //set集合
        printSet();

        //map集合
        printMap();

        //properties
        printProperties();
    }
}

1.2配置文件的bean标签设置property标签
<?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="userService" class="com.shsxt.service.UserService">
                <!--bean对象注入-->
                <property name="userDao" ref="userDao"/>
                <property name="sxtStudent" ref="sxtStudent"/>
                <!--常用对象注入-->
                <property name="str" value="Hello Spring"/>
                <!--基本类型注入-->
                <property name="id" value="100"/>
                <!--list集合注入-->
                <property name="list">
                        <list>
                                <value>江西</value>
                                <value>上海</value>
                                <value>浙江</value>
                        </list>
                </property>
                <!--set集合注入-->
                <property name="set">
                        <set>
                                <value>南昌</value>
                                <value>浦东区</value>
                                <value>杭州</value>
                        </set>
                </property>
                <!--map注入-->
                <property name="map">
                        <map>
                                <entry>
                                        <key><value>邓紫棋</value></key>
                                        <value>平凡天使</value>
                                </entry>
                                <entry>
                                        <key><value>花花</value></key>
                                        <value>我们</value>
                                </entry>
                                <entry>
                                        <key><value>易烊千玺</value></key>
                                        <value>朋友请听好</value>
                                </entry>
                        </map>
                </property>
                <!--Properties注入-->
               <property name="properties">
                        <props>
                                <prop key="1">歌手</prop>
                                <prop key="2">演员</prop>
                                <prop key="3">舞蹈</prop>
                        </props>
               </property>
        </bean>

        <bean id="userDao" class="com.shsxt.dao.UserDao"></bean>
        <bean id="sxtStudent" class="com.shsxt.dao.SxtStudent"></bean>

</beans>
1.3加载资源
public class Test01 {
    public static void main(String[] args) {
        //获取上下文
        BeanFactory factory=new ClassPathXmlApplicationContext("spring.xml");
        //通过getBean获得实例化好的对象
        UserService userService= (UserService) factory.getBean("userService");
        //调用方法
        userService.test();
    }
}
2.构造器注入
2.1提供带参构造器
public class UserService02 {

    /*构造器注入*/
    private UserDao02 userDao02;
    private SxtStudent02 sxtStudent02;
    private String name;


    public UserService02(UserDao02 userDao02) {
        this.userDao02 = userDao02;
    }


    public UserService02(UserDao02 userDao02, SxtStudent02 sxtStudent02) {
        this.userDao02 = userDao02;
        this.sxtStudent02 = sxtStudent02;
    }

    public UserService02(UserDao02 userDao02, SxtStudent02 sxtStudent02, String name) {
        this.userDao02 = userDao02;
        this.sxtStudent02 = sxtStudent02;
        this.name = name;
    }

    public void test(){
        System.out.println("UserService02 test......");
        userDao02.test();
        sxtStudent02.test();
        System.out.println("名字:"+name);
    }
}
2.2XML配置
<?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="userService02" class="com.shsxt.service.UserService02">
                 <constructor-arg name="userDao02" ref="userDao02"/>
                <constructor-arg name="sxtStudent02" ref="sxtStudent02"/>
                <constructor-arg name="name" value="张三"/>
        </bean>

      <bean id="userDao02" class="com.shsxt.dao.UserDao02"></bean>
        <bean id="sxtStudent02" class="com.shsxt.dao.SxtStudent02"></bean>
</beans>
2.3加载资源
public class Test02 {
    public static void main(String[] args) {
        //获取上下文
        BeanFactory factory=new ClassPathXmlApplicationContext("spring02.xml");
        //通过getBean获得实例化好的对象
        UserService02 userService02= (UserService02) factory.getBean("userService02");
        //调用方法
        userService02.test();
    }
}
构造器可能出现的问题:循环依赖

带参构造器

public class AccountService {

    private RoleService roleService;

   public AccountService(RoleService roleService) {
        this.roleService = roleService;
    }

    public void  test() {
        System.out.println("AccountService Test...");
    }
}

public class RoleService {

    private AccountService accountService;

   public RoleService(AccountService accountService) {
        this.accountService = accountService;
    }

    public void  test() {
        System.out.println("RoleService Test...");
    }
}

xml配置

 <!--
        如果多个bean对象中互相注入,则会出现循环依赖的问题
        可以通过set方法注入解决
    -->
<bean id="accountService" class="com.shsxt.service.AccountService">
    <constructor-arg name="roleService" ref="roleService"/>
</bean>

<bean id="roleService" class="com.shsxt.service.RoleService">
    <constructor-arg name="accountService" ref="accountService"/>
</bean>
如何解决:将构造器注入改为set方法注入
public class AccountService {

    private RoleService roleService;

   /* public AccountService(RoleService roleService) {
        this.roleService = roleService;
    }*/

    public void setRoleService(RoleService roleService) {
        this.roleService = roleService;
    }

    public void  test() {
        System.out.println("AccountService Test...");
    }
}

public class RoleService {

    private AccountService accountService;

   /* public RoleService(AccountService accountService) {
        this.accountService = accountService;
    }*/

    public void setAccountService(AccountService accountService) {
        this.accountService = accountService;
    }

    public void  test() {
        System.out.println("RoleService Test...");
    }
}

xml配置

<!--修改为set方法注入-->
    <bean id="accountService" class="com.shsxt.service.AccountService">
        <property name="roleService" ref="roleService"/>
    </bean>

    <bean id="roleService" class="com.shsxt.service.RoleService">
       <property name="accountService" ref="accountService"/>
    </bean>
3.静态工厂注入(了解)
3.1定义工厂类
public class StaticFactory {
	//定义静态方法
    public static Car createCar(){
        return new Car();
    }
}

3.2在配置文件中设置bean标签,指定工厂对象并设置对应的方法
 <!--静态工厂注入-->
    <bean id="car" class="com.shsxt.factory.StaticFactory" factory-method="createCar"></bean>
3.3加载资源
public class Test04 {
    public static void main(String[] args) {
        BeanFactory factory=new ClassPathXmlApplicationContext("spring03.xml");
        Car car = (Car) factory.getBean("car");
        car.test();
    }
}
4.实例化工厂注入(了解)
4.1定义工厂类
public class InstanceFactory {
    public Car create(){
        return new Car();
    }
}

4.2声明工厂bean标签,声明bean对象,指明工厂对象和工厂方法
<!--实例化工厂注入-->
    <bean id="instanceFactory" class="com.shsxt.factory.InstanceFactory"></bean>
    <bean id="car" factory-bean="instanceFactory" factory-method="create"></bean>
4.3加载资源
public class Test04 {
    public static void main(String[] args) {
        BeanFactory factory=new ClassPathXmlApplicationContext("spring03.xml");
        Car car = (Car) factory.getBean("car");
        car.test();
    }
}

二、Spring IOC自动注入(装配)

1.准备环境(修改配置文件)
  <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
       https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
      
  <beans>
2.开启自动化注入
<!--开启自动化装配(注入)-->
<context:annotation-config/>
<bean id="userService" class="com.shsxt.service.UserService"></bean>
3.给注入的bean对象添加注解
@Resource注解
 @Resource注解实现自动注入(反射)
    1、默认根据属性字段名称查找对应的bean对象 (属性字段的名称与bean标签的id属性值相等)
    2、如果属性字段名称未找到,则会通过类型(Class类型)查找
    3、属性可以提供set方法,也可以不提供set方法
    4、注解可以声明在属性级别 或 set方法级别
    5@Resource可以设置name属性,name属性值必须与bean的id属性值一致;如果设置了name属性值,就只会按照name属性值查找bean对象
    6、当注入接口时,如果接口只有一个实现则正常实例化;如果接口存在多个实现,则需要使用name属性指定需要被实例化的bean对象
   
public class UserService {	
	//自动注入
    @Resource
    private UserDao userDao;
    //自动注入
    //@Resource(name="userDao")
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }*/
	public void test(){
        System.out.println("UserService test.......");
        userDao.test();
    }
}

加载资源

public class Test01 {
    public static void main(String[] args) {
        BeanFactory factory=new ClassPathXmlApplicationContext("spring.xml");
        UserService userService= (UserService) factory.getBean("userService");
        userService.test();
    }
}
@AutoWired注解
@Autowired注解实现自动化注入:
  1、默认通过类型(Class类型)查找bean对象   与属性字段的名称无关
  2、属性可以提供set方法,也可以不提供set方法
  3、注解可以声明在属性级别 或 set方法级别
  4、可以添加@Qualifier结合使用,通过value属性值查找beam对象(value属性值必须要设置,且值要与bwan标签的id属性值对应)
@Autowired
@Qualifier(value = "accountDao")
private AccountDao accountDao;

public void setAccountDao(AccountDao accountDao) {
    this.accountDao = accountDao;
}

三、Spring IOC扫描器

过程

Spring IOC扫描器
        作用:bean对象统一进行管理,简化开发配置,提高开发效率
        1、设置自动化扫描的范围
                   如果bean对象未在指定包范围,即使声明另外注解,也无法实例化
       2、使用指定的注解(声明在类级别)  bean对象的id属性默认是 类的首字母小写
                     Dao层:
                         @Repository
                     Service层:
                         @Service
                     Controller层:
                         @Controller
                     任意类:
                          @Component
              注:开发过程中建议按照指定规则声明注解
1.设置自动化扫描的范围
<!--设置自动化扫描的范围-->
        <context:component-scan base-package="com.shsxt"/>
2.使用特定的注解
@Controller
public class ResourceController {

    @Autowired
    private ResourceService resourceService;

    public  void  test() {
        System.out.println("ResourceController...");
        resourceService.test();
    }
}
@Service
public class ResourceService {

    @Resource
    private ResourceDao resourceDao;

    public  void  test() {
        System.out.println("ResourceService...");
        resourceDao.test();
    }
}
@Repository
public class ResourceDao {

    public void  test() {
        System.out.println("ResourceDao...");
    }
}
@Component
public class PropertyUtils {
    public void test(){
        System.out.println("PropertyUtils...");
    }
}
3.资源加载
public class Test03 {
    public static void main(String[] args) {
        BeanFactory factory=new ClassPathXmlApplicationContext("spring3.xml");
        
        ResourceDao resourceDao= (ResourceDao) factory.getBean("resourceDao");
        resourceDao.test();

       ResourceService resourceService= (ResourceService) factory.getBean("resourceService");
        resourceService.test();

        ResourceController resourceController= (ResourceController) factory.getBean("resourceController");
        resourceController.test();

        ResourceUtil resourceUtil= (ResourceUtil) factory.getBean("resourceUtil");
        resourceUtil.test();

    }
}

四、Spring IOC扫描器实现用户登录

Controller层
public class UserController {

    @Resource
    private UserService userService;
    /**
     * 登录界面
     *      接收参数,模拟数据
     *      调用UserService层方法,返回resultInfo对象
     * @param uname
     * @param upwd
     */
    public void Login(String uname,String upwd){
        //调用service层方法
        ResultInfo resultInfo=userService.loginService(uname,upwd);
        System.out.println("显示信息:"+resultInfo);
    }
}
Service层
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service

public class UserService {

    @Resource
    private UserDao userDao;
    /**
     * 1.判断参数是否为空
     *      为空,设置状态码和原因,返回resultInfo对象
     * 2.根据name查询Dao层方法,返回User对象
     * 3.判断用户是否为空
     *      为空,设置状态码和原因,返回resultInfo对象
     * 4.判断密码和数据库密码是否相等
     *      不相等,设置状态码和原因,返回resultInfo对象
     * 5.登录成功,返回resultInfo对象
     *
     * @param uname
     * @param upwd
     * @return
     */
    public ResultInfo loginService(String uname, String upwd) {
        ResultInfo resultInfo=new ResultInfo();
        //判断参数是否为空
        if(StringUtils.isBlank(uname)){
            //状态码和原因
            resultInfo.setCode(0);
            resultInfo.setMsg("用户名不能为空!");
            return resultInfo;
        }
        if(StringUtils.isBlank(upwd)){
            //状态码和原因
            resultInfo.setCode(0);
            resultInfo.setMsg("密码不能为空!");
            return resultInfo;
        }
        //调用Dao层方法,返回user对象
        User user=userDao.loginDao(uname);
        //判断用户是否为空
        if(user==null){
            //状态码和原因
            resultInfo.setCode(0);
            resultInfo.setMsg("用户不存在!");
            return resultInfo;
        }
        //判断密码是否相等
        if(!(user.getUpwd().equals(upwd))){
            //状态码和原因
            resultInfo.setCode(0);
            resultInfo.setMsg("密码输入错误!");
        }else{
            //状态码
            resultInfo.setCode(1);
            resultInfo.setMsg("success");
            resultInfo.setResult(user);
        }
        return resultInfo;
    }
}
Dao层
@Repository
public class UserDao {

    private Map<String,Object>map;
    //模拟数据库数据
    public UserDao(){
        map=new HashMap<>();
        User user=new User();
        user.setUid(1);
        user.setUname("admin");
        user.setUpwd("123456");
        map.put("admin",user);
    }

    public User loginDao(String uname) {
        return (User) map.get(uname);
    }
}

public class ResultInfo {

    private Integer code;//状态码
    private String msg;//提示信息
    private Object result;//返回对象可以是list map 对象String JavaBean

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getResult() {
        return result;
    }

    public void setResult(Object result) {
        this.result = result;
    }

    @Override
    public String toString() {
        return "ResultInfo{" +
                "code=" + code +
                ", msg='" + msg + '\'' +
                ", result=" + result +
                '}';
    }
}


public class User {
    private Integer uid;
    private String uname;
    private String upwd;

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public String getUname() {
        return uname;
    }

    public void setUname(String uname) {
        this.uname = uname;
    }

    public String getUpwd() {
        return upwd;
    }

    public void setUpwd(String upwd) {
        this.upwd = upwd;
    }

    @Override
    public String toString() {
        return "User{" +
                "uid=" + uid +
                ", uname='" + uname + '\'' +
                ", upwd='" + upwd + '\'' +
                '}';
    }
}

xml配置
<!--开启自动化扫描范围-->
<context:component-scan base-package="com.shsxt"/>
资源加载
public class TestDemo {
    public static void main(String[] args) {
        BeanFactory factory=new ClassPathXmlApplicationContext("spring.xml");
        UserController userController= (UserController) factory.getBean("userController");
        userController.Login("admin","123456");
    }
}

五、Bean的作用域和生命周期

1.bean的作用域
​ 实现
Bean的作用域
    scope:
         设置bean对象的作用域(singleton或prototype),默认singleton
    singleton单例作用域
          Spring IOC容器在实例化对象时,会将单例对象设置到单例缓存池中

       /*  lazy-init属性(懒加载)
                 如果为false,则在IOC容器启动时会实例化bean对象,默认false
                 如果为true,则IOC容器启动时不会实例化Bean对象,在使用bean对象时才会实例化

       lazy-init设置为false有什么好处?
           1、可以提前发现潜在的配置问题
           2、Bean 对象存在于缓存中,使用时不用再去实例化bean,加快程序运行效率  

         什么对象适合作为单例对象?
                 无状态的对象 (不存在会改变对象状态的成员变量)
                         controller层、service层、dao层
          */

  prototype原型作用域
          Spring IOC容器在实例化对象时,不会将单例对象设置到单例缓存池中,每一次实例都是一个新的对象

  Web作用域
         request作用域
                 在每一次请求实例化一个bean对象
         session作用域
                 在每一次有效会话实例化一个bean对象
         globalSession作用域
                 类似于session
xml配置
  <!-- singleton单例作用域:lazy-init懒加载-->

    <bean id="resourceService" class="com.shsxt.service.ResourceService" lazy-init="false"></bean>

<!--prototype原型作用域-->

        <bean id="resourceService" class="com.shsxt.service.ResourceService" scope="prototype"></bean>

2.bean的生命周期
Bean的生命周期
        Bean的生命周期包括Bean的定义、初始化、使用和销毁4个阶段
        定义
                通过配置文档的方式来定义Bean的
        初始化
                默认在IOC容器加载时,就实例化对象
                Spring bean 初始化有两种方式:
                        I.在配置文档中通过指定 init-method 属性来完成。
                        II.实现org.springframework.beans.factory.InitializingBean接口。
        使用
              I.使用BeanFactory
              II.使用ApplicationContext
        销毁
             步骤一:实现销毁方式(Spring容器会维护bean对象的管理,可以指定bean对象的销毁所要执行的方法)
                  <bean id="userServiceImpl"class="com.shsxt.service.impl.UserServiceImpl" init-method="init" destroy-method="destroy">
                        </bean>

            步骤二:过AbstractApplicationContext 对象,调用其close方法实现bean的销毁过程。
                AbstractApplicationContext ctx=new ClassPathXmlApplicationContext("Spring-application.xml");
                        ctx.close();
public class RoleService implements InitializingBean {
    /*初始化*/
    public RoleService(){
        System.out.println("RoleService被初始化。。。。。。");
    }
    public void test(){
        System.out.println("RoleService........");
    }

    public void init(){
        System.out.println("RoleService init........");
    }

    public void destroy() {
        System.out.println("RoleService destroy...");
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("RoleService init afterPropertiesSet.....");
    }
}

xml配置

  <!--Bean生命周期-->
      <bean id="roleService" class="com.shsxt.service.RoleService"></bean>

        <!--init初始化-->
       <bean id="roleService" class="com.shsxt.service.RoleService" init-method="init"></bean>

        <!--实现org.springframework.beans.factory.InitializingBean接口。-->
       <bean id="roleService" class="com.shsxt.service.RoleService" init-method="init"></bean>

        <!--销毁-->
        <bean id="roleService" class="com.shsxt.service.RoleService" destroy-method="destroy"></bean>

 //销毁
// 通过AbstractApplicationContext 对象,调用其close方法实现bean的销毁过程
        AbstractApplicationContext ct=new ClassPathXmlApplicationContext("spring4.xml");
        System.out.println("销毁前:"+ct.getBean("roleService"));
        ct.close();
        System.out.println("销毁后:" + ct.getBean("roleService"));

六、定时任务

第一种:
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"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/task
       http://www.springframework.org/schema/task/spring-task.xsd">	
	<!--开启自动化扫描范围-->
	<context:component-scan base-package="com.shsxt"/>

    <task:scheduled-tasks>
        <!-- 每个两秒执行一次任务 -->
        <task:scheduled ref="taskSchedule" method="job1" cron="0/2 * * * * ?"/>

        <!-- 每隔五秒执行一次任务 -->
        <task:scheduled ref="taskSchedule" method="job2" cron="0/5 * * * * ?"/>

        <!-- 多个定时任务 在这里配置 -->
    </task:scheduled-tasks>
</beans>
@Component
public class TaskSchedule {
    public void job1(){
        System.out.println("任务 1:"+new SimpleDateFormat("yyyy-MM-dd  hh:mm:ss").format(new Date()));
    }
    public void job2(){
        System.out.println("任务 2:"+new SimpleDateFormat("yyyy-MM-dd  hh:mm:ss").format(new Date()));
    }
}

加载资源

public class TestDemo {
    public static void main(String[] args) {
       BeanFactory factory = new ClassPathXmlApplicationContext("spring.xml");
      TaskSchedule taskSchedule = (TaskSchedule) factory.getBean("taskSchedule");
    }
}
第二种:
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"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/task
       http://www.springframework.org/schema/task/spring-task.xsd">

    <context:component-scan base-package="com.shsxt"/>
    <!--配置定时任务驱动-->
    <task:annotation-driven />
</beans>

@Component
public class TaskSchedule02 {
    @Scheduled(cron="0/2 * * * * ?")
    public void job1(){
        System.out.println("任务 1:"+new SimpleDateFormat("yyyy-MM-dd  hh:mm:ss").format(new Date()));
    }
    @Scheduled(cron = "0/5 * * * * ?")
    public void job2(){
        System.out.println("任务 2:"+new SimpleDateFormat("yyyy-MM-dd  hh:mm:ss").format(new Date()));
    }

}
加载资源
public class TestDemo {
    public static void main(String[] args) {

      BeanFactory factory = new ClassPathXmlApplicationContext("spring2.xml");
        TaskSchedule taskSchedule02 = (TaskSchedule) factory.getBean("taskSchedule02");

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值