今日内容

  • 容器相关
    • 容器继承体系
    • 获取Bean的方式
  • 注解+XML实现IoC
  • 全注解实现IoC
  • Spring整合其他框架
    • Mybatis
    • JUnit

1. 容器

1.1 基础代码环境

  • 基础代代码环境

  • 依赖

    <!-- 略 -->
    
  • BookDao

    package com.itheima.dao;
    
    public interface BookDao {
        public void save();
    }
    
    
  • BooDaoImpl

    package com.itheima.dao.impl;
    
    import com.itheima.dao.BookDao;
    
    public class BookDaoImpl implements BookDao {
        public BookDaoImpl() {
            System.out.println("constructor");
        }
    
        public void save() {
            System.out.println("book dao save ..." );
        }
    }
    
  • beans.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">
    	<!-- 装配进Spring容器 -->
        <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" lazy-init="true"/>
    
    </beans>
    

1.2 Bean对象的获取方式

Spring容器对象,提供了多个获取Bean对象方法getBean()的重载方法,方便获取Bean对象。

方法声明 作用 备注
Object getBean(String beanName) 根据Bean的id获取Bean对象,需要向下转型
T getBean(T.class) 根据类型获取Bean对象,不需要转型;但是如果有多个符合类型的,会报错。
T getBean(String beanName, T.class) 同时根据类型和id获取Bean对象,不需要转型,也不会报错
  • 演示代码

    public class App {
        public static void main(String[] args) {
            //1.加载类路径下的配置文件
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    
    //        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
    //        BookDao bookDao = ctx.getBean("bookDao",BookDao.class);
    //        BookDao bookDao = ctx.getBean(BookDao.class);
    //        bookDao.save();
        }
    }
    

1.3 ApplicationContext体系

/*
├─ BeanFactory (接口)
	├─xxxx .....	
        └─ ApplicationContext(接口)
             ├── yyy.....
             │   	├── ClassPathXmlApplicationContext   类路径下加载xml配置文件
             │   	├── FileSystemXmlApplicationContext  文件系统下加载xml配置文件
        	 └─ zzzz....
                 ├── AnnotationConfigApplicationContext  注解
*/
1.3.1FileSystemXmlApplicationContext

从文件系统中读取XML文件,如果文件路径使用的是相对路径,相对的是当前项目的根目录

不推荐使用该方式读取配置文件,因为配置文件位置不应该固定,应该随着项目位置变动而变动,所以推荐使用ClassPathXmlApplicationContext

退一步讲,就算要使用FileSystemXmlApplicationContext也尽量使用绝对路径,这样不容易出错,特别是你项目目录结构特别乱的时候。

  • 演示代码

    public class App {
        public static void main(String[] args) {
            //1.加载类路径下的配置文件
            //ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            //2.从文件系统下加载配置文件
            // 如果文件路径使用的是相对路径,相对的是  当前项目的根路径;
            ApplicationContext ctx = new FileSystemXmlApplicationContext("D:\\workspace\\spring\\spring_10_container\\src\\main\\resources\\applicationContext.xml");
    
            BookDao bookDao = ctx.getBean(BookDao.class);
            bookDao.save();
        }
    }
    
1.3.2 BeanFactory

Spring容器的顶层接口,早期容器类。目前其主要维护懒加载的非单例BeanClasspathXMLApplicationContext主要维护非懒加载的单例Bean

  • 演示代码

    package com.itheima;
    
    import com.itheima.dao.BookDao;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.xml.XmlBeanFactory;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.core.io.Resource;
    //初始化BeanFactory
    public class AppForBeanFactory {
        public static void main(String[] args) {
            Resource resources = new ClassPathResource("applicationContext.xml");
            BeanFactory bf = new XmlBeanFactory(resources);
    //        BookDao bookDao = bf.getBean(BookDao.class);
    //        bookDao.save();
        }
    }
    

2. 注解配置

