Spring(二)基于 基于注解的IOC以及IOC的案例

基于注解的IOC以及IOC的案例

1 spring中IOC的常用注解

2 案例使用XML方式和注解方式实现单表的CRUD操作(持久层技术选择:dbutils)

3 改造基于注解的IOC案例,使用纯注解的方式实现

4 spring的一些新注解使用

5 spring和Junit整合

基于注解的IOC配置

对于账户的业务层实现类
曾经XML的配置:

 <bean id="accountService" class="com.tju.service.impl.AccountServiceImpl"
  scope=""  init-method="" destroy-method="">
 <property name=""  value="" | ref=""></property>
 </bean>

用于创建对象的注解:
他们的作用就和在XML配置文件中编写一个标签实现的功能是一样的

  • Component:
    • 作用:用于把当前类对象存入spring容器中
      属性:
    • value:用于指定bean的id。当我们不写时,它的默认值是当前类名,且首字母改小写。

示例:

    @Component()  //什么都不写默认id是当前类名,且首字母小写
   @Component(value="accountServic")  //可以自己指定id
   @Component("accountServic")  //由于注解只有一个属性,且属性名是value,所以可以省略属性名
public class AccountServiceImpl implements IAccountService {

 ............
}

注意:还少一步配置
测试时
ApplicationContext ac = new ClassPathXmlApplicationContext(“bean.xml”);
读取配置文件创建核心容器时找不到bean id无法创建对象(使用注解时通过配置文件就能找到),要在配置文件中指定注解的位置

bean.xml 查阅spring框架文档找到context约束,配置扫描包上的注解

<?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.xsd">

    <!--告知spring在创建容器时要扫描的包(扫描包上类的注解),配置所需要的标签不是在beans的约束中,而是一个名称为 context名称空间和约束中-->
    <context:component-scan base-package="com.tju"></context:component-scan>
</beans>

由Componen衍生的注解

  • Controller:一般用在表现层
  • Service:一般用在业务层
  • Repository:一般用在持久层
    以上三个注解他们的作用和属性与Component是一模一样。
    他们三个是spring框架为我们提供明确的三层使用的注解,使我们的三层对象更加清晰

用于注入数据的注解
他们的作用就和在xml配置文件中的bean标签中写一个标签的作用是一样的

  • Autowired:
    • 作用:自动按照类型注入。只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功
      • 如果ioc容器中没有任何bean的类型和要注入的变量类型匹配,则报错。
      • 如果Ioc容器中有多个类型匹配时
    • 出现位置:
      可以是变量上,也可以是方法上
    • 细节:
      在使用注解注入时,set方法就不是必须的了。

示例
注入成员变量 accountDao

@Service("accountService")
public class AccountServiceImpl implements IAccountService {

      @Autowired
    private IAccountDao accountDao;

    public void  saveAccount(){
        accountDao.saveAccount();
    }
}

IAccountDao 对象被注入成功

原理
spring的IOC容器:Map结构 Map的key是一个String类型(对象的id),Map的value是一个object类型(对象类型)

容器中有哪些对象呢?

在Service实现类上有一个注解,所以容器中肯定有记录

@Service("accountService")
public class AccountServiceImpl implements IAccountService

在Dao实现类上有一个注解,所以容器中肯定有记录

@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao
{
    public  void saveAccount(){
        System.out.println("保存了账户");
    }
}

要注入的对象是谁?
Service实现类对象 AccountServiceImpl上的一个成员变量

@Autowired 自动按照类型注入
private(访问修饰符) IAccountDao(数据类型) accountDao(变量名称)=null(数据);

要注入的对象从Spring的IOC容器中通过自己(要注入对象)的数据类型遍历Map的value(也就是先比较对象类型,不管key)
如果value(容器中)和数据类型匹配(AccountDaoImpl implements IAccountDao和IAccountDao),就可以注入成功,找不到匹配则注入失败
要注入的对象就有值了

如果有多个匹配
还有一个Dao接口的实现类,IOC容器中多了一个value为IAccountDao的记录

@Repository("accountDao2")
public class AccountDaoImpl2  implements IAccountDao {

    public  void saveAccount(){

        System.out.println("保存了账户2222222222222");
    }
}

注入对象再到IOC容器中去匹配时,不止有一个匹配,有多个接口的实现类可以匹配
1 现根据注入对象的数据类型到IOC容器中比较value,圈定一个范围
2 再根据注入对象的变量名称到IOC容器圈定的范围中比较key(就是原来的bean-id)
如果有唯一 一样的数据类型(value)+bean id(key)则注入成功

