【万字长文】Spring框架 层层递进轻松入门 (IOC和DI)

开篇絮叨

前面一篇文章花大量内容,重点学习了 Spring入门 的一些思想,以及简单的学习了 IOC基础 以及基于基于 XML 的配置方式,你们应该清楚,XML与注解经常是如影随行的,他们就像一对双胞胎,但兄弟两个的想法都是一致的,那就是帮助开发者实现想要的功能,咱们所说的IOC 技术,无疑是为了下降程序间的耦合,那么,今天就来聊一聊,基于注解的IOC配置,固然为了你们有对比学习,两种配置同时讲解,同时我把例举得尽可能完整一些,就来完成一个对单表进行 CURD 的案例java

(一) 准备代码与环境

(1) 添加必要的依赖

  • spring-context
  • mysql-connector-java
  • c3p0(数据库链接池)
  • commons-dbutils(简化JDBC的工具)—后面会简单介绍一下
  • junit (单元自测)

说明:因为我这里建立的是一个Maven项目,因此在这里修改 pom.xml 添加一些必要的依赖坐标就能够mysql

若是建立时没有使用依赖的朋友,去下载咱们所须要的 jar 包导入就能够了spring

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>

        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>

        <dependency>
            <groupId>commons-dbutils</groupId>
            <artifactId>commons-dbutils</artifactId>
            <version>1.4</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

简单看一下,spring核心的一些依赖,以及数据库相关的依赖等就都导入进来了sql

<div align="center">
<img src="https://user-gold-cdn.xitu.io/2020/2/24/1707618a159a64af?w=535&h=368&f=png&s=152529" style="zoom:80%">
</div>数据库

(2) 建立帐户表以及实体

A:建立 Account 表
-- ----------------------------
-- Table structure for account
-- ----------------------------
CREATE TABLE `account`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32),
  `balance` float,
  PRIMARY KEY (`id`)
)
B:建立 Account 类

没什么好说的,对应着咱们的表创出实体apache

public class Account implements Serializable {
    private  Integer id;
    private String name;
    private Float balance;
    ......补充 get set toString 方法

(3) 建立Service以及Dao

A:AccountService 接口
public interface AccountService {

    void add(Account account);

    void delete(Integer accpuntId);

    void update(Account account);

    List<Account> findAll();

    Account findById(Integer accountId);
}
B:AccountServiceImpl 实现类
public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao;

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

    public void add(Account account) {
        accountDao.addAccount(account);
    }

    public void delete(Integer accpuntId) {
        accountDao.deleteAccount(accpuntId);
    }

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

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

    public Account findById(Integer accountId) {
        return accountDao.findAccountById(accountId);
    }
}
C:AccountDao 接口
public interface AccountDao {

    void addAccount(Account account);

    void deleteAccount(Integer accountId);

    void updateAccount(Account account);

    List<Account> findAllAccount();

    Account findAccountById(Integer accountId);
}
D:AccountDaoImpl 实现类

因为今天要完成的是一个增删改查的操做,因此咱们引入了 DBUtils 这样一个操做数据库的工具,它的做用就是封装代码,达到简化 JDBC 操做的目的,因为之后整合 SSM 框架的时候,持久层的事情就能够交给 MyBatis 来作,而今天咱们重点仍是讲解 Spring 中的知识,因此这部分会用就能够了,重点看 XML 与 注解 两种配置方式安全

用到的内容基本讲解:微信

QueryRunner 提供对 sql 语句进行操做的 API (insert delete update)session

ResultSetHander 接口,定义了查询后,如何封装结果集(仅提供了咱们用到的)框架

  • BeanHander:将结果集中第第一条记录封装到指定的 JavaBean 中
  • BeanListHandler:将结果集中的全部记录封装到指定的 JavaBean 中,而且将每个 JavaBean封装到 List 中去
public class AccountDaoImpl implements AccountDao {

    
    private QueryRunner runner;

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