2.1 概念

  • 配置的方式

    方式1:xml配置

    方式2:注解配置

  • 注解的作用

    xml配置比较繁琐;

    注解配置方式目的是为了简化配置

  • 注解的优劣

    Spring的全/半注解开发,全注解配置非常繁杂:

    • 使用的是SSM开发的话,建议半注解配置(XML+注解进行配置)

      XML负责配置第三方的类,注解配置自己定义的类。

    • 使用的是SpringBoot开发,建议使用全注解。

  • 相关概念

    • 组件Spring中万物皆BeanBean也可以被称为组件,包含我们在核心配置文件中配置的或者Spring各种内置Bean
    • 组件扫描Spring中通过配置一个包路径,扫描该包下所有的类,把标记有指定的注解的类装配进Spring容器成为Bean/组件,该操作即为组件扫描。

2.2 注解+xml开发

2.2.1 使用步骤相关
  1. spring配置文件beans.xml中开启组件扫描

    <!--启动组件扫描,指定对应扫描的包路径,该包及其子包下所有的类都会被扫描,加载包含指定注解的类-->
    <context:component-scan base-package="com.itheima"/>
    
  2. 在要装配进Spring容器的类上添加注解

    @Component("bookService")  // 如果没有指定id,默认使用当前类名的首字母小写作为id
    public class BookServiceImpl implements BookService {}
    
  3. 测试类中,通过Spring容器对象获取bean对象并测试

    ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
    BookService bookService = (BookService) ctx.getBean("bookService");
    bookService.save();
    
  4. 注解使用注意事项
    在进行组件所扫描时,会对配置的包及其子包中所有文件进行扫描
    扫描过程是以文件夹递归迭代的形式进行的
    扫描过程仅读取合法的java文件
    扫描时仅读取spring可识别的注解
    扫描结束后会将可识别的有效注解转化为spring对应的Bean装配进Spring容器。

2.3 全注解开发

如果是单纯的最求0xml配置Spring,就不需要任何配置XML配置文件了;但是使用全注解的配置会比较繁杂(特别是装配第三方的Bean),没有起到简化配置的作用。所以,如果使用的SSM开发,不推荐使用全注解。

2.3.1 步骤
  1. 新建配置类,并使用@Configuration标注其是一个配置类
  2. 配置类上通过@ComponentScan(String[])开启组件扫描
  3. 新建Bean的类,并标注@Component注解
  4. 创建容器对象,并获取Bean对象测试。容器类为:AnnotationConfigApplicationContext
2.3.2 演示
  • 新建配置类,并使用注解标注

    package com.itheima.config;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration  //表示自己是一个配置类,替代了原来的配置文件
    @ComponentScan("com.itheima")	// 组件扫描
    //@ComponentScan({"com.itheima",""})	// 组件扫描
    public class SpringConfig {
    }
    
  • Service/Dao不变

    // 略
    
  • 创建容器对象并获取Bean测试

    package com.itheima;
    
    import com.itheima.config.SpringConfig;
    import com.itheima.dao.BookDao;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class App {
        public static void main(String[] args) {
            // 创建AnnotationConfigXxx对象,并加载配置类
            AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
            
            // 获取Bean对象
            BookDao bookDao1 = ctx.getBean(BookDao.class);
            BookDao bookDao2 = ctx.getBean(BookDao.class);
            System.out.println(bookDao1);
            System.out.println(bookDao2);
            ctx.close();
        }
    }
    
2.3.3 注意
  • 配置类就相当于原来的配置文件,读取配置文件也就变成了读取配置类。

  • 配置类上@ComponentScan注解只能使用一次,多个位置可以通过String类型数组传递

  • 相关注解见2.4

  • 第一组成对出现的注解和配置

    // 组件扫描
    // @Component 要加在被装配的类上,组件扫描要写在配置文件中或者配置类上 
    @Component  和 组件扫描<context:component-scan base-package="com.itheima"/>
    @Component@ComponentScan("com.itheima")
    

2.4 常用注解及功能

