21.3 Spring IoC容器与Bean管理(下)



接下来,介绍基于注解与Java Config配置IoC容器。

相比XML配置IoC容器,只是配置方式的不同,其底层原理是一样的。

一、基于注解配置IoC容器

1.1 注解

1.定义

JDK1.5 以后,提供了一种特殊的语法:在类、属性、方法上,通过@符号,增加的某一个特定的类名,称为注解。

作用:为类、属性、方法,在不改变其里面代码的情况下,实现额外的功能扩展、增强。

本质:注解就是写在源代码中的配置信息。

2.优势

左右是鱼与熊掌的问题,不可兼得

因为Spring框架,主要面向Java工程师:首先考虑的是爱用、体验,迎合市场、程序员口味。

对比基于XML基于注解
劣势XML中,要书写大量的bean标签;写死在程序中,不易维护
劣势程序员的开发体验不好。因为源码中每次使用一个bean时,都要去翻阅XML找beanId;同时,在XML中对象设置时,也要与源代码中不断切换。
优势后期维护性好前期开发体验好
适合场景 “声明式”的原则,更适合轻量级的现代企业应用

之前,学习MyBatis、Servlet时,除了配置文件形式,也有注解形式。

Spring同理。

程序员喜欢的开发体验:

在编写源代码过程中,顺便就把这个bean进行了配置。

1.2 注解的种类:3类

Spring中,按照功能划分,可分为三种注解:

(1)组件类型的注解---------------声明当前类的功能、职责------------------------------ 用于实例化(创建)对象

(2)自动装配的注解---------------根据属性特征,完成值或对象的注入

(3)元数据的注解------------------更细化的辅助IoC容器,管理bean对象的注解

二、基于注解1:组件类型

就是放在Java类上的注解。

用途:简单补上一个组件注解,IoC容器就会自动的实例化(创建)对象,确实清爽简便

2.1 分类:4个

  • mapper层其实就是dao层
  • 红框其实是通用注解@Component的细化
  • 组件类型的注解,实例化对象的beanId默认是类名的首字母小写。

Component

a part or element of a larger whole, especially a part of a machine or vehicle.

2.2 在XML中,开启组件扫描

上述4类组件类型的注解,要想被Spring IoC识别,必须有个前置条件:在applicationContext.xml种,开启组件扫描。

组件扫描原理:扫描该路径下所有的java类,一旦某个Java类上有上述四类组件类型的注解,就对其进行实例化对象,并管理到IoC容器中。

语法:

主要是确定扫描的位置,即基准包

2.3 示例:基于组件类型的注解,来完成IoC容器的对象实例化

1.

新建Maven工程s07;

在工程的配置文件pom.xml中,引入如下依赖:

2.

新建Spring的配置文件applicationContext.xml

利用注解配置IoC容器时,一些基础配置还是要写在XML文件中,并不是完全摆脱它。

加入官网的格式头:基于注解的schema

相比于之前基于XML的schema,基于注解的schema多了一个context的命名空间:

就像Java中的包名,是为了区分重名的类一样;这里context的命名空间,是为了区分重名的bean。

注意标签context:component-scan的含义:

不需要再增加bean标签了,而只需一句话,设置基准包的名称即可

即:在applicationContext.xml中,加载读取上述属性文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>

    <!--在IoC容器初始化时,自动扫描四种组件类型的注解,并完成实例化
    @Component      @Controller      @Service     @Repository-->
    <context:component-scan base-package="com.imooc"/>

</beans>

新建包,必须是以com.imooc开头的:
com.imooc.spring.ioc下,新建四个包:

3.分别在上述包中创建对应的类:

(1)
在dao包下,新建类UserDao,用于用户表的增删改查:
bean对象总要有一个beanId:组件类型的注解,beanId默认是类名的首字母小写。

package com.imooc.spring.ioc.dao;           // 类名的前缀是以com.imooc开头的,所以能扫描到
import org.springframework.stereotype.Repository;


@Repository                    // beanId默认是userDao
public class UserDao {
}

也可以人为指定beanId:

package com.imooc.spring.ioc.dao;           // 类名的前缀是以com.imooc开头的,所以能扫描到
import org.springframework.stereotype.Repository;