自动按照类型注入
图=============================

Qualifier:

  • 作用:在按照类型中注入的基础之上再按照名称注入。它在给类成员注入时不能单独使用必须和@Autowired配合。但是在给方法参数注入时可以(稍后我们讲)
  • 属性:
    value:用于指定注入bean的id。
@Service("accountService")
public class AccountServiceImpl implements IAccountService {

      @Autowired
     @Qualifier("accountDao1")
    private IAccountDao accountDao;

    public void  saveAccount(){
        accountDao.saveAccount();
    }
}

Resource

  • 作用:直接按照bean的id注入。它可以独立使用
  • 属性:
    name:用于指定bean的id。
@Service("accountService")
public class AccountServiceImpl implements IAccountService {

    @Resource(name = "accountDao2")
    private IAccountDao accountDao;

    public void  saveAccount(){
        accountDao.saveAccount();
    }
}

以上三个注入都只能注入bean类型的数据,而基本类型和String类型无法使用上述注解实现。
另外,集合类型的注入只能通过XML来实现。

用于注入数据的注解
  • Value
    • 作用:用于注入基本类型和String类型的数据
    • 属性:
      • value:用于指定数据的值。它可以使用spring中SpEL(也就是spring的el表达式)
        SpEL的写法:${表达式}

改变作用范围以及和生命周期相关的注解

用于改变作用范围的

他们的作用就和在bean标签中使用scope属性实现的功能是一样的

  • Scope
    • 作用:用于指定bean的作用范围
    • 属性:
      • value:指定范围的取值。常用取值:singleton prototype,不写默认单例
@Scope("prototype")
public class AccountServiceImpl implements IAccountService {
.............
}
和生命周期相关的注解 了解

他们的作用就和在bean标签中使用init-method和destroy-method的作用是一样的

  • PreDestroy
    作用:用于指定销毁方法
  • PostConstruct
    作用:用于指定初始化方法
public class AccountServiceImpl implements IAccountService {


    @Resource(name = "accountDao2")
    private IAccountDao accountDao = null;

    @PostConstruct
    public void  init(){
        System.out.println("初始化方法执行了");
    }

    @PreDestroy
    public void  destroy(){
        System.out.println("销毁方法执行了");
    }

    public void  saveAccount(){
        accountDao.saveAccount();
    }
}

测试

  //1.获取核心容器对象
    ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
    //2.根据id获取Bean对象
    IAccountService as  = (IAccountService)ac.getBean("accountService");

    as.saveAccount();
    ac.close();

结果
初始化方法执行了
保存了账户2222222222222
销毁方法执行了

基于XML的IOC案例

在这里插入图片描述

IAccountService业务层接口

/**
 * 账户的业务层接口
 */
public interface IAccountService {

    /**
     * 查询所有
     * @return
     */
    List<Account> findAllAccount();


    /**
     * 查询一个
     * @return
     */
   Account findAccountById(Integer accountid);


    /**
     * 保存
     * @param account
     */
    void saveAccount(Account account);

    /**
     * 更新
     * @param account
     */
    void updateAccount(Account account);

    /**
     *删除
     * @param account
     */
    void deleteAccount(Account account);
}

AccountServiceImpl业务层实现类

/**
 * 业务层实现类
 */
public class AccountServiceImpl implements IAccountService{


    //业务层是调用持久层的
    private IAccountDao accountDao;

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

    public List<Account> findAllAccount() {
        return accountDao.findAllAccount();
    }

    public Account findAccountById(Integer accountId) {
        return accountDao.findAccountById(accountId);
    }

    public void saveAccount(Account account) {
       accountDao.saveAccount(account);
    }

    public void updateAccount(Account account) {
        accountDao.updateAccount(account);
    }

    public void deleteAccount(Account account) {
        accountDao.deleteAccount(account);

    }
}

持久层接口

public interface IAccountDao {

    /**
     * 查询所有
     * @return
     */
    List<Account> findAllAccount();


    /**
     * 查询一个
     * @return
     */
    Account findAccountById(Integer id);


    /**
     * 保存
     * @param account
     */
    void saveAccount(Account account);

    /**
     * 更新
     * @param account
     */
    void updateAccount(Account account);

    /**
     *删除
     * @param account
     */
    void deleteAccount(Account account);
}

