码迷,mamicode.com
首页 > 编程语言 > 详细

Spring框架4:Spring使用注解和XML配置控制反转(IOC)

时间:2020-02-26 20:55:38      阅读:66      评论:0      收藏:0      [点我收藏+]

标签:mon   public   alt   factor   jar包   空间   rmi   apache   字母   

本系列笔记均是对b站教程https://www.bilibili.com/video/av47952931 的学习笔记,非本人原创

技术图片

注解配置IOC

注解配置和基于xml的配置功能是一样的,只是配置形式不一样
这里以一个项目为例,项目还是之前的那个
AccountDAOImpl:

package com.jiading.dao.impl;

import com.jiading.dao.IAccountDAO;
import org.springframework.stereotype.Repository;

@Repository
public class AccountDAOImpl implements IAccountDAO {
    /*
    模拟保存
     */
    public void saveAccount() {
        System.out.println("保存了账户");
    }
}

AcccountServiceImpl:

package com.jiading.service.impl;

import com.jiading.dao.IAccountDAO;
import com.jiading.dao.impl.AccountDAOImpl;
import com.jiading.service.IAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/*
曾经xml的配置:
    <bean id="accountService" class="com.jiading.service.impl.AccountServiceImpl"></bean>

    用于创建对象的注解
        作用和xml中编写bean标签实现的功能是一样的
        @Component:将当前对象存入spring容器中
            属性:
                value:指定bean的id,不写时默认值是当前类名且首字母小写
        @Controller:一般用在表现层
        @Service:一般用在业务层
        @Repository:一般用于持久层
        以上三个注解的作用和属性,和Component一模一样
        他们三个是spring框架为我们提供明确的三层使用的注解,使我们的三层框架更加清晰

    用于注入数据的
        作用和bean标签下写<property>作用一样,只能注入bean类型的,基本类型和String类型不能用此
        @Autowired:自动按照类型注入,只要容器中有唯一的bean对象类型和要注入的变量类型匹配,就可以注入成功
            出现位置:可以是变量上,也可以是方法上
            细节:在使用注解注入时,set方法就不是必须的了
        @qualifier:在按照类中注入的基础上再按照名称注入。它在给类成员注入时不能单独使用,但是给方法的参数注入时可以
            属性:
                value:用于指定注入bean的id
        @Resource:直接按照bean的id注入,可以独立使用
            属性:name,用于指定bean的id
       集合类型的注入只能通过xml实现
        对于基本类型和String类型:
            @Value:注入基本类型和String类型的数据
            属性:
                value,用于指定数据的值,也可以使用spring中的spEl,也即spring中的El表达式
                    SpEl的写法:$(表达式)

    用于改变作用范围的
        作用和bean标签中使用scope一样
        @scope:用于指定bean的作用范围
            属性:
                value,指定范围的取值。常用值也是singleton和prototype

    和生命周期相关的
        作用和bean标签中使用init-method和destory-method一样
        了解即可
        @PreDestory:用于指定销毁方法
        @PostCOnstruct:用于指定初始化方法
        这两个注解都是加在方法前面的
    */
@Repository
@Scope("singleton")
public class AccountServiceImpl implements IAccountService {
    @Autowired
    @Qualifier("accountDAOImpl")
    //就像这样,在给类成员注解时必须和autiwired一起
    //上面那两个和@Resource(name="accountDAO")等价

    //@Autowired:自动按照类型注入,只要容器中有唯一的bean对象类型和要注入的变量类型匹配,就可以注入成功。
    // 如果没有就报错,有多个匹配结果默认也报错,除非有对象的id和这里的变量名一样,也就是这里的变量叫accountDAO,有没有一个容器中的bean的id(即注解时候Key)的值)也叫accountDAO
    private IAccountDAO accountDAO ;//spring从容器中找符合类型要求的,像这里虽然是个接口,但是它的实现类也是符合要求的,所以就用实现类了

    @PostConstruct
    public void init(){
        System.out.println("初始化方法执行了");
    }
    @PreDestroy
    public void destory(){
        System.out.println("销毁方法执行了");
    }
    public void saveAccount() {
        accountDAO.saveAccount();
    }

}

Client:

package com.jiading.ui;