    public void addAccount(Account account) {
        try {
            runner.update("insert into account(name,balance)values(?,?)", account.getName(), account.getBalance());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


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

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

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

(二) XML 配置方式

在这里有两基本的方式,一是经过构造函数注入,另外一种就是经过Set注入,实际上所作的就是,使用类的构造函数或者Set给成员变量进行赋值,但特别的是,这里是经过配置,使用 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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--配置Service-->
    <bean id="accountService" class="cn.ideal.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <!--配置Dao-->
    <bean id="accountDao" class="cn.ideal.dao.impl.AccountDaoImpl">
        <property name="runner" ref="runner"></property>
    </bean>

    <!--配置 QueryRunner-->
    <bean id="runner" class="org.apache.commons.dbutils.QueryRunner">
        <!--注入数据源-->
        <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/ideal_spring"></property>
        <property name="user" value="root"></property>
        <property name="password" value="root99"></property>

    </bean>
</beans>

分析一下:

配置 Bean 标签的时候,咱们见到了两种形式 property、constructor-arg 也就是对应着 set 方式 与构造函形式,先说一下比较常见的 set 方式,用上面的代码中距离:

(1) Set 方式

顾名思义,就是经过去找你给出对应的 Set 方法,而后对成员变量进行赋值,先看下类中的代码

public class AccountServiceImpl implements AccountService {
    //成员
    private AccountDao accountDao;
    //Set方法
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
     
    ...... 下面是增删改查的方法
}

这是 bean.xml 中的配置

<!--配置Service-->
<bean id="accountService" class="cn.ideal.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
</bean>

而后 property 配置的过程当中,有一些属性须要说一下

  • name:与成员变量名无关,与set方法后的名称有关,例如 setAccountDao() 获取到的就是accountDao,而且已经小写了开头
  • value:这里能够写基本数据类型和 String
  • ref:这里能够引入另外一个bean,帮助咱们给其余类型赋值 (例如这里就经过 ref 引入了下面 id 值为accountDao的 bean)

固然,之后可能会见到一种方式就是 使用 p名称空间注入数据 (本质仍是set)

头部中须要修改引入这一句

xmlns:p="http://www.springframework.org/schema/p"

我直接拿之前文章中的一个例子:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p"
    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="accountService" 
    class="cn.ideal.service.impl.AccountServiceImpl" p:name="汤姆" p:age="21" p:birthday-ref="nowdt"/>
<bean id="nowdt" class="java.util.Date"></bean>
</beans>

(2) 构造函数方式

下面就是使用构造函数的一种方式,这一种的前提就是:类中必须提供一个和参数列表相对应的构造函数

因为咱们选择的是 DBUtils 这样一个工具,而它为咱们提供了两种构造函数,即带参和无参,因此咱们能够在其中注入数据源,也可使得每一条语句都独立事务

还有一点须要说明的就是:咱们下面的数据源使用了 c3p0 这只是一种选择方式,并非必定的,是由于使用 DBUtils 的时候须要手动传递一个 Connection 对象

<!--配置 QueryRunner-->
<bean id="runner" class="org.apache.commons.dbutils.QueryRunner">
    <!--注入数据源-->
    <constructor-arg name="ds" ref="dataSource"></constructor-arg>
</bean>

来讲一下所涉及到的标签:

  • constructor-arg(放在 bean 标签内) 再说一说其中的一些属性值

    • 给谁赋值:

      • index:指定参数在构造函数参数列表的索引位置
      • type:指定参数在构造函数中的数据类型
      • name:指定参数在构造函数中的名称(更经常使用)
    • 赋什么值:

      • value:这里能够写基本数据类型和 String
      • ref:这里能够引入另外一个bean,帮助咱们给其余类型赋值

(3) 注入集合属性

为了演示这些方式,咱们在一个实体成员中将常见的一些集合都写出来,而后补充其 set 方法

private String[] strs;
private List<String> list;
private Set<String> set;
private Map<String,String> map;
private Properties props;

在配置中也是很简单的,只须要按照下列格式写标签就能够了,因为增删改查中并无涉及到集合的相关信息,这里就是简单提一下,能够本身测试一下

<bean id="accountService" class="cn.ideal.service.impl.AccountServiceImpl">
    <property name="strs">
        <array>
            <value>张三</value>
            <value>李四</value>
            <value>王五</value>
        </array>
    </property>

    <property name="list">
        <list>
            <value>张三</value>
            <value>李四</value>
            <value>王五</value>
        </list>
    </property>

    <property name="set">
        <set>
            <value>张三</value>
            <value>李四</value>
            <value>王五</value>
        </set>
    </property>

    <property name="map">
        <map>
            <entry key="name" value="张三"></entry>
            <entry key="age" value="21"></entry>
        </map>
    </property>

    <property name="props">
        <props>
            <prop key="name">张三</prop>
            <prop key="age">21</prop>
        </props>
    </property>
 </bean>

(4) 测试代码

public class AccountServiceTest {

    private ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
    private AccountService as = ac.getBean("accountService", AccountService.class);

    @Test
    public void testAdd(){
        Account account = new Account();
        account.setName("jack");
        account.setBalance(1000f);
        as.add(account);
    }

    @Test
    public void testUpdate(){
        Account account = as.findById(4);
        account.setName("杰克");
        account.setBalance(1500f);
        as.update(account);
    }

    @Test
    public void testFindAll(){
        List<Account> list = as.findAll();
        for(Account account : list) {
            System.out.println(account);
        }
    }

    @Test
    public void testDelete(){
        as.delete(4);
    }
}

(5) 执行效果

添加,修改(包含了查询指定id),删除

<div align="center">

<img src="https://user-gold-cdn.xitu.io/2020/2/24/1707618a27d84ba4?w=259&h=153&f=png&s=5014" style="zoom:80%">
<img src="https://user-gold-cdn.xitu.io/2020/2/24/1707618a841155ed?w=266&h=156&f=png&s=5381" style="zoom:80%">
<img src="https://user-gold-cdn.xitu.io/2020/2/24/1707618adeefa5e7?w=263&h=136&f=png&s=4654" style="zoom:80%">

</div>

查询全部

<div align="center">

<img src="https://user-gold-cdn.xitu.io/2020/2/24/1707618aeedd590b?w=437&h=90&f=png&s=31302" style="zoom:80%">

</div>

(三) 注解配置方式

首先,咱们先将上面的例子使用注解来实现一下,再来具体的讲解:

(1) 改造原程序为注解配置

首先须要为 Dao 和 Service 的实现类中 添加注解

@Service("accountService")
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;
     
       下面的原封不动
}
@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {
    @Autowired
    private QueryRunner runner;
   
    下面的原封不动
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
    <!--开启扫描-->
    <context:component-scan base-package="cn.ideal"></context:component-scan>

    <!--配置 QueryRunner-->
    <bean id="runner" class="org.apache.commons.dbutils.QueryRunner">
        <!--注入数据源-->
        <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/ideal_spring"></property>
        <property name="user" value="root"></property>
        <property name="password" value="root99"></property>
    </bean>
</beans>

到这里,一个最基本的注解改造就完成了,你们能够用前面的测试类进行一下测试

下面咱们正式说一下注解配置相关的知识

(2) 经常使用注解

A:建立对象

@Component

  • 让Spring 来管理资源,至关于XML 中配置一个 bean <bean id="" class="">
  • 能够在括号内指定 value 值,即指定 bean 的 id ,若是不指定就会默认的使用当前类的类名
  • 若是注解中只有一个value属性要赋值,value能够不写,直接写名称,如上面例子中

@Controller @Service @Repository

对于建立对象的注解,Spring 还提供了三种更加明确的说法,做用是彻底相同的,可是针对不一样的场景起了不一样的叫法罢了

  • @Controller:通常用于表现层
  • @Service:通常用于业务层
  • @Repository:通常用于持久层
B:注入数据
@Autowired
  • 自动按类型注入,至关于XML 中配置一个 bean <property name="" ref=""> 或者 <property name="" value="">
  • 容器中有一个惟一的 bean 对象类型和注入的变量类型一致,则注入成功

    • @Autowired
      private AccountDao accountDao;
      
      @Repository("accountDao")
      public class AccountDaoImpl implements AccountDao {......}
    • 好比上面的例子,Spring的IOC中容器是一个Map的结构,字符串“accountDao” 以及这个能够认为是 AccountDao 类型的 AccountDaoImpl 类就被以键值对的形式存起来,被注解 @Autowired的地方,会直接去容器的 value 部分去找 AccountDao 这个类型的类
    • 当 IoC 中匹配到了多个符合的,就会根据变量名去找,找不到则报错:例以下面,根据 AccountDao类型匹配到了两个类,因此根据变量名去找找到了 AccountDaoImplA 这个类
    • @Autowired
      private AccountDao accountDaoA;
      
      @Repository("accountDaoA")
      public class AccountDaoImplA implements AccountDao {......}
      
      @Repository("accountDaoB")
      public class AccountDaoImplB implements AccountDao {......}
  • 能够对类的成员变量、方法以及构造函数进行标注,完成自动装配
  • 使用此注解能够省略 set 方法
@Qualifier
  • 在自动按类型注入的基础之上,按照 Bean 的 id 注入,给字段注入的时候不可以单独使用,须要配合上面的 @Autiwire 使用,可是给方法参数注入的时候,能够独立使用
  • 使用时:value 值指定 bean 的 id

它有时候必须配合别的注解使用,有没有一个标签能够解决这个问题呢?答案就是 @Resource

@Resource
  • 直接按照 bean 的 id 注入,不过只能注入其余 bean 类型
  • 使用时:name 值指定 bean 的 id

前面三个都是用来注入其余的 bean 类型的数据,下面来讲一说,基本类型以及String的实现

(特别说明:集合类型的注入只能经过 XML 来实现)

@Value
  • 这个注解就是用来注入基本数据类型和 String 类型数据的
  • 使用时:value 属性用于指定值
C:改变做用范围
@Scope
  • 指定 bean 的做用范围 至关于XML 中配置一个 <bean id="" class="" scope
  • 使用时:value 属性用于指定范围的值(singleton prototype request session globalsession)
D:生命周期相关

至关于:<bean id="" class="" init-method="" destroy-method="" />

@PostConstruct
  • 指定初始化方法
@PreDestroy
  • 指定销毁方法

(四) XML和注解 的对比与选择

(1) 优缺点

通常来讲,咱们两种配置方式都是有人使用的,不过我我的更习惯使用注解的方式

  • XML

    • 类之间的松耦合关系,扩展性强,利于更换修改
    • 对象之间的关系清晰明了
  • 注解:

    • 简化配置,而且使用起来也容易,效率会高一些
    • 在类中就能找对配置,清晰明了
    • 类型安全

(2) 二者对比

XML配置 注解配置
建立对象 <bean id="" class=""> @Controller @Service @Repository@Component
指定名称 经过 id 或者 name 值指定 @Controller("指定的名称")
注入数据 <property name="" ref=""> @Autowired @Qualifier @Resource @Value
做用范围 <bean id="" class="" scope> @Scope
生命周期 <bean id="" class="" init-method="" destroy-method=""/> @PostConstruct @PreDestroy

(五) 补充新注解

为何要补充新注解呢? 在咱们使用注解时,在书写代码时,简化了不少,可是咱们在 bean.xml 文件中 仍然须要 开启扫描、 进行配置QueryRunner 以及 数据源,如何完全摆脱 xml 配置全面使用注解呢?

这也就是咱们将要补充的几个新注解,做用就是让咱们全面使用注解进行开发

(1) 注解讲解

A: 配置类注解
@Configuration
  • 指定当前类是 spring 的一个配置类,至关于 XML中的 bean.xml 文件
  • 获取容器时须要使用下列形式
  • private ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);

依旧使用上方的 CURD 的案例代码进行修改,首先与cn同级建立了一个名为 config 的包,而后编写一个名为 SpringConfiguration 的类,固然实际上这两个名字无所谓的,添加注解

@Configuration
public class SpringConfiguration {
}
B: 指定扫描包注解
@ComponentScan

@Configuration 至关于已经帮咱们把 bean.xml 文件创立好了,按照咱们往常的步骤,应该指定扫描的包了,这也就是咱们这个注解的做用

  • 指定 spring 在初始化容器时要扫描的包,在 XML 中至关于:
  • <!--开启扫描-->
    <context:component-scan base-package="cn.ideal"></context:component-scan>
  • 其中 basePackages 用于指定扫描的包,和这个注解中value属性的做用是一致的

具体使用:

@Configuration
@ComponentScan("cn.ideal")
public class SpringConfiguration {
}
C: 建立对象
@Bean

写好了配置类,以及指定了扫描的包,下面该作的就是配置 QueryRunner 以及数据源了,在 XML 中咱们会经过书写 bean 标签来配置,而 Spring 为咱们提供了 @Bean 这个注解来替代原来的标签

  • 将注解写在方法上(只能是方法),也就是表明用这个方法建立一个对象,而后放到 Spring 的容器中去
  • 经过 name 属性 给这个方法指定名称,也就是咱们 XML 中 bean 的 id

具体使用:

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 javax.sql.DataSource;

public class JdbcConfig {

    /**
     * 建立一个 QueryRunner对象
     * @param dataSource
     * @return
     */
    @Bean(name = "runner")
    public QueryRunner creatQueryRunner(DataSource dataSource){
        return  new QueryRunner(dataSource);
    }


    /**
     * 建立数据源,而且存入spring
     * @return
     */
    @Bean(name = "dataSource")
    public DataSource createDataSource() {
        try {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setUser("root");
            ds.setPassword("1234");
            ds.setDriverClass("com.mysql.jdbc.Driver");
            ds.setJdbcUrl("jdbc:mysql:///spring_day02");
            return ds;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
D: 配置 properties 文件
@PropertySource

上面在建立数据源的时候,都是直接把配置信息写死了,若是想要使用 properties 进行内容的配置,在这时候就须要,使用 @PropertySource 这个注解

  • 用于加载 .properties 文件中的配置
  • value [] 指定 properties 文件位置,在类路径下,就须要加上 classpath
@Configuration
@ComponentScan("cn.ideal")
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfiguration {
}
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")
    public QueryRunner creatQueryRunner(DataSource dataSource){
        return  new QueryRunner(dataSource);
    }


    /**
     * 建立数据源,而且存入spring
     * @return
     */
    @Bean(name = "dataSource")
    public DataSource createDataSource() {
        try {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setUser(username);
            ds.setPassword(password);
            ds.setDriverClass(driver);
            ds.setJdbcUrl(url);
            return ds;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
E:导入其余配置类
@Import

这样看来一个 JdbcConfig 就基本写好了,咱们在其中配置了 QueryRunner 对象,以及数据源,这个时候,实际上咱们原先的 bean.xml 就能够删掉了,可是咱们虽然写好了 JdbcConfig 可是如何将两个配置文件联系起来呢?这也就是这个注解的做用

@Configuration
@ComponentScan("cn.ideal")
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfiguration {
}

(2) 注解获取容器

修改获取容器的方式后,就能够进行测试了

private ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
private AccountService as = ac.getBean("accountService", AccountService.class);

(五) Spring 单元测试改进

因为咱们须要经过上面测试中两行代获取到容器,为了避免每一次都写这两行代码,因此咱们在前面将其定义在了成员位置,可是有没有办法能够省掉这个步骤呢?

也就是说,咱们想要程序自动建立容器,可是原来的 junit 很显然是实现不了的,由于它并不会知道咱们是否使用了 spring ,不过 junit 提供了一个注解让咱们替换它的运行器,转而由 spring 提供

首先须要导入 jar 包 或者说导入依赖坐标

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

使用 @RunWith 注解替换原有运行器 而后使用 @ContextConfiguration 指定 spring 配置文件的位置,而后使用 @Autowired 给变量注入数据

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

    @Autowired
    private AccountService as;
    
}

(六) 总结

到这里,这篇文章就结束了,这篇文章主要讲解的内容接着咱们上一篇文章讲解,上一篇更多的是从传统按部就班的提到 Spring,更多的是帮助你们理解为何用Spring,而这篇文章是基于上一篇的基础,更多的提到的是如何去用 Spring,因此看起来更像是一个工具书同样的文章,并无提到不少的思想原理,而是帮助你们快速的上手用 XML 以及注解的方式,固然大神天然不少,不敢说什么有技术,但总归是但愿能给不太熟悉 spring 的朋友一些帮助,或者临时当作一篇工具文来查找,再次感谢你们的访问与赞,谢谢朋友们的支持!再次感谢!

(七) 结尾

若是文章中有什么不足,欢迎你们留言交流,感谢朋友们的支持!

若是能帮到你的话,那就来关注我吧!若是您更喜欢微信文章的阅读方式,能够关注个人公众号

在这里的咱们素不相识,却都在为了本身的梦而努力 ❤

一个坚持推送原创开发技术文章的公众号:理想二旬不止

相关文章
相关标签/搜索