持久层实现类

public class AccountDaoImpl implements IAccountDao {

    private QueryRunner runner;

    public void setRunner(QueryRunner runner) {
        this.runner = runner;
    }

    public List<Account> findAllAccount() {
        try {
            return runner.query("select * from account",new BeanListHandler<Account>(Account.class));
        } catch (SQLException e) {
            throw  new RuntimeException(e);
        }
    }

    public Account findAccountById(Integer accountId) {
        try {
            return runner.query("select * from account where id = ? ",new BeanHandler<Account>(Account.class),accountId);
        } catch (SQLException e) {
            throw  new RuntimeException(e);
        }
    }

    public void saveAccount(Account account) {
        try {
         runner.update("insert into account(name,money) values(?,?)",account.getName(),account.getMoney());
        } catch (SQLException e) {
            throw  new RuntimeException(e);
        }

    }

    public void updateAccount(Account account) {
        try {
            runner.update("update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId());
        } catch (SQLException e) {
            throw  new RuntimeException(e);
        }

    }

    public void deleteAccount(Account account) {
        try {
            runner.update("delete from account  where id=?",account.getId());
        } catch (SQLException e) {
            throw  new RuntimeException(e);
        }

    }
}

Account实体类

public class Account implements Serializable{
    private Integer id;
    private String name;
    private Float money;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public Float getMoney() {
        return money;
    }

    public void setMoney(Float money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", money=" + money +
                '}';
    }
}

核心配置文件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">

    <!--配置Service-->
    <bean id="accountService" class="com.tju.service.impl.AccountServiceImpl">
        <!--注入的是dao对象-->
        <property name="accountDao" ref="accountDao"></property>


    </bean>


        <!--配置Dao对象-->
        <bean id="accountDao" class="com.tju.dao.impl.AccountDaoImpl">
            <!--注入QueryRunner-->
            <property name="runner" ref="runner"></property>
        </bean>

        <!--配置QueryRunner,配置多例对象,每次使用这个对象都是一个创建新的-->
        <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
            <!--注入数据源对象-->
            <constructor-arg name="ds" ref="dataSource"></constructor-arg>
        </bean>

        <!--配置数据源,连接数据库的信息-->
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <!--注入连接数据库的必备信息-->
            <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
            <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/springtest"></property>
            <property name="user" value="root"></property>
            <property name="password" value="xgh961120"></property>
        </bean>
</beans>

测试类

/**
 * 使用junit单元测试我们的配置
 */
public class AccountServiceTest {
    @Test
    public void testFindAll() throws Exception {
        //1获取容器,读取配置文件
        ApplicationContext ac =new ClassPathXmlApplicationContext("bean.xml");
        //2得到业务层对象
        IAccountService as = ac.getBean("accountService", IAccountService.class);
        //3执行方法
        List<Account> accounts = as.findAllAccount();
        for (Account account : accounts) {
            System.out.println(account);

        }

    }
    @Test
    public void testFindOne() throws Exception {
        //1获取容器,读取配置文件
        ApplicationContext ac =new ClassPathXmlApplicationContext("bean.xml");
        //2得到业务层对象
        IAccountService as = ac.getBean("accountService", IAccountService.class);
        //3执行方法
        Account account = as.findAccountById(1);
        System.out.println(account);

    }
    @Test
    public void testSave() throws Exception {
        //1获取容器,读取配置文件
        ApplicationContext ac =new ClassPathXmlApplicationContext("bean.xml");
        //2得到业务层对象
        IAccountService as = ac.getBean("accountService", IAccountService.class);
        //3执行方法
        Account account = new Account();
        account.setName("test");
        account.setMoney(10000f);
        as.saveAccount(account);

    }
    @Test
    public void testUpdate() throws Exception {
        //1获取容器,读取配置文件
        ApplicationContext ac =new ClassPathXmlApplicationContext("bean.xml");
        //2得到业务层对象
        IAccountService as = ac.getBean("accountService", IAccountService.class);
        //3执行方法
        Account account = new Account();
        account.setId(4);
        account.setName("test");
        account.setMoney(2345f);

        as.updateAccount(account);


    } @Test
    public void testDelete() throws Exception {
        //1获取容器,读取配置文件
        ApplicationContext ac =new ClassPathXmlApplicationContext("bean.xml");
        //2得到业务层对象
        IAccountService as = ac.getBean("accountService", IAccountService.class);
        //3执行方法
        Account account = new Account();
        account.setId(4);


        as.deleteAccount(account);

    }

}

注解IOC案例

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