2.4.0 注解及其功能
注解 标 注位置 等同于XML中标签或属性 作用 备注
@Component bean标签 把当前类装配进Spring容器 默认以类名作为id
类名首字母小写
@Controller bean标签 同@Component 语义化的@Component
@Service bean标签 同@Component 语义化的@Component
@Repository bean标签 同@Component 语义化的@Component
@AutoWired 属性 bean property[ref] 从Spring容器中寻找对象注入 注入不依赖setter
@Value 属性 bean property[value] 为普通类型属性注入内容 注入不依赖setter,支持SpEL & OGNL
@PropertySource <context:property-placeholder location=""/> 引入properties配置文件
@ComponentScan <context:component-scan base-package=""/> 开启组件扫描
@Bean 方法 <bean> 装配第三方的类 默认以方法名作为id
@Qualifier 属性 配合@AutoWired实现按照名称注入 配合@AutoWired实现按照名称注入
@Resource 属性 =@AutoWired + @Qulifier 按照名称注入 jdk9及以上版本默认不支持
@Configuration 配置文件变成了配置类 标注该类是一个配置类,加载进Spring
@Scope bean标签scope属性 bean的singleton|prototype 默认Singleton
@PostConstruct 方法 bean标签init-method属性 标注初始化方法
@PreDestroy 方法 bean标签destroy-method属性 标注销毁方法
@Import <import resource=""/> 导入分配置类 参数可以是一个字节码对象数组,用于导入多个配置类
2.4.1 @Component
  • 标注在类上,该类的对象被装配进Spring容器,需要配合组件扫描方可生效
  • 可以通过该注解的value属性指定beanid,不指定时默认使用首字母小写的类名作为id
  • 语义化的注解有:@Service@Controller@Repository@Configuration
  • 应用场景:按照类的分类,使用对应的注解;不知道属于哪一类,用@Component
2.4.2 @ComponentScan

作用:注解开启组件扫描

配置类 替代的 就是原来的 配置文件

@ComponentScan("basePackage")

@ComponentScan("com.itheima")	// 组件扫描
//@ComponentScan({"com.itheima",""})	// 组件扫描
public class SpringConfig {
}
2.4.3 @Autowired

作用:按照类型注入

运行原理

根据被 标注的属性的类型,从Spring容器中查找是否有符合要求的bean对象。

  • 容器中有且只有一个符合类型要求的bean,直接注入
  • 容器中有且存在多个符合类型要求的bean,会根据成员变量名和容器中的beanId进行匹配,匹配成功就注入
  • 匹配失败,就报错,提示需要的类型bean有两个 ,名字分别是什么,但是我都用不了。如果想要使用,就需要配合@Qualifier 类实现注入。
  • 也可以使用@Resource(name = "bookDao")

工作中用法:

  • 就用@Autowired
@Service
public class BookServiceImpl implements BookService {
    //@Autowired:注入引用类型,自动装配模式,默认按类型装配
    @Autowired
    //@Qualifier:自动装配bean时按bean名称装配
    @Qualifier("bookDao")// @Resource(name) =  @Autowired + @Qualifier
    // JDK9及以上版本不能直接使用
    @Resource(name = "bookDao")
    private BookDao bookDao;

    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}
2.4.4 @Value
  • 注入简单类型是属性(基本类型 + String),相当于property标签的value属性
  • 该注解不依赖于setter,被标注的成员变量不需要setter
  • 支持SpEL & OGNL。SpEL:#{}; OGNL:${}
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
    //@Value:注入简单类型(无需提供set方法)
    // 需要加载properties文件后才能使用${}
    @Value("${name}")
    private String name;

    public void save() {
        System.out.println("book dao save ..." + name);
    }
}
2.4.5 @PropertySource

作用:注解引入properties文件。在任意一个被Spring装在的Bean的类上均可使用。

@Configuration
// value值不支持通配符,多个文件使用数组穷举。
// classpath:可以省略不写,但是classpath*:不允许写
@PropertySource(value={"classpath:jdbc.properties","classpath:abc.properties"})
public class SpringConfig {

}

jdbc.properties

name=root

注意:

连接不要素硬编码在Java代码中,还是写在properties文件中。

可以手动读取properties配置文件,使用注解 @PropertySource完成加载。

2.4.6 @Qualifier

作用:配合@AutoWired共同实现:按照名称注入

@Autowired
@Qualifier("userDao")
private UserDao userDao;
2.4.7 @Resource