@Repository("udao")         // 人为指定beanId        
public class UserDao {
}

新建应用入口类SpringApplication,加载XML文件以初始化IoC容器:

public class SpringApplication {
    public static void main(String[] args) {
        // 加载XML文件以初始化IoC容器
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        // 获取到容器内所有有效的beanId,返回一个数组
        String[] ids = context.getBeanDefinitionNames();
        for (String id : ids) {
            System.out.println(id + ":" + context.getBean(id));
        }
    }
}

问题1:

这里不用确定对象的类型?

当默认beanId时,结果为:

userDao:com.imooc.spring.ioc.dao.UserDao@4b53f538   // 默认beanId,是userDao,是UserDao类的实例化对象

当人为指定beanId时,结果为:

udao:com.imooc.spring.ioc.dao.UserDao@4b53f538        // 人为指定beanId,即udao生效了,也是UserDao类的实例化对象

实际的工作场景,常使用的是默认beanId。因为这样所有的开发人员,都遵循了统一的标准,不用额外相互询问。

(2)

service包中,新建类UserService,即用户的业务逻辑类:
简单补上一个@Service,就会自动完成IoC容器的对象实例化与管理的工作,确实清爽简便:

package com.imooc.spring.ioc.service;


@Service
public class UserService {
}

(3)

controller包中,新建类UserController,即用户控制器:

常用于Web领域,目前未搭建web环境,所以只简单演示下:

package com.imooc.spring.ioc.controller;


@Controller
public class UserController {
}

(4)

utils包中,新建类StringUtils

因为也包含了被IoC管理的对象,但是它却没有明确的分类:

package com.imooc.spring.ioc.utils;


@Component                            // 所以,使用通用注解
public class StringUtils {

}

同理,上述四类注解,都可以自定义beanId。

运行下,结果为:

userController:com.imooc.spring.ioc.controller.UserController@382db087
userDao:com.imooc.spring.ioc.dao.UserDao@73d4cc9e
userService:com.imooc.spring.ioc.service.UserService@80169cf
stringUtils:com.imooc.spring.ioc.utils.StringUtils@5427c60c

4.

上述的bean对象,是单例还是多例?

单例。因为只有是单例,才会在IoC容器初始化的过程中,进行创建。如果是多例,则会延迟到getbean或对象注入时创建。

三、基于注解2:装配注解

目的:自动的为某个属性注入数据。

3.1 分类:2个

  • @Autowired是Spring自家定义的,其他的三个是JSR规范的,是Java的行业标准
  • 不推荐使用按类型装配,建议使用强大的@Resource
  • 上述两者,都是不依赖set方法,完成属性注入,而是通过反射技术,将属性的修饰符从private改为public,最后改回private

Autowired:

wire=line,自动连线的

Resource:

a stock or supply of money, materials, staff, and other assets that can be drawn on by a person or organization in order to function effectively

相比之下,以前的基于XML的依赖注入:

book-shop工程中:

3.2 放置装配注解Autowired的两种位置

1.如果装配注解放在属性上

MVC都是分层,且必须逐层调用。

结果为什么没有setter方法?

将UserDao的属性uDao的值,通过getter方法提取出来:

确实能成功提取出来,说明已经完成了属性注入。但是,为啥没调用setter方法呢?

2.如果装配注解放在set方法上

调整注解@Autowired的位置,放到setter方法上:

既完成了属性注入,又调用了setter方法

3.比较不同

比较如果装配注解放在属性上如果装配注解放在set方法上
就不再执行set方法会执行set方法,对set方法的参数进行注入
(自动按类型/名称)
原理运行时动态完成:Spring通过反射技术,将属性的修饰符从private改为public,这样外界可以直接对该属性赋值
多数常用通常不用

接下来,基于多数常用的装配注解放在属性上,来进行属性注入,进行介绍。

3.3 装配注解Autowired:按类型class匹配,来属性注入,不推荐

1.

在dao包下,新建接口IUserDao,这是所有UserDao类都要实现的接口:

public interface IUserDao {
}
@Repository()
public class UserDao implements IUserDao {        // 实现上述接口

    public UserDao() {
        System.out.println("正在创建UserDao:" + this);
    }
}