import com.jiading.dao.IAccountDAO;
import com.jiading.dao.impl.AccountDAOImpl;
import com.jiading.service.IAccountService;
import com.jiading.service.impl.AccountServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Client {
    /*
    获取spring的IOC核心容器,并根据ID获取对象
     */
    public static void main(String[] args) {
        //1. 获取核心容器对象
        ClassPathXmlApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
        //2.根据id获取bean对象
        IAccountService as=(IAccountService)ac.getBean("accountServiceImpl");
        System.out.println(as);
        AccountDAOImpl acDAO = ac.getBean("accountDAOImpl", AccountDAOImpl.class);
        System.out.println(acDAO);
        as.saveAccount();
        ac.close();//只有主动close了容器,才能调用bean的销毁方法
    }
}

bean.xml:
是的,虽然使用的是注解,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名称空间和约束中-->
    <!-- 扫描base-package下所有的包-->
    <context:component-scan base-package="com.jiading"></context:component-scan>

</beans>

注意,使用注解配置也不是完全排除xml的配置方法,如果我们要引用一些外部资源的话,依然可以在xml中配置的,然后使用时使用@Autowired来使用

基于XML的IOC案例

先介绍一下什么是dbUtils:

来源: https://www.cnblogs.com/CQY1183344265/p/5854418.html
Dbutils:主要是封装了JDBC的代码,简化dao层的操作。
作用:帮助java程序员,开发Dao层代码的简单框架。
框架的作用:帮助程序员,提高程序的开发效率。
出生:Dbutils是由Apache公司提供。

还有c3p0是什么:

https://baike.baidu.com/item/c3p0
C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate、Spring等。

这个项目有很多可以借鉴的地方
pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>day02_ioc_account_xml</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>commons-dbutils</groupId>
            <artifactId>commons-dbutils</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.19</version>
        </dependency>
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
    </dependencies>
</project>

关键看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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 配置数据源 -->
    <bean id="dataSoure" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!-- 连接数据库的必备信息-->
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/jd_learning"></property>
    <property name="user" value="root"></property>
    <property name="password" value="<密码>"></property>
    </bean>

    <!-- queryRunner不能是单例对象,防止多线程出现问题-->
    <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
        <!-- 注入数据源 -->
        <constructor-arg name="ds" ref="dataSoure"></constructor-arg>
    </bean>

    <bean id="accountDao" class="com.jiading.dao.impl.AccountDaoImpl">
        <property name="runner" ref="runner"></property>
    </bean>

    <bean id="accountService" class="com.jiading.service.impl.AccountServiceImpl">
        <!-- 注入dao对象-->
        <property name="accountDao" ref="accountDao"></property>
    </bean>
</beans>

注意这里使用c3p0作为数据库连接对象,而dbutils的QueryRunner作为SQL命令的执行对象
每一个模块都是对其他模块有所依赖的,一般的依赖是通过在模块内创建对象的引用,然后通过set函数进行注入,例如AccountServiceImpl.java中的这段:

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

    private IAccountDao accountDao;

这需要我们在配置文件中就将依赖配置好(当然用注解的话就是在类中配置了),例如:

    <bean id="accountService" class="com.jiading.service.impl.AccountServiceImpl">
        <!-- 注入dao对象-->
        <property name="accountDao" ref="accountDao"></property>
    </bean>

但是有些类没有set函数,这时可以使用构造函数配置方法,例如配置queryRunner:

    <!-- queryRunner不能是单例对象,防止多线程出现问题-->
    <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
        <!-- 注入数据源 -->
        <constructor-arg name="ds" ref="dataSoure"></constructor-arg>
    </bean>

对于基本类型的配置就比较简单:

    <!-- 配置数据源 -->
    <bean id="dataSoure" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!-- 连接数据库的必备信息-->
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/jd_learning"></property>
    <property name="user" value="root"></property>
    <property name="password" value="<密码>"></property>
    </bean>

通过这种方法,各个层的类在对于依赖可以直接声明其对象,然后设计一个set函数,之后直接调用使用即可

package com.jiading.dao.impl;

import com.jiading.dao.IAccountDao;
import com.jiading.domain.Account;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import java.sql.SQLException;
import java.util.List;

public class AccountDaoImpl implements IAccountDao {
    public void setRunner(QueryRunner runner) {
        this.runner = runner;
    }

    private QueryRunner runner;

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

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

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

    public void updateAccount(Account account) {
        try {
            //name和money都是可变的,不变的是id,也就是主键,所以查找的时候要查id
            runner.update("update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId());
        } catch (Exception e) {
            throw new RuntimeException();
        }
    }

    public void deleteAccount(Integer accountId) {
        try {
            runner.update("delete from account where id=?",accountId);
        } catch (Exception e) {
            throw new RuntimeException();
        }
    }
}
package com.jiading.service.impl;

import com.jiading.dao.IAccountDao;
import com.jiading.domain.Account;
import com.jiading.service.IAccountService;

import java.util.List;

public class AccountServiceImpl implements IAccountService {
    public void setAccountDao(IAccountDao accountDao) {
        this.accountDao = accountDao;
    }

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

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

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

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