等同于@Autowired + @Qualifier,但是属于javax拓展包,Java9及以上版本默认不加载拓展包的依赖,需要手动添加才能用。

工作中如何注入

工作中,为当前类成员变量注入,使用@Autowired

  • 如果被注入的bean只有一个,使用@Autowired

  • 如果被注入的bean不止一个,按照名称注入:使用@Autowired + 属性名和被注入id名一致

2.4.8 @Bean
  • 作用:装配第三方类

  • 做法:

    1. 定义一个方法,让方法的返回值是这个第三方类的对象;

    2. 方法所在的类,需要被Spring识别并装在,方法才能生效,所以要在类上加一个@Configuration

  • 演示代码

    @Configuration
    public class JdbcConfig {
        /**
         * @Bean 标注在方法上,会把当前方法的返回值装配进Spring容器,可以指定ID;
         *       如果没有指定id,以方法名作为id。
         *       通常情况下,我们的方法名会省略get,直接写dataSource,也就不需要指定id了。SpringBoot常见方式
         */
        // @Bean("dataSource")
        @Bean // 不指定id,默认使用方法名做id
        public DataSource dataSource(){
            DruidDataSource ds = new DruidDataSource();
            ds.setDriverClassName("com.mysql.jdbc.Driver");
            ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
            ds.setUsername("root");
            ds.setPassword("root");
            return ds;
        }
    }
    
    
  • 测试代码

    package com.itheima;
    
    import com.itheima.config.SpringConfig;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    import javax.sql.DataSource;
    
    public class App {
        public static void main(String[] args) {
            // 加载配置类JdbcConfig并解析
            AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JdbcConfig.class);
            DataSource dataSource = ctx.getBean(DataSource.class);
            System.out.println(dataSource);
        }
    }
    

@Bean应用场景

  • 注解+XML配置方式中不常用,因为需要自己通过代码创建对象,麻烦。

  • 但是在SpringBoot中常用,SpringBoot要求全注解实现配置。

@Bean注入其他资源(简单类型 + 引用类型)

使用注解方式装配第三方Bean时就要用到@Bean+方法返回值,如果这个第三方Bean中用到了其他资源,可以通过下述方式注入。

  1. 基本类型资源,需要借助于成员变量+ @Value注解
  2. 引用类型资源,需要直接在形参位置添加需要类型的形参即可,实现原理是Spring自动按照类型装配。
    如果符合类型要求的Bean有多个,怎么玩?使用@Qualifier("bookDaoImpl2")
  • 演示代码

    package com.itheima.config;
    
    import com.alibaba.druid.pool.DruidDataSource;
    import com.itheima.dao.BookDao;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import javax.sql.DataSource;
    
    //@Configuration
    public class JdbcConfig {
        //1.定义一个方法获得要管理的对象
        @Value("${properties文件中的key}")
        private String driver;
        @Value("jdbc:mysql://localhost:3306/spring_db")
        private String url;
        @Value("root")
        private String userName;
        @Value("root")
        private String password;
        //2.添加@Bean,表示当前方法的返回值是一个bean
        //@Bean修饰的方法,形参根据类型自动装配
        @Bean
        public DataSource dataSource(@Autowired @Qualifier("bookDaoImpl2") BookDao bookDao){
            System.out.println(bookDao);
            bookDao.save(); // 控制台打印save2
            DruidDataSource ds = new DruidDataSource();
            ds.setDriverClassName(driver);
            ds.setUrl(url);
            ds.setUsername(userName);
            ds.setPassword(password);
            return ds;
        }
    }
    
  • 两个dao实现类和父接口

    // 实现类1
    @Repository
    public class BookDaoImpl implements BookDao {
    
        public void save() {
            System.out.println("book dao save ...");
        }
    }
    
    // 实现类2
    @Repository
    public class BookDaoImp2 implements BookDao {
    
        public void save() {
            System.out.println("book dao save ...");
        }
    }
    
    // 父接口
    public interface BookDao {
        public void save();
    }
    
  • 测试类

    public class App {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
            DataSource dataSource = ctx.getBean(DataSource.class);
            System.out.println(dataSource);
        }
    }
    