与此同时,因为有了接口,按照面向对象编程理念,属性类型就应该从具体的类,变为接口:

@Service
public class UserService {
    
//    @Autowired
//    private UserDao uDao;            // 属性类型原先是具体的类

    @Autowired
    private IUserDao uDao;            // 属性类型就应该从具体的类,变为接口
    

    public UserService() {
        System.out.println("正在创建UserService:" + this);
    }

    public IUserDao getuDao() {
        return uDao;
    }

}

2.

如果原有的UserDao,是基于MySQL进行的开发;但是,随着技术发展,公司的数据要迁移到其他数据库,比如Oracle等,那么:

首先想到的是,是基于接口,再创建一个新的实现类UserOracleDao

建一个新的实现类`UserOracleDao`@Repository
public class UserOracleDao implements IUserDao {        // 新建一个新的实现类`UserOracleDao`
    
    public UserOracleDao(){
        System.out.println("正在创建UserOracleDao" + this);
    }
}

此时,程序运行就会报错:

原因:因为装配注解Autowired,是按类型来寻找匹配的

NoUniqueBeanDefinitionException: No qualifying bean of type 'com.imooc.spring.ioc.dao.IUserDao' available: expected single matching bean but found 2: userDao,userOracleDao

即:

3.

解决:

方式1:把UserDao@Repository()注解,去掉:

暴力,你先写别实例化对象了

方式2:通过引入额外的注解@Primary,来表示:如果有多个相同类型的对象就特指某一个对象

顾虑:开发新的类时,程序员还要考虑是否会出现类型冲突的情况。

上述根源:出现了多个相同类型(接口类型也算类型)的对象。稍不注意,就会出错。

3.4 装配注解@Resource:按名称name匹配,来属性注入,推荐

1.用法

很智能:优先按名称装配,如果匹配不到,再去按照类型装配。具体为:

注解@Resource的规则:
1.如果该注解人为设置了name属性,则按照name在IoC容器中寻找对应的bean,完成属性注入;如果没找到对应的bean,就会报错

2.如果该注解没有设置name属性:

​ 2.1 默认的,以属性名作为bean name,在IoC容器中进行匹配,完成属性注入;

​ 2.2 如果属性名找不到,只能按照兜底的类型匹配,同@Autowired,必要时加入@Primary来解决类型冲突

推荐:使用1或2.1,用的都挺多,但是尽量避免使用2.2类型匹配。

2.示例

新建DepartmentService,提供与部门相关的业务方法:

方式1:

@Service
public class DepartmentService {

    @Resource(name = "userOracleDao")        // 人为设置了name属性
    private IUserDao uDao;                   //部门,会涉及员工信息的操作
}

方式2:
规范属性的命名

3.试验

这印证了,2.1:默认的,以属性名作为bean name

四、基于注解3:元数据

作用:为Spring IoC容器管理对象时,提供一些辅助信息

4.1 分类:5个

4.2 演示

1.

对于@Scope@PostConstruct元数据注解

@Service
@Scope("prototype")               // 跟XML中的bean scope完全相同,多例模式
public class UserService {

    @Autowired                
    private IUserDao uDao;

    public UserService() {
        System.out.println("正在创建UserService:" + this);
    }

    @PostConstruct              // 跟XML中的init-method完全相同,用于属性值注入
    public void init(){
        System.out.println("初始化UserService对象");
    }

    public IUserDao getuDao() {
        return uDao;
    }
}

结果为:

初始化UserService对象

2.

对于@Value元数据注解,可以这样使用:

写死在成程序中

也可以这样使用:

基于属性文件,进行调用:

(1)

新建config.properties属性文件,代表应用程序的配置信息:
属性文件,是基于键值对的形式,且必须保证每一个key是不同的:

metaData=imooc.com

(2)

applicationContext.xml中,加载读取上述属性文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>

    <!--    通知Spring IoC容器,在初始化时加载这个属性文件-->
    <context:property-placeholder location="classpath:config.properties"/>

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

</beans>

(3)

在需要用到这个静态数值的地方,将key放入其中:

@Service
@Scope("prototype")               
public class UserService {

    @Autowired                    
    private IUserDao uDao;