 <!-- 告知spring在创建容器时要扫描的包 -->
    <context:component-scan base-package="com.tju"></context:component-scan>

实现类加注解和成员变量加注解

@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {
@Service("accountService")
public class AccountServiceImpl implements IAccountService{

    @Autowired
    private IAccountDao accountDao;

spring的新注解-Configuration和CompnentScan

使用注解后,XML分为两部分
在这里插入图片描述

怎么拿掉这些XML配置?

新建SpringConfiguration类

在这里插入图片描述
该类是一个配置类,它的作用和bean.xml是一样的

spring中的新注解

Configuration注解

  • 作用:指定当前类是一个配置类,此时类和bean.xml作用一致
  • 细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。
因为
AnnotationConfigContext ac =new AnnotationConfigApplicationContext(SpringConfig.class) //会读配置类可以不写

ComponentScan 注解

作用:用于通过注解指定spring在创建容器时要扫描的包
相当于bean.xml中的
在这里插入图片描述

  • ComponentScans注解(若干ComponentScan组成)
    在这里插入图片描述

  • ComponentScan

在这里插入图片描述

  • 属性:

    • value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。
 @ComponentScan(basePackages={"com.tju"}) //路径是类路径
       注解的属性有且只有一个值,数组类型可以把大括号拿走,省略属性名是value名称
      @ComponentScan("com.tju"

我们使用此注解就等同于在xml中配置了:

  <context:component-scan base-package="com.tju"></context:component-scan>

修改XML第二部分

在这里插入图片描述

只有放到spring容器中才能等效XML,使用Bean注解
在这里插入图片描述

Bean注解

  • 作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中
  • 属性:
    • name:用于指定bean的id。当不写时,默认值(id)是当前方法的名称 ,放入容器中的key是createQueryRunner,返回值创建出来的对象就是value =QueryRunner对象
    • 细节:
      当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象。
      查找的方式和Autowired注解的作用是一样的

@Configuration //可写可不写
@ComponentScan(“com.tju”)
public class SpringConfiguration {

在这里插入图片描述
}

AnnotationConfigApplicationContext的使用在这里插入图片描述

构造方法是参数是被spring注解过的类

测试时修改原来读取配置文件的语句,改为读配置类有注解的类
在这里插入图片描述

将QueryRunner设置为单例
在这里插入图片描述

新建一个config类
JdbcConfig.java
和spirng相关的配置类

抽取出来专门配置数据库的配置

  • 和spring连接数据库相关的配置类

public class JdbcConfig {
在这里插入图片描述
在这里插入图片描述
}

注意针对两个配置类能读取的情况

ApplicationContext ac =new AnnontationConfigApplicationContext(SpringConfiguration.class);
此时
@Configuration //可写可不写
@ComponentScan(“com.tju”)
public class SpringConfiguration {

但JdbcConfig必须加Configuration注解,成为Configuration类,创建spring容器的时候加载配置类
@Configuration
public class JdbcConfig {

如果这种情况
ApplicationContext ac =new AnnontationConfigApplicationContext(SpringConfiguration.class,JdbcConfig.class);
两个配置类都可以不加@Configuration,手动加载配置类

再次升级JdbcConfig 类上不加@Configuration,且之手动加载SpringConfiguration.class配置类
引入import注解在这里插入图片描述

数组多个配置类

Import

  • 作用:用于导入其他的配置类
  • 属性:
    • value:用于指定其他配置类的字节码。
    • 当我们使用Import的注解之后,有Import注解的类就父配置类,而导入的都是子配置类
@Configuration   //可加可不加
@ComponentScan("com.tju")
@Import(JdbcConfig.class)
public class SpringConfiguration {


}
//什么都没有
public class JdbcConfig {}
//手动加载主配置类
ApplicationContext ac =new  AnnontationConfigApplicationContext(SpringConfiguration.class);

改造JdbcConfig.java写死部分

在这里插入图片描述

引入jdbcConfig.properties配置文件

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/eesy
jdbc.username=root
jdbc.password=1234

在Jdbc配置类中定义变量
driver,url,username,password
@Value("$(key)")
key就是jdbc.driver,jdbc.url…
用value注解赋值

/**

  • 和spring连接数据库相关的配置类
    */
    public class JdbcConfig {

    @Value("${jdbc.driver}")
    private String driver;

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    /**

    • 用于创建一个QueryRunner对象
    • @param dataSource
    • @return
      */
      @Bean(name=“runner”)
      @Scope(“prototype”)
      public QueryRunner createQueryRunner(@Qualifier(“ds2”) DataSource dataSource){
      return new QueryRunner(dataSource);
      }

jdbc.config

    @Bean(name="ds2")
    public DataSource createDataSource(){
        try {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(driver);
            ds.setJdbcUrl(url);
            ds.setUser(username);
            ds.setPassword(password);
            return ds;
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    @Bean(name="ds1")
    public DataSource createDataSource1(){
        try {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(driver);
            ds.setJdbcUrl("jdbc:mysql://localhost:3306/eesy02");
            ds.setUser(username);
            ds.setPassword(password);
            return ds;
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
}

引入注解读取配置文件

PropertySource

  • 作用:用于指定properties文件的位置
  • 属性:
    • value:指定文件的名称和路径。
    • 关键字:classpath,表示类路径下

在这里插入图片描述

PropertySources注解
多个PropertySource
在这里插入图片描述

@Configuration   //可写可不写
@ComponentScan("com.tju")
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfiguration {


}

Qualifier注解的使用

解决类型匹配注解后,有两个匹配的bean对象,但bean对象id与形参不同报错
使用Qualifier指出匹配的bean-id
在这里插入图片描述

spring整合junit问题分析

  1. 应用程序的入口
    main方法
  2. junit单元测试中,没有main方法也能执行
    junit集成了一个main方法
    该方法就会判断当前测试类中哪些方法有 @Test注解
    junit就让有Test注解的方法执行
  3. junit不会管我们是否采用spring框架
    在执行测试方法时,junit根本不知道我们是不是使用了spring框架
    所以也就不会为我们读取配置文件/配置类创建spring核心容器
  4. 由以上三点可知
    当测试方法执行时,没有Ioc容器,就算写了Autowired注解,也无法实现注入
    在这里插入图片描述
  • 使用Junit单元测试:测试我们的配置
  • Spring整合junit的配置
    1. 导入spring整合junit的jar(坐标)

在这里插入图片描述
2. 使用Junit提供的一个注解把原有的main方法替换了,替换成spring提供的
@Runwith
在这里插入图片描述
3. 告知spring的运行器,spring和ioc创建是基于xml还是注解的,并且说明位
@ContextConfiguration

  • locations:指定xml文件的位置,加上classpath关键字,表示在类路径下

  • classes:指定注解类所在地位置

    当我们使用spring 5.x版本的时候,要求junit的jar必须是4.12及以上

注解整合

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class AccountServiceTest {

    @Autowired
    private IAccountService as = null;


    @Test
    public void testFindAll() {
        //3.执行方法
        List<Account> accounts = as.findAllAccount();
        for(Account account : accounts){
            System.out.println(account);
        }
    }

    @Test
    public void testFindOne() {
        //3.执行方法
        Account account = as.findAccountById(1);
        System.out.println(account);
    }

    @Test
    public void testSave() {
        Account account = new Account();
        account.setName("test anno");
        account.setMoney(12345f);
        //3.执行方法
        as.saveAccount(account);

    }

    @Test
    public void testUpdate() {
        //3.执行方法
        Account account = as.findAccountById(4);
        account.setMoney(23456f);
        as.updateAccount(account);
    }

    @Test
    public void testDelete() {
        //3.执行方法
        as.deleteAccount(4);
    }
}

XML整合

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:bean.xml")
public class AccountServiceTest {

    @Autowired
    private  IAccountService as;

    @Test
    public void testFindAll() {
        //3.执行方法
        List<Account> accounts = as.findAllAccount();
        for(Account account : accounts){
            System.out.println(account);
        }
    }

    @Test
    public void testFindOne() {
        //3.执行方法
        Account account = as.findAccountById(1);
        System.out.println(account);
    }

    @Test
    public void testSave() {
        Account account = new Account();
        account.setName("test");
        account.setMoney(12345f);
        //3.执行方法
        as.saveAccount(account);

    }

    @Test
    public void testUpdate() {
        //3.执行方法
        Account account = as.findAccountById(4);
        account.setMoney(23456f);
        as.updateAccount(account);
    }

    @Test
    public void testDelete() {
        //3.执行方法
        as.deleteAccount(4);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值