2.4.9 @Import

多配置类

  • 配置类可以拆分为多个,方便管理。eg:拆分出来SpringConfigJdbcConfig等多个配置类。
  • 分配置类怎么生效
    • 方式1:每个配置类都配置@Configuration注解并在组件扫描的范围内,会被自动识别并解析
    • 方式2:或者在主配置类中通过@Import(其他配置类字节码对象数组),分配置类就不需要标注@Configuration,就会被自动加载并解析。
@Configuration
@ComponentScan("com.itheima")
//@Import:导入配置信息
@Import({JdbcConfig.class})
public class SpringConfig {
}

测试2.4.6中DataSource对象获取,加载SpringConfig主配置类同样生效

package com.itheima;

import com.itheima.config.SpringConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import javax.sql.DataSource;

public class App {
    public static void main(String[] args) {
        // 加载主配置类,分配置类也会因为主配置类中@Import,而被加载解析
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        DataSource dataSource = ctx.getBean(DataSource.class);
        System.out.println(dataSource);
    }
}

2.5

3. Spring整合其他框架

3.1 全注解整合Mybatis

3.1.1 导入依赖坐标
<!-- 配置私服 -->

<!-- 配置各个依赖 -->
    <dependencies>
        <!-- spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <!-- spring-jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>

        <!-- mybatis整合Spring的依赖 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.0</version>
        </dependency>

        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>

        <!-- mysql 数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <!-- druid数据源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>

        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
            <scope>provided</scope>
        </dependency>

        <!-- junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

    </dependencies>
3.1.2 新建软件三层相关类/接口
  • 实体类Account

    package com.itheima.domain;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import java.io.Serializable;
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Account implements Serializable {
    
        private Integer id;
        private String name;
        private BigDecimal money; // 使用BigDecimal,可以进行精确运算
    
    }
    
  • Dao层接口

    package com.itheima.dao;
    
    import com.itheima.domain.Account;
    import org.apache.ibatis.annotations.Delete;
    import org.apache.ibatis.annotations.Insert;
    import org.apache.ibatis.annotations.Select;
    import org.apache.ibatis.annotations.Update;
    
    import java.util.List;
    
    public interface AccountDao {
    
        @Insert("insert into tbl_account(name,money)values(#{name},#{money})")
        void save(Account account);
    
        @Delete("delete from tbl_account where id = #{id} ")
        void delete(Integer id);
    
        @Update("update tbl_account set name = #{name} , money = #{money} where id = #{id} ")
        void update(Account account);
    
        @Select("select * from tbl_account")
        List<Account> findAll();
    
        @Select("select * from tbl_account where id = #{id} ")
        Account findById(Integer id);
    }
    
  • Service层接口

    package com.itheima.service;
    
    import com.itheima.domain.Account;
    import java.util.List;
    
    public interface AccountService {
    
        void save(Account account);
        void delete(Integer id);
        void update(Account account);
        List<Account> findAll();
        Account findById(Integer id);
    }
    
  • Service层接口实现类

    	package com.itheima.service.impl;
    
    import com.itheima.dao.AccountDao;
    import com.itheima.domain.Account;
    import com.itheima.service.AccountService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    @Service
    public class AccountServiceImpl implements AccountService {
    
        @Autowired
        private AccountDao accountDao;
    
        public void save(Account account) {
            accountDao.save(account);
        }
    
        public void update(Account account){
            accountDao.update(account);
        }
    
        public void delete(Integer id) {
            accountDao.delete(id);
        }
    
        public Account findById(Integer id) {
            return accountDao.findById(id);
        }
    
        public List<Account> findAll() {
            return accountDao.findAll();
        }
    }	
    
3.1.2 新建并配置主配置类

该配置类为主配置类,之后要导入其他分配置类,导入方式: @Import({A.class,B.class})

@Configuration
@ComponentScan("com.itheima")
@Import({JDBCConfig.class,MyBatisConfig.class})
public class SpringConfig {
}
3.1.3 新建并配置jdbc配置类