    public void deleteAccount(Integer accountId) {
        accountDao.deleteAccount(accountId);
    }
}

还要配置数据对象Account.java:

package com.jiading.domain;

import java.io.Serializable;

/*
账户的实体类
 */
public class Account implements Serializable {
    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;
    }

    /*
         一个对象序列化的接口,一个类只有实现了Serializable接口,它的对象才是可序列化的。因此如果要序列化某些类的对象,这些类就必须实现Serializable接口。而实际上,Serializable是一个空接口,没有什么具体内容,它的目的只是简单的标识一个类的对象可以被序列化。
    ? ? ? ? 什么情况下需要序列化:
    ? ? ? ? 1.?????当你想把的内存中的对象写入到硬盘的时候。
    ? ? ? ? 2.?????当你想用套接字在网络上传送对象的时候。
    ? ? ? ? 3.?????当你想通过RMI传输对象的时候。
         */
    private Integer id;

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

    private String name;
    private Float money;
}

测试类:

package com.jiading.test;

import com.jiading.domain.Account;
import com.jiading.service.IAccountService;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

/*
使用Junit单元测试,测试我们的配置
 */
public class AccountServiceTest {
    @Test
    public void testFindAll() {
        ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
        IAccountService accountService = (IAccountService)ac.getBean("accountService");
        List<Account> allAccount = accountService.findAllAccount();
        for (Account account:allAccount){
            System.out.println(account);
        }
    }
    @Test
    public void testFindone() {
        ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
        IAccountService accountService = (IAccountService)ac.getBean("accountService");
        Account accountById = accountService.findAccountById(1);
        System.out.println(accountById);
    }
    @Test
    public void testSave() {
        Account account=new Account();
        account.setName("test");
        account.setMoney(12345f);
        ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
        IAccountService accountService = (IAccountService)ac.getBean("accountService");
accountService.saveAccount(account);
    }
    @Test
    public void testUpdate() {
    }
    @Test
    public void testDelete() {
    }
}

改为使用注解

我们可以将上面使用xml的配置转为使用注解
这里就举一点例子吧,剩下的大同小异

@Component("accountService")
public class AccountServiceImpl implements IAccountService {
    @Autowired
    private IAccountDao accountDao;

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">
    <context:component-scan base-package="com.jiading"></context:component-scan>
    <!-- 配置数据源 -->
    <bean id="dataSoure" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!-- 连接数据库的必备信息-->
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/jd_learning"></property>
        <property name="user" value="root"></property>
        <property name="password" value="<密码>"></property>
    </bean>

    <!-- queryRunner不能是单例对象,防止多线程出现问题-->
    <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
        <!-- 注入数据源 -->
        <constructor-arg name="ds" ref="dataSoure"></constructor-arg>
    </bean>
</beans>

但是不能在创建容器之后使用:

@AutoWired
IAccountService accountService;

那么,我们能不能连这剩下的xml也不用,完全拜托这个xml文档而纯用注解呢?其实是可以的,但是改动要比较大:
我们新建一个config包,和com包并列
在测试类中,调用的方式变成了:

//获取容器
        ApplicationContext ac=new AnnotationConfigApplicationContext(springConfiguration.class);
        /*
        使用AnnotationConfigApplicationContext创建容器时,可以指定多个配置类(这个构造函数是可变参数的),它们之间是兄弟关系
         */

这个springConfiguration就是我们的主配置类,它在config这个包里:

package config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;

/*
该类是一个配置类,作用和bean.xml一样
为了达到这样的效果,需要加注解@Configuration,作用就是指定当前类是一个配置类
    当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写
@ComponentScan:用于通过注解指定spring在创建容器时要扫描的包,就和xml中 <context:component-scan base-package="">的作用一样
    属性写value或者basepackage都可以
 */
/*
@Import:用于导入其他的配置类
 */
@Configuration
//@ComponentScan({"com.jiading","config"})
//如果使用@Inport的话就可以改写为:
@ComponentScan("com.jiading")
@Import(JdbcConfig.class)//加了这个,在JdbcConfig中甚至就不需要加@Configuration注解了
/*
使用Import注解之后,有Import的类就是父配置类,Import指向的是子配置类
 */

@PropertySource("classpath:jdbcConfig.properties")
//@PropertySource:指定配置文件的位置
//classpath表示后面的路径是类路径
public class springConfiguration {
}

为什么它里面没有内容呢,因为我们原来留下的就是一些JDBC的相关操作,而这是比较公共的配置,可能有多个模块都要用到,所以把它独立出来,不和该模块的总体配置混在一起:
JdbcConfig.java

package config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

import javax.sql.DataSource;

/*
和spring连接数据库相关的配置类
 */
@Configuration
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对象
    @Bean:用于把当前方法的返回值作为bean对象,存入spring的IOC容器中
        属性:
            name:用于指定bean的id,默认值是当前方法的名称
    @Scope:用于指定是单例还是多例,默认是单例的
     */
    @Bean(name = "runner")
    @Scope("prototype")
    public QueryRunner createQueryRunner(DataSource datasource) {
        //这里传入的参数spring会自动从容器中找,和Autowired步骤一样:自动按照类型匹配,如果类型一样的话优先参数名和id一样的
        return new QueryRunner(datasource);
    }