    @Value("${metaData}")                // 将key放入其中
    private String metaData;

    public UserService() {
        System.out.println("正在创建UserService:" + this);
    }

    @PostConstruct                        // 初始化对象=为对象的属性赋值           
    public void init(){
        System.out.println("初始化UserService对象,metaData=" + metaData);          
    }

    public IUserDao getuDao() {
        return uDao;
    }

}

结果为:

这样在运行时,就成功为属性注入了静态数据,即成功的初始化了对象。

初始化UserService对象,metaData=imooc.com

对于上述将应用程序的配置信息放于config.properties属性文件的写法,很常见:

比如:以前连接JDBC时:

metaData=imooc.com
connection.driver=xxxxx          // 通过前缀,来体现其作用或范围
connection.url=xxxxx
connection.username=xxxxx
connection.password=xxxxx

综上所述,Spring的核心注解,已介绍完毕。

本质:注解,就是XML的一种延申。更简单、好用。摆脱了频繁切换源代码与XML配置的问题。

五、基于Java Config来配置IoC容器

java Config,是Spring 3.0 以后推出的新的配置方式。

5.1 Java Config概述

1.

本质:用Java类,来完全替代传统的XML文件。

2.

场景:敏捷开发,适合快速迭代、快速上线的工程。比如以后学习的Spring Boot就是Spring生态中进行敏捷开发的框架,默认就是基于Java Config来配置IoC容器。---------------------------------------------------------前期开发体验好

相比,XML更适合大型项目的团队协作中,切分开、各司其职。------------后期维护性好。

3.

优势:

(1)完全摆脱XML的束缚,使用独立的Java类来创建对象、管理依赖(属性赋值)

(2)能对配置进行集中创建管理:由于之前基于注解的配置形式,注解分散在每一个类中,工程一大很麻烦

(3)可在编译时进行依赖检查,不易出错:XML只有在运行时才能知道配置是否正确

缺点:写死在程序中

5.2 分类:4个

Java Config 来初始化对象的语法:

5.3 示例 :基于Java Config来实例化对象

1.

新建Maven工程s08:

在工厂的配置文件pom.xml中,引入依赖spring-context、阿里云镜像仓库:

2.

新建包,并创建演示用的三个Java类:

只创建类,不用实现:

新建mapper层的类UserDao

public class UserDao {
}

新建service层的类UserService

public class UserService {

    private UserDao userDao;            // 因为依赖UserDao,所以持有它的属性

    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

新建controll层的类UserController

public class UserController {
    private UserService userService;         // 因为依赖UserService,所以持有它的属性

    public UserService getUserService() {
        return userService;
    }

    public void setUserService(UserService userService) {
        this.userService = userService;
    }
}

3.

让上述三个类,在IoC容器初始化时,完成对象的创建、以及关联(属性赋值)。

新建一个独立的Java类Config.java

不要看作是工程的一部分,而是视为配置文件。

(初始化以后,代码的运行阶段,所有工程都是基于IoC容器。严格意义上,下面的new关键词的那些代码,并不是IoC管理的范畴?)

@Configuration              // 表明当前类是一个配置类,用于完全替代 applicationContext.xml
public class Config {

    @Bean                      // 通过定义一些方法,来创建对象,将方法返回的对象放入IoC容器。实例化的对象beanId=方法名
    public UserDao userDao(){
        UserDao userDao = new UserDao();        // 方法内部,还是new关键词的那些代码
        return userDao;
    }
}

新建应用入口类SpringApplication.java

public class SpringApplication {
    public static void main(String[] args) {
        // 基于Java Config来配置ioC容器的初始化
        ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        
        String[] ids = context.getBeanDefinitionNames();
        for (String id : ids) {
            System.out.println(id + ":" + context.getBean(id));
        }
    }
}

结果为:

成功显示两个实例化的bean对象:

config:com.imooc.spring.ioc.Config$$EnhancerBySpringCGLIB$$9ddf0940@49070868      // 用于配置的Java类Config的实例化对象
userDao:com.imooc.spring.ioc.dao.UserDao@6385cb26        // 实例化的对象beanId=方法名

在独立的Java类Config.java中,来配置其他对象:

@Configuration              // 表明当前类是一个配置类,用于完全替代 applicationContext.xml
public class Config {