该配置类为JDBC相关分配置类,要被导入到主配置类

@PropertySource("classpath:jdbc.properties")
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;

    @Bean("dataSource")
    public DataSource getDataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}

jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db
jdbc.username=root
jdbc.password=root
3.1.4 新建并配置Mybatis配置类

该配置类为Mybatis相关分配置类,要被导入到主配置类

public class MyBatisConfig {


    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
        SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
        ssfb.setTypeAliasesPackage("com.itheima.domain");
        ssfb.setDataSource(dataSource);
        return ssfb;
    }

    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer(){
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
        msc.setBasePackage("com.itheima.dao");
        return msc;
    }
}
3.1.5 测试

App类中的main方法中测试

public class App2 {
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        AccountService accountService = (AccountService) ctx.getBean("accountService");
        Account ac = accountService.findById(2);
        System.out.println(ac);
    }
}

3.2 整合JUnit

目的:简化Spring单元测试

3.2.1 导入依赖坐标
<!-- junit version ≥ 4.12 -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>
<!-- spring整合junit的依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.2.10.RELEASE</version>
</dependency>
3.2.2 使用Spring专用的类加载器

写一个测试类,在测试类上添加@RunWith(SpringJUnit4ClassRunner.class)

//设定spring专用的类加载器
@RunWith(SpringJUnit4ClassRunner.class)
public class AccountServiceTest {}
3.2.3 加载配置类/配置文件

在上面的测试类上添加注解,@ContextConfiguration(配置文件或者配置类)

//设定spring专用的类加载器
@RunWith(SpringJUnit4ClassRunner.class)
//设定加载的spring上下文对应的配置
@ContextConfiguration(classes = SpringConfig.class)
//设定加载的spring上下文对应的配置
//@ContextConfiguration(classes = {SpringConfig.class, xxxConfig.class})
//@ContextConfiguration(value = {"classpath:配置文件1.xml","classpath:配置文件2.xml"})
//@ContextConfiguration(locations = {"classpath:配置文件1.xml","classpath:配置文件2.xml"})
//@ContextConfiguration(locations = "classpath:配置文件1.xml")
public class AccountServiceTest {}

@ContextConfiguration注解源码

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface ContextConfiguration {
    // 该属性用于指定配置文件的数组
    @AliasFor("locations")
    String[] value() default {};
    
	// 该属性用于指定配置文件的数组
    @AliasFor("value")
    String[] locations() default {};

    // 该属性用于指定配置类的字节码对象的数组
    Class<?>[] classes() default {};
}
3.2.4 测试类中注入要被测试的类
//设定spring专用的类加载器
@RunWith(SpringJUnit4ClassRunner.class)
//设定加载的spring上下文对应的配置
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest {

    // 想测谁,就注入谁
    @Autowired
    private AccountService accountService;
    
    @Test
    public void testFindById() {
        Account ac = accountService.findById(2);
        Assert.assertEquals("Jock1", ac.getName());
    }
}
3.4.5 完整代码
package com.itheima.service;

import com.itheima.config.SpringConfig;
import com.itheima.dao.AccountDao;
import com.itheima.domain.Account;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;

//设定spring专用的类加载器
@RunWith(SpringJUnit4ClassRunner.class)
//设定加载的spring上下文对应的配置
@ContextConfiguration(classes = SpringConfig.class)
//@ContextConfiguration(value = {"classpath:配置文件1.xml","classpath:配置文件2.xml"})
//@ContextConfiguration(locations = {"classpath:配置文件1.xml","classpath:配置文件2.xml"})
//@ContextConfiguration(locations = "classpath:配置文件1.xml")
public class AccountServiceTest {

    // 想测谁,就注入谁
    @Autowired
    private AccountService accountService;

    // 这里可能会报错,但是不要理会,不是语法错误,是spring帮你检查当前spring容器中是否有类的对象,不一定准确
    @Autowired
    AccountDao accountDao;

    @Test
    public void testFindById() {
        Account ac = accountService.findById(2);
        System.out.println(ac);

    }

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

    @Test
    public void testDao() {
        accountDao.findAll();
    }
}
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