    @Bean(name = "datasource")
    /*
    将配置参数定义在外边,随时可改,不需要修改程序和重新编译
     */
    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();
        }
    }
}

为什么这里没有直接将参数放进去,而是使用Value注解来读取,也是为了将配置文件和程序独立起来,可以修改:
jdbcConfig.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/jd_learning
jdbc.username=root
jdbc.password=<密码>

由此可以看出,为了将项目化为纯注解项目,所费的功夫其实是挺大的。而在实际运用中,是该使用注解还是xml,首先看公司的要求。如果没有要求的话,之前注解和xml混合的方式其实挺好的:jar包中的类使用xml方式,而自己写的类使用注解方式


这里可以思考一个问题,既然我们可以使用注解来注入类,那为什么在最外面的调用时,还依然要使用IAccountService accountService = (IAccountService)ac.getBean("accountService");的方式呢?这么想是没错的,我们可以使用注解来注入,但是有一个问题是,注解只能注入类变量,不能注入方法中的局部变量,所以需要将它作为类变量才能使用注解注入。
除此之外,我们能不能不手动创建容器,特别是对于Test类中,每一个test方法都需要使用

ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
IAccountService accountService = (IAccountService)ac.getBean("accountService");

才能使用,能不能改进下呢?其实是可以的

改进Junit方法

我们知道,Junit方法没有main方法但是可以执行的原因是其实是有一个隐含的main方法来调用各个Test方法的(可以运行单个Test方法,但是如果点击类名的话也可以选择运行该类中所有Test方法),而我们可以利用@before注解和init方法,使得在执行Test方法之前先执行这个方法,而我们在这个方法中将容器和AccountService初始化。此时在各个Test方法中就不需要重复定义它们了。但是这依然是不能使用注解注入AccountService的,因为AccountService是类变量,初始化的时候就需要spring进行注入,而此时spring容器还没有创建,所以在init方法中依然需要accountService = (IAccountService)ac.getBean("accountService");语句。
那有没有其他的方法呢?其实是有的,就是在main方法创建的时候就把spring容器创建好,而这使用Junit原有的main方法是无法完成的,这就需要使用整合了spring框架的junit main方法。
在pom.xml中导入:

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>

测试类这样写:

package com.jiading.test;

import com.jiading.domain.Account;
import com.jiading.service.IAccountService;
import config.springConfiguration;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;

/*
使用Junit单元测试,测试我们的配置
spring整合junit的配置
1. 导入spring整合junit的jar
2. 使用junit提供的一个注解@Runwith,把原有的main方法替换成spring提供的main方法,为我们创建容器
3. 告知spring运行器,spring和ioc创建是基于xml还是注解的,并告知位置
当使用spring5.x版本时,要求Junit的jar包必须是4.1.2及以上版本的
 */

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = springConfiguration.class)

/*
location属性:指定xml文件的位置,表示类路径
classes:指定注解类所在位置
 */
public class AccountServiceTest {
    @Autowired
    private IAccountService as;
    @Test
    public void testFindAll() {
        List<Account> allAccount = as.findAllAccount();
        for (Account account:allAccount){
            System.out.println(account);
        }
    }
    @Test
    public void testFindone() {
        Account accountById = as.findAccountById(1);
        System.out.println(accountById);
    }
    @Test
    public void testSave() {
        Account account=new Account();
        account.setName("test");
        account.setMoney(12345f);
        as.saveAccount(account);
    }
}

Spring框架4:Spring使用注解和XML配置控制反转(IOC)

标签:mon   public   alt   factor   jar包   空间   rmi   apache   字母   

原文地址:https://www.cnblogs.com/jiading/p/12368803.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!