    @Bean          // 通过定义一些方法,来创建对象,将方法返回的对象放入IoC容器。实例化的对象beanId=方法名
    public UserDao userDao(){
        UserDao userDao = new UserDao();
        return userDao;
    }


    @Bean
    public UserService userService(){
        UserService userService = new UserService();
        return userService;
    }

    @Bean             // 这个过程,相当于XML中<bean id="xxx" class="xxx">的Java表现形式
    public UserController userController(){
        UserController userController = new UserController();
        return userController;
    }

}

结果为:
按照方法定义的先后顺序,依次进行了实例化,并以方法名作为beanId进行了管理:

config:com.imooc.spring.ioc.Config$$EnhancerBySpringCGLIB$$dd8fc29a@4d49af10
userDao:com.imooc.spring.ioc.dao.UserDao@279ad2e3
userService:com.imooc.spring.ioc.service.UserService@58134517
userController:com.imooc.spring.ioc.controller.UserController@4450d156

综上所述,是基于Java Config来实例化对象的演示。

5.4 示例 :基于Java Config来对象依赖注入

在当前的配置类中,如何实现对象间的关联,即实现service依赖dao,controller依赖service呢?

依托set方法,但是set的对象却来自于当前的IoC容器。因此,应该设置bean对应的set方法的参数。

@Configuration      
public class Config {

    @Bean         
    public UserDao userDao(){
        UserDao userDao = new UserDao();
        System.out.println("已创建" + userDao);
        return userDao;
    }


    @Bean
    public UserService userService(UserDao userDao) {
        UserService userService = new UserService();
        System.out.println("已创建" + userService);
        userService.setUserDao(userDao);                    // 调用set方法,完成UserService中,属性userDao的赋值
        System.out.println("调用setUserDao:" + userDao);
        return userService;
    }

    
    @Bean      
    public UserController userController(UserService userService) {
        UserController userController = new UserController();
        System.out.println("已创建" + userController);
        userController.setUserService(userService);             // 调用set方法,完成属性赋值
        System.out.println("调用setUserService:" + userService);
        return userController;
    }
}

结果为:

已完成属性的注入

已创建com.imooc.spring.ioc.dao.UserDao@1dd02175
    
已创建com.imooc.spring.ioc.service.UserService@16267862
调用setUserDao:com.imooc.spring.ioc.dao.UserDao@1dd02175                // 属性的注入
    
已创建com.imooc.spring.ioc.controller.UserController@6166e06f
调用setUserService:com.imooc.spring.ioc.service.UserService@16267862     // 属性的注入
=========================================

既然对象是运行时注入的,那么注入的过程是按照名称name注入,还是按照类型注入呢?

先按name尝试注入,name不存在则按照类型注入。

5.5 Java Config兼容注解形式

1.

其实,Java Config可以与注解形式不冲突:

比如@Primary不仅可以用在注解类中,还可以用在Java Config配置文件中。

2.

比如:
在该工程中,除此之外,李四要开发员工mapper层的类EmployeeDao,他习惯用注解的形式:

@Repository
public class EmployeeDao {

}

将原本注解配置IoC容器中,XML的最后利用价值也放在java类中:

标签 context:component-scan basePackages = "xxx" ,变为注解 @ComponentScan(basePackages = "xxx")

表明:在IoC容器启动时,不但会加载读取当前Config.java类对象,还会去指定路径下扫描头上是组件类的注解的类,来实例化对象

@Configuration              
@ComponentScan(basePackages = "com.imooc")        // 注解形式,开启组件扫描
public class Config {

    @Bean         
    public UserDao userDao(){
        UserDao userDao = new UserDao();
        System.out.println("已创建" + userDao);
        return userDao;
    }


    @Bean
    public UserService userService(UserDao userDao) {
        UserService userService = new UserService();
        System.out.println("已创建" + userService);
        userService.setUserDao(userDao);                
        System.out.println("调用setUserDao:" + userDao);
        return userService;
    }

    
    @Bean     
    public UserController userController(UserService userService) {
        UserController userController = new UserController();
        System.out.println("已创建" + userController);
        userController.setUserService(userService);    
        System.out.println("调用setUserService:" + userService);
        return userController;
    }
}

结果为:

在IoC容器初始化时,他人李四用注解配置的bean对象,也能成功创建:

config:com.imooc.spring.ioc.Config$$EnhancerBySpringCGLIB$$40d69d8b@161b062a
employeeDao:com.imooc.spring.ioc.dao.EmployeeDao@17c1bced        // 他人李四用注解配置的bean对象,也能成功创建:
userDao:com.imooc.spring.ioc.dao.UserDao@51931956
userService:com.imooc.spring.ioc.service.UserService@2357d90a
userController:com.imooc.spring.ioc.controller.UserController@15bb6bea

3.

上述创建完对象后,还可以对象的注入:

在视为配置文件的独立的Java类Config.java中:

调用set方法,完成属性赋值

六、Spring与JUnit4整合

6.1 Spring Test:测试模块

Spring Test模块是Spring中专用于测试的模块。

最常用的功能:与JUnit4单元测试框架,进行良好整合。即通过Spring Test模块,可以在JUnit单元测试时,自动初始化IoC容器。

原理:基于注解。

6.2 Spring与JUnit4的整合过程:三步

分三步:

  • 注解@Runwith---------------------- 将JUnit4 的运行过程交给Spring来完成,让Spring接管JUnit4 的控制权,以便完成IoC的初始化工作;
  • 注解@ContextConfiguration---用于说明,在初始化IoC容器过程中,到底要加载哪个配置文件呢?

即:共三步:

(1)在pom.xml中,引入依赖spring-contextjunit4

(2)在新建的测试用例类中,增加两个注解,完成IoC容器的初始化工作

(3)在测试用例类中,用@Resource,注入我们需要的属性。并在测试用例的的方法中,验证代码执行是否正确。

6.3 示例

1.

新建Maven工程s09:

在工程的配置文件pom.xml中,引入依赖spring-context、阿里云镜像仓库,以及新的依赖spring-test

新建applicationContext.xml配置文件,增加官方的格式头schema:

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

2.

新建测试类:

在包com.imooc.spring.ioc.dao中,新建mapper层的类UserDao.java

public class UserDao {

    public void insert(){
        System.out.println("新增用户数据");
    }
}

新建service层的类UserService.java

public class UserService {

    private UserDao userDao;


    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    
    public void createUser(){
        System.out.println("调用创建用户的业务代码");
        userDao.insert();
    }
}

applicationContext.xml配置文件中,进行配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>

    <bean id="userDao" class="com.imooc.spring.ioc.dao.UserDao">
        
    </bean>
    
    <bean id="userService" class="com.imooc.spring.ioc.service.UserService">
        <property name="userDao" ref="userDao"/>
    </bean>

</beans>

3.

对上述代码,进行测试:

以前:创建一个应用入口类SpringApplication.java

现在:复杂场景下,需要多个测试用例,此时 JUnit就排上用场了

在工程的配置文件pom.xml中,再引入依赖junit

在包test|java中,新建测试类SpringTestor

// 将JUnit4的执行权交由Spring,在测试用例执行前,自动的初始化IoC容器
@RunWith(SpringJUnit4ClassRunner.class)          // SpringJUnit4ClassRunner是引入依赖spring-test中最核心的类
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})     // 通知IoC容器,要加载读取哪个配置文件
public class SpringTestor {

    // 如何使用?就假设这个测试类在运行时,IoC容器已初始化完毕、已经提前准备好了:即根据上述配置文件,创建对象,对象依赖注入都已完成。
    @Resource
    private UserService userService;

    @Test                             // 在测试用例中,直接调用业务方法即可
    public void testUserService(){
        userService.createUser();
    }
}

结果为:

调用创建用户的业务代码
新增用户数据

上述测试用例,其实是在IoC容器内部运行的。

在测试类SpringTestor创建好以后,会自动的注入userService对象。当然,userService对象在IoC容器初始化过程中,就已经准备好了。

在测试用例中,直接调用业务方法即可。

综上所述,Spring Test:测试模块的使用,为承上启下。后续仍会频繁使用。

声明:Jerry's Blog|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - 21.3 Spring IoC容器与Bean管理(下)


Follow excellence, and success will chase you.