Spring - IOC注解开发

Spring_IOC注解开发

一、基于注解的IOC和DI

1. 快速入门(重点)

需求描述
  • 有dao层:UserDaoUserDaoImpl
  • 有service层:UserServiceUserServiceImpl
  • 使用注解配置bean,并注入依赖
需求分析
  1. 准备工作:创建Maven项目,导入依赖坐标

  2. 编写代码并注解配置:

    编写dao层、service层代码,使用注解@Component配置bean:代替xml里的bean标签

    使用注解@Autowired依赖注入:代替xml里的propertyconstructor-arg标签

  3. 在xml配置文件中开启组件扫描

  4. 测试

需求实现
1) 准备工作
  • 创建Maven项目,导入依赖坐标
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
2) 编写代码,并注解配置
  • UserDao接口
package com.itheima.dao;

public interface UserDao {
    void add();
}
  • UserDaoImpl实现类
package com.itheima.dao.impl;

import com.itheima.dao.UserDao;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

@Component
public class UserDaoImpl implements UserDao {
    public void add() {
        System.out.println("调用了UserDaoImpl的add方法~!~");
    }
}


  • UserService接口
package com.itheima.service;

public interface UserService {
    void add();
}

  • UserServiceImpl实现类
package com.itheima.service.impl;

import com.itheima.dao.UserDao;
import com.itheima.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

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

/*
    需求:
        在UserServiceImpl里面调用UserDaoImpl的add方法
    分析:
        1. 把这两个类交给spring管理,让spring创建这两个类的对象
        2. 在UserServiceImpl里面注入UserDaoImpl 的对象
        3. 使用对象来调用方法
     步骤:
        1. 在UserServiceImpl和UserDaoImpl身上打注解 :  @Component
        2. 在UserServiceImpl里面定义属性,private UserDao userDao;
        3. 在属性身上打注解:  @AutoWired
        4. 在xml里面打开扫描的开关,这样spring才能知道哪些类要创建对象,里面的什么属性要注入!
 */
@Component 
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDaoImpl;  //被注入的属性写成 接口 类型比较好,后面的属性名可以改成接口的任一实现类,因为实现类的bean 的id 默认是首字母小写的类名。接口有多个实现类就会有属性名去找默认id是属性名的bean

    public void add() {
        System.out.println("调用了UserServiceImpl的add方法~!");
        userDaoImpl.add();
    }

}

3) 开启组件扫描
  • 创建applicationContext.xml,注意引入的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">


    <!--
        1. 告诉spring要扫描指定的包,因为这个包下有些类要创建对象,你不写bean标签的话他是不认识的,那么就要告诉它去扫描,
           被打了注解的类就相当于之前在配置文件写的那个bean,目的都是为了创建类的对象;这个开关,会扫描指定包下的所有类,识别			类上的注解,然后进一步解析类中的属性设置,完成IOC 和 DI的功能

        2. context:component-scan : 用来指定扫描组件的标签
            base-package : 表示要扫描哪个包
                a. 可以写一个总的包名
                b. 可以写具体的包名,可以写多!使用 空格,逗号,分号,tab 分隔!
    -->
    <!--<context:component-scan base-package="com.itheima.dao.impl com.itheima.service.impl"/>-->
    <context:component-scan base-package="com.itheima"/>
</beans>
4) 功能测试
  • 创建一个测试类,调用Service
package com.itheima.test;

import com.itheima.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUserServiceImpl {

    @Test
    public void testAdd(){

        //1. 创建工厂
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        //2. 问工厂要对象
        UserService us = context.getBean(UserService.class);

        //3. 调用方法
        us.add();

    }
}

步骤小结
  1. 导入依赖

  2. 定义接口和实现类(dao 和 service)

  3. 在实现类上面打上注解 @Component

  4. 在属性上面打上注解@AutoWired

  5. 在applicationContext.xml里面打开扫描的开关

    <context:component-scan base-package=“com.itheima”/>

2. 注解使用详解

2.1 开启组件扫描
  • 在Spring中,如果要使用注解开发,就需要在applicationContext.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">


    <!--
        1. 告诉spring要扫描指定的包,因为这个包下有些类要创建对象
        context:component-scan : 用来指定扫描组件的标签
            base-package : 表示要扫描哪个包
                a. 可以写一个总的包名
                b. 可以写具体的包名,可以写多!使用 空格,逗号,分号,tab 分隔!
    -->
    <!--<context:component-scan base-package="com.itheima.dao.impl com.itheima.service.impl"/>-->
    <context:component-scan base-package="com.itheima"/>
</beans>
2.2 声明bean的注解【IOC】
简介
注解说明
@Component用在类上,相当于bean标签
@Controller用在web层类上,配置一个bean(是@Component的衍生注解)
@Service用在service层类上,配置一个bean(是@Component的衍生注解)
@Repository用在dao层类上,配置一个bean(是@Component的衍生注解)
  • @Component:类级别的一个注解,用于声明一个bean,使用不多
    • value属性:bean的唯一标识 (id值)。如果不配置,默认以首字母小写的类名为id
  • @Controller, @Service, @Repository,作用和@Component完全一样,但更加的语义化,使用更多
    • @Controller:用于web层的bean
    • @Service:用于Service层的bean
    • @Repository:用于dao层的bean
示例
  • UserDaoImpl类上使用注解@Repository
@Repository("userDao")
public class UserDaoImpl implements UserDao{
}
  • UserServiceImpl类上使用注解@Service
@Service("userService")
public class UserServiceImpl implements UserService{
}
  • UserController类上使用注解@Controller
@Controller
public class UserController{}
2.3 配置bean的注解 【IOC】
注解说明
@Scope相当于bean标签的scope属性
@PostConstruct相当于bean标签的init-method属性
@PreDestroy相当于bean标签的destory-method属性
配置bean的作用范围:
  • @Scope:配置bean的作用范围,相当于bean标签的scope属性。加在bean对象上

  • @Scope的常用值有:

  • singleton:单例的,容器中只有一个该bean对象

    • 何时创建:容器初始化时
    • 何时销毁:容器关闭时
  • prototype:多例的,每次获取该bean时,都会创建一个bean对象

    • 何时创建:获取bean对象时
    • 何时销毁:长时间不使用,垃圾回收
@Scope("prototype")
@Service("userService")
public class UserServiceImpl implements UserService{
    //...
}
配置bean生命周期的方法
  • @PostConstruct是方法级别的注解,用于指定bean的初始化方法
  • @PreDestroy是方法级别的注解,用于指定bean的销毁方法
package com.itheima.service.impl;

import com.itheima.dao.UserDao;
import com.itheima.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

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

/*
    需求:
        在UserServiceImpl里面调用UserDaoImpl的add方法
    分析:
        1. 把这两个类交给spring管理,让spring创建这两个类的对象
        2. 在UserServiceImpl里面注入UserDaoImpl 的对象
        3. 使用对象来调用方法
     步骤:
        1. 在UserServiceImpl和UserDaoImpl身上打注解 :  @Component
        2. 在UserServiceImpl里面定义属性,private UserDao userDao;
        3. 在属性身上打注解:  @AutoWired
        4. 在xml里面打开扫描的开关,这样spring才能知道哪些类要创建对象,里面的什么属性要注入!
 */


/*
    IOC的注解:
        @Component : 是通用的注解
            @Controller :针对web层
            @Service : 针对service层
            @Repository :针对dao层

            属性:
                value :  用来指定id值,如果不指定,那么将会把类名(首字母小写)作为id值!

        @Scope: 用来配置单例或者多例
            singleton: 单例, 默认就是单例
            prototype: 多例
        @PostConstruct: 创建对象的时候,调用指定的方法
        @PreDestroy: 销毁对象的时候调用指定的方法

 */
//@Component //组件
@Service("us")
@Scope("prototype")
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDaoImpl;

    public void add() {
        System.out.println("调用了UserServiceImpl的add方法~!");
        userDaoImpl.add();
    }

    //=========================================
    //对象创建完毕,就执行这个方法
    @PostConstruct
    public void init(){
        System.out.println("调用了UserServiceImpl的init方法~!");
    }

    //对象销毁的时候,就执行这个方法! 只有单例才会走这个方法
    @PreDestroy
    public void destroy(){
        System.out.println("调用了UserServiceImpl的destroy方法~!");
    }
}

2.4 依赖注入的注解【DI】
注解说明
@Autowired相当于property标签的ref 注入对象
@Qualifier结合@Autowired使用,用于根据名称(标识符)注入依赖
@Resource相当于@Autowired + @Qualifier
@Value相当于property标签的value ,注入普通 的属性
注入bean对象
  • @Autowired:用于byType(按照类型来找对象)注入bean对象,按照依赖(属性)的类型,从Spring容器中查找要注入的bean对象
      1. 如果找到一个,直接注入
      1. 如果找到多个,则以变量名为id,查找bean对象并注入
        1. 如果找不到,抛异常
  • @Qualifier:是按id注入,但需要和@Autowired配合使用。
  • @Resource:(是jdk提供的)用于注入bean对象(byName注入),相当于@Autowired + @Qualifier

绝大多数情况下,只要使用@Autowired注解注入即可

使用注解注入时,不需要set方法了

  • UserDao
package com.itehima.dao;

public interface UserDao {
    void add();
}
  • UserDao实现
package com.itheima.dao.impl;

import com.itheima.dao.UserDao;
import org.springframework.stereotype.Component;

@Repository
public class UserDaoImpl implements UserDao {
    public void add() {
        System.out.println("调用了UserdaoImpl的add方法~!~");
    }
}

  • UserService
package com.itehima.service;

public interface UserService {
    void add();
}
  • UserService实现
package com.itheima.service.impl;

import com.itheima.dao.UserDao;
import com.itheima.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

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

@Service("us02")
public class UserServiceImpl02 implements UserService {

    /*

        @Autowired :自动注入
            1. 按照的属性类型去找spring的工厂里面找对象,找到对象(只有一个)就注入进来
            2. 如果在spring的工厂里面,有多个对象满足这种类型,
                2.1 会拿着属性的名字当成id ,再去找对象,如果有匹配的就注入。
                2.2 如果还没有找到匹配的,就会报错!
        @Qualifier : 用于给@Autowired指定id值。告诉它用这个id去找对象注入
        @Resource :  等价于@Autowired + @Qualifier
            1. 按照id去找对象注入

         以上三个注解,就是用注入对象的,最常用的是@Autowired,而且95%的场景下,是只有一种实现类\

         @Value : 用来注入普通的数据
            1. 主要是用来注入properties里面的数据
            2. @Value("${properties里面的KEY}") , 要先导入进来properties的文件才可以注入
     */
    @Autowired
    private UserDao userDaoImpl02;

    @Autowired
    @Qualifier("userDaoImpl02")
    private UserDao abc;

    @Resource(name = "userDaoImpl02")
    private UserDao cba;

    @Value("深圳")
    private String address;

    public void add() {
        System.out.println("调用了UserServiceImpl02的add方法~!" + address);
        //userDaoImpl02.add();
        //abc.add();
        cba.add();
    }
}


  • 测试
package com.itheima.test;

import com.itheima.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUserServiceImpl02 {

    @Test
    public void testAdd(){

        //1. 创建工厂
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        //2. 问工厂要对象
        UserService us = (UserService) context.getBean("us02");


        //3. 调用方法
        us.add();

    }
}


注入普通值
  • @Value:注入简单类型值,例如:基本数据类型和String
@Service
public class UserServiceImpl02 implements UserService{
    
    @Value("深圳")
    private String address;
    
    //...
}
小结
  • 在xml里要开启组件扫描
<context:component-scan base-package="com.itheima"/>
  • 声明bean的注解(注册bean的注解) | IOC的注解
    • @Component("bean的名称"), 括号里面bean的名称就是id 值, 可以用在任何类上,注册bean对象
    • @Controller("bean名称"), @Service("bean名称"), @Repository("bean名称"),分别用于web层、service层、dao层的类上
  • 配置bean的注解
    • 如果要给一个bean设置作用范围:在bean上加注解@Scope("singleton/prototype")
    • 如果要给一个bean设置一个初始化方法:就在方法上加注解@PostConstruct
    • 如果要给一个bean设置一个销毁方法:就在方法上加注解@PreDestroy
  • 依赖注入的注解
    • @Autowired:byType注入,直接加在依赖项那个成员变量上
      • Spring会根据类型,从容器里查找bean并注入进来
      • 如果只找到一
      • 合的就会报错
    • @Autowired + @Qualifier("要注入的bean的名称"): 这种组合一般不怎么用,因为比较麻烦。
    • @Resource(name="要注入的bean的名称"):byName注入
    • @Value("要注入的简单值"):用于注入简单值
      • @Value("${properties里的key}"):把properties里指定key的值注入进来。前提条件是必须已经引入了properties文件

二、整合Mybatis

​ spring作为service层框架,对dao层和web层提供了很好的支持,整合Mybatis其实就是把mybatis的核心配置文件(SQLMapConfig.xml) 给去掉,并且把调用mybatis的代码简化,简化成注入对象,然后直接调用方法。

1. 导入依赖

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

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

        <!--整合Mybatis-->
        <!--1. 数据库依赖-->
        <!--2. mybatis本身的依赖-->
        <!--3. 日志依赖-->
        <!--4. 整合mybatis和spring的依赖-->
        <!--5. 导入连接池依赖-->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.4</version>
        </dependency>


        <!--spring对jdbc封装的jar包也要导入进来,否则mybatis无法整合-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.2.RELEASE</version>
        </dependency>
        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.5</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.5</version>
        </dependency>
        <!-- mysql 驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.32</version>
        </dependency>

        <!-- 添加slf4j日志api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.20</version>
        </dependency>
        <!-- 添加logback-classic依赖 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
        <!-- 添加logback-core依赖 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.3</version>
        </dependency>

    </dependencies>

2. 定义dao接口和映射文件

  • 接口
package com.itheima.dao;

import com.itheima.bean.Brand;
import org.springframework.stereotype.Repository;

import java.util.List;


public interface BrandDao {

    List<Brand> findAll();

}

  • 映射文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.dao.BrandDao">

    <resultMap id="brandMap" type="Brand">
        <result column="brand_name" property="brandName"/>
        <result column="company_name" property="companyName"/>
    </resultMap>

    <select id="findAll"  resultMap="brandMap">
        select * from tb_brand
    </select>
</mapper>

3. 定义service接口和实现

  • 接口
package com.itheima.service;

import com.itheima.bean.Brand;

import java.util.List;

public interface BrandService {

    /**
     * 查询所有
     * @return
     */
    List<Brand> findAll();
}

  • 实现
package com.itheima.service.impl;

import com.itheima.bean.Brand;
import com.itheima.dao.BrandDao;
import com.itheima.service.BrandService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/*
    需求:
        在service里面调用dao的findAll方法。
    步骤:
        1. 不写mybatis的核心配置文件了,但是核心配置文件的内容还是需要有的。由spring来接管这个工作。
        2.  mybatis的核心配置文件里面包含两个部分的内容: 环境配置和映射文件配置
            2.1 环境配置由 SqlSessionFactoryBean类来接管
            2.2 映射文件配置由MapperScannerConfigure类来接管
        3. 以上的两个类需要在applicationContext.xml中定义出来!

        4. 在service类上打注解: @Service
        5. 在service里面定义出来dao的属性,然后在属性上打注解 : @Autowired
 */
@Service
public class BrandServiceImpl implements BrandService {

    @Autowired
    private BrandDao brandDao;

    @Override
    public List<Brand> findAll() {
        System.out.println("调用了BrandServiceImpl的findAll方法~!");
        return brandDao.findAll();
    }
}

4. 定义配置文件

  • db.properties
db.driverClass=com.mysql.jdbc.Driver
db.jdbcUrl=jdbc:mysql://localhost:3306/day29_demo
db.user=root
db.password=root
  • applicationContext.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.itheima"/>

    <!--
        一、 整合MyBatis
            目标: 去掉mybatis的核心配置文件,由spring来接管他们的配置
    -->

    <!--0. 引入外部的properties-->
    <context:property-placeholder location="db.properties"/>

    <!--1. 让spring创建连接池对象-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${db.driverClass}"/>
        <property name="jdbcUrl" value="${db.jdbcUrl}"/>
        <property name="user" value="${db.user}"/>
        <property name="password" value="${db.password}"/>
    </bean>

    <!--
        2. 创建SqlSessionFactoryBean对象
            2.1 能够在背后帮助我们创建出来SqlSessionFactory对象
            2.2 还会接着创建SqlSession对象
            2.3 还会根据下面的扫描包的结果,创建Dao的代理对象
            2.4 还会把这个代理对象放到spring的IOC容器里面去管理。
            2.5 正是由于它有了管理的这一套机制,所以我们在service里面想要得到dao|mapper的代理对象
                就变得非常简单,只需要想平常需要对象一样,定义一个属性,然后再属性上打注解 @Autowired。
                即可调用dao的方法!
     -->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--2.1 注入连接池进来-->
        <property name="dataSource" ref="dataSource"/>

        <!--2.2 给JavaBean起别名-->
        <property name="typeAliasesPackage" value="com.itheima.bean"/>
    </bean>

    <!--
        3. 创建MapperScannerConfigurer
            作用: 用来扫描xml映射文件的
     -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.itheima.dao"/>
    </bean>

</beans>

5. 单元测试

package com.itheima.test;

import com.itheima.service.BrandService;
import com.itheima.service.impl.BrandServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestBrandServiceImpl {

    @Test
    public void testFindAll(){

        //1. 创建工厂
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        //2. 问工厂要对象
        BrandService bs = context.getBean(BrandServiceImpl.class);

        //3. 调用方法
        System.out.println(bs.findAll());
    }
}

三、纯注解开发IOC和DI

​ 在上边的CURD练习中,仍然有部分配置需要使用applicationContext.xml,那么能不能使用注解替换掉所有的xml呢?Spring提供了一些新注解,可以达到这个目标。

请注意:Spring提供的这部分新注解,并非为了完全代替掉XML,只是提供了另外一种配置方案

注解简介

注解说明
@Configuration被此注解标记的类,是配置类 等同于applicationContext.xml
@ComponentScan用在配置类上,开启注解扫描。使用basePackage属性(等效于value属性,所以直接写包名也行)指定扫描的包
@PropertySource用在配置类上,加载properties文件。使用value属性指定properties文件路径
@Import用在配置类上,引入子配置类。用value属性指定子配置类的Class
@Bean用在配置类的方法上,把返回值声明为一个bean。用name/value属性指定bean的id

注解详解

  • 导入依赖
<dependencies>
        <!-- c3p0连接池(也可以用其它连接池) -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>
        <!-- DBUtils工具包 -->
        <dependency>
            <groupId>commons-dbutils</groupId>
            <artifactId>commons-dbutils</artifactId>
            <version>1.7</version>
        </dependency>
        <!-- 数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.1.2.RELEASE</version>
        </dependency>
    </dependencies>
1 @Configuration配置类
  • @Configuration把一个Java类声明为核心配置类
    • 加上Java类上,这个Java类就成为了Spring的核心配置类,用于代替applicationContext.xml
    • @Component的衍生注解,所以:核心配置类也是bean,也会被spring管理起来,当然里边也可以注入依赖
/*
    @Configuration:
        1. 表示这个类是一个核心配置类
        2. 它的作用等价于以前的applicationContext.xml
        3. @Configuration 是从@Component注解衍生出来的,所以这个类也会被spring管理起来(创建对象)
 */
@Configuration
public class AppConfig {
}
2 配置类上的注解
  • @ComponentScan配置组件注解扫描

    • basePackages或者value属性:指定扫描的基本包
    • 等同于替代了applicationContext.xml里面的这句话
    <!--1. 打开包的扫描开关-->
     <context:component-scan base-package="com.itheima"/>
    
  • @PropertySource用于加载properties文件

    • value属性:指定propertis文件的路径,从类加载路径里加载
    • 等同于替代了applicationContext.xml里面的这句话
    <!--导入properties文件-->
    <context:property-placeholder location="classpath:db.properties"/>
    
  • @Import用于导入其它配置类

    • Spring允许提供多个配置类(模块化配置),在核心配置类里加载其它配置类
    • 相当于xml中的<import resource="模块化xml文件路径"/>标签
  • 核心配置类

package com.itheima.config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;

/*
    @Configuration:
        1. 表示这个类是一个核心配置类
        2. 它的作用等价于以前的applicationContext.xml
        3. @Configuration 是从@Component注解衍生出来的,所以这个类也会被spring管理起来(创建对象)
    @ComponentScan :
        1. 用来指定扫描包,等价于 <context:component-scan base-package=""/>
    @PropertyScource:
        1. 用来导入外部的properties文件,等价于<context:property-placeholder location=""/>
        2. 导入这个properties文件的时候,如果有错(1. 找不到这个文件,2.这个文件无法打开,)可以在
            名字的前面加上 classpath:
        3. 要想把properties里面的内容注入进来,就需要定义好对应的属性,然后使用@Value来注入值
            @Value("${KEY}")
     @Import:
        1. 可以用来导入子配置类
 */
@Configuration
//@ComponentScan("com.itheima")
//@PropertySource("db.properties")
@Import(AppConfig01.class) //导入子配置类
public class AppConfig {
    @Value("${db.driverClass}")
    private String driverClass;

    @Value("${db.jdbcUrl}")
    private String jdbcUrl;

    @Value("${db.user}")
    private String user;

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

    public void show(){
        System.out.println("driverClass = " + driverClass);
        System.out.println("jdbcUrl = " + jdbcUrl);
        System.out.println("user = " + user);
        System.out.println("password = " + password);
    }

    //==============================以下代码是说明@Bean=============================

    /*
        @Bean
            1. 打在方法身上,spring会来调用这个方法
            2. spring会把这个方法的返回值管理起来,丢到spring的工厂里面去
            3. 可以在@Bean的value属性里面设置对象的id,如果不设置,那么将会使用方法的名字作为id值
     */

    //1. 把QueryRunner对象交给spring管理,使用方法名字作为id值
    @Bean
    public QueryRunner runner01(){
        return new QueryRunner();
    }

    // 2. 把QueryRunner对象交给spring管理,使用属性来指定id值
    @Bean("run02")
    public QueryRunner runner02(){
        return new QueryRunner();
    }

    /*
        3.使用@Bean注解标记的方法,方法内部需要用到spring工厂(容器)里面的某一个对象,怎么办?
            3.1 此时可以在方法的参数上,写上想要的对象参数即可
                a. 其实它就是在方法参数的前面,隐藏着一个注解: @Autowired
            3.2 但是也要考虑出现极端的情况:如果在spring的容器里面,有多个对象满足这个参数的类型,咋办?
                a. 搭配使用@Qualifier ,指定id值。
                b. 投机取巧,把方法的参数名字,写成id的名字即可

     */
    @Bean
    public QueryRunner runner03(@Qualifier("dataSource") DataSource ds){
        System.out.println("ds===" + ds);
        return new QueryRunner(ds);
    }

    @Bean
    public QueryRunner runner04(DataSource dataSource2){
        System.out.println("dataSource2===" + dataSource2);
        return new QueryRunner(dataSource2);
    }

    @Bean
    public DataSource dataSource() throws PropertyVetoException {
        ComboPooledDataSource ds = new ComboPooledDataSource();
        ds.setDriverClass(driverClass);
        ds.setJdbcUrl(jdbcUrl);
        ds.setUser(user);
        ds.setPassword(password);
        return ds;
    }
   @Bean
    public DataSource dataSource2() throws PropertyVetoException {
        ComboPooledDataSource ds = new ComboPooledDataSource();
        ds.setDriverClass(driverClass);
        ds.setJdbcUrl(jdbcUrl);
        ds.setUser(user);
        ds.setPassword(password);
        return ds;
    }
}

  • 子配置类
package com.itheima.config;

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

@ComponentScan("com.itheima")
@PropertySource("db.properties")
public class AppConfig01 {
}

3 @Bean声明bean
1) @Bean定义bean
  • @Bean注解:方法级别的注解

    • 作用: 方法会由spring调用,并且把方法返回值声明成为一个bean,作用相当于<bean>标签 , 这个方法的返回值将会被Spring管理起来。

    • @Bean注解可以写在方法上,这些方法可以写在核心配置类里面,也可以写在其他的组件类里面,但是一般会写在核心配置类里面。

  • @Bean注解的属性:

    • value属性:bean的id。如果不设置,那么方法名就是bean的id
@Configuration
@ComponentScan("com.itheima")
public class AppConfig {
    
    ...

    //==============================以下代码是说明@Bean=============================

    /*
        @Bean
            1. 打在方法身上,spring会来调用这个方法
            2. spring会把这个方法的返回值管理起来,丢到spring的工厂里面去
            3. 可以在@Bean的value属性里面设置对象的id,如果不设置,那么将会使用方法的名字作为id值
     */

    //1. 把QueryRunner对象交给spring管理,使用方法名字作为id值
    @Bean
    public QueryRunner runner01(){
        return new QueryRunner();
    }

    // 2. 把QueryRunner对象交给spring管理,使用属性来指定id值
    @Bean("run02")
    public QueryRunner runner02(){
        return new QueryRunner();
    }

    /*
        3.使用@Bean注解标记的方法,方法内部需要用到spring工厂(容器)里面的某一个对象,怎么办?
            3.1 此时可以在方法的参数上,写上想要的对象参数即可
                a. 其实它就是在方法参数的前面,隐藏着一个注解: @Autowired
            3.2 但是也要考虑出现极端的情况:如果在spring的容器里面,有多个对象满足这个参数的类型,咋办?
                a. 搭配使用@Qualifier ,指定id值。
                b. 投机取巧,把方法的参数名字,写成id的名字即可

     */
    @Bean
    public QueryRunner runner03(@Qualifier("dataSource") DataSource ds){
        System.out.println("ds===" + ds);
        return new QueryRunner(ds);
    }

    @Bean
    public QueryRunner runner04(DataSource dataSource2){
        System.out.println("dataSource2===" + dataSource2);
        return new QueryRunner(dataSource2);
    }

    @Bean
    public DataSource dataSource() throws PropertyVetoException {
        ComboPooledDataSource ds = new ComboPooledDataSource();
        ds.setDriverClass(driverClass);
        ds.setJdbcUrl(jdbcUrl);
        ds.setUser(user);
        ds.setPassword(password);
        return ds;
    }
   @Bean
    public DataSource dataSource2() throws PropertyVetoException {
        ComboPooledDataSource ds = new ComboPooledDataSource();
        ds.setDriverClass(driverClass);
        ds.setJdbcUrl(jdbcUrl);
        ds.setUser(user);
        ds.setPassword(password);
        return ds;
    }
    

}
2) @Bean的依赖注入
  • @Bean注解的方法可以有任意参数,这些参数即是bean所需要的依赖,默认采用byType方式注入
  • 可以在方法参数上增加注解@Qualifier,用于byName注入
3) 完整代码
package com.itheima.config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;

/*
    @Configuration:
        1. 表示这个类是一个核心配置类
        2. 它的作用等价于以前的applicationContext.xml
        3. @Configuration 是从@Component注解衍生出来的,所以这个类也会被spring管理起来(创建对象)
    @ComponentScan :
        1. 用来指定扫描包,等价于 <context:component-scan base-package=""/>
    @PropertyScource:
        1. 用来导入外部的properties文件,等价于<context:property-placeholder location=""/>
        2. 导入这个properties文件的时候,如果有错(1. 找不到这个文件,2.这个文件无法打开,)可以在
            名字的前面加上 classpath:
        3. 要想把properties里面的内容注入进来,就需要定义好对应的属性,然后使用@Value来注入值
            @Value("${KEY}")
     @Import:
        1. 可以用来导入子配置类
 */
@Configuration
//@ComponentScan("com.itheima")
//@PropertySource("db.properties")
@Import(AppConfig01.class) //导入子配置类
public class AppConfig {
    @Value("${db.driverClass}")
    private String driverClass;

    @Value("${db.jdbcUrl}")
    private String jdbcUrl;

    @Value("${db.user}")
    private String user;

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

    public void show(){
        System.out.println("driverClass = " + driverClass);
        System.out.println("jdbcUrl = " + jdbcUrl);
        System.out.println("user = " + user);
        System.out.println("password = " + password);
    }

    //==============================以下代码是说明@Bean=============================

    /*
        @Bean
            1. 打在方法身上,spring会来调用这个方法
            2. spring会把这个方法的返回值管理起来,丢到spring的工厂里面去
            3. 可以在@Bean的value属性里面设置对象的id,如果不设置,那么将会使用方法的名字作为id值
     */

    //1. 把QueryRunner对象交给spring管理,使用方法名字作为id值
    @Bean
    public QueryRunner runner01(){
        return new QueryRunner();
    }

    // 2. 把QueryRunner对象交给spring管理,使用属性来指定id值
    @Bean("run02")
    public QueryRunner runner02(){
        return new QueryRunner();
    }

    /*
        3.使用@Bean注解标记的方法,方法内部需要用到spring工厂(容器)里面的某一个对象,怎么办?
            3.1 此时可以在方法的参数上,写上想要的对象参数即可
                a. 其实它就是在方法参数的前面,隐藏着一个注解: @Autowired
            3.2 但是也要考虑出现极端的情况:如果在spring的容器里面,有多个对象满足这个参数的类型,咋办?
                a. 搭配使用@Qualifier ,指定id值。
                b. 投机取巧,把方法的参数名字,写成id的名字即可

     */
    @Bean
    public QueryRunner runner03(@Qualifier("dataSource") DataSource ds){
        System.out.println("ds===" + ds);
        return new QueryRunner(ds);
    }

    @Bean
    public QueryRunner runner04(DataSource dataSource2){
        System.out.println("dataSource2===" + dataSource2);
        return new QueryRunner(dataSource2);
    }

    @Bean
    public DataSource dataSource() throws PropertyVetoException {
        ComboPooledDataSource ds = new ComboPooledDataSource();
        ds.setDriverClass(driverClass);
        ds.setJdbcUrl(jdbcUrl);
        ds.setUser(user);
        ds.setPassword(password);
        return ds;
    }
   @Bean
    public DataSource dataSource2() throws PropertyVetoException {
        ComboPooledDataSource ds = new ComboPooledDataSource();
        ds.setDriverClass(driverClass);
        ds.setJdbcUrl(jdbcUrl);
        ds.setUser(user);
        ds.setPassword(password);
        return ds;
    }
}

小结

  • 配置类上要加注解@Configuration 变成核心配置类,主要是用来替代applicationContext.xml

  • 要开启组件扫描,在配置类上@ComponentScan("com.itheima")

  • 如果要把jar包里的类注册成bean:

    • 在配置类里加方法,方法上加@Bean,会把方法返回值注册bean对象
  • 如果要引入外部的properties文件,在配置类上加@PropertySource("classpath:xxx.properties")

  • 引入模块配置类,在配置类上使用@Import(子配置类.class)

  • @Bean ,如果期望让spring来管理某个方法的返回值(注意: 这个返回值大多数都是对象,很少是一个普通的数据,比如:数字、字符串…)

四、整合Mybatis

1. 导入依赖

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

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

        <!--整合Mybatis-->
        <!--1. 数据库依赖-->
        <!--2. mybatis本身的依赖-->
        <!--3. 日志依赖-->
        <!--4. 整合mybatis和spring的依赖-->
        <!--5. 导入连接池依赖-->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.4</version>
        </dependency>


        <!--spring对jdbc封装的jar包也要导入进来,否则mybatis无法整合-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.2.RELEASE</version>
        </dependency>
        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.5</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.5</version>
        </dependency>
        <!-- mysql 驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.32</version>
        </dependency>

        <!-- 添加slf4j日志api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.20</version>
        </dependency>
        <!-- 添加logback-classic依赖 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
        <!-- 添加logback-core依赖 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.3</version>
        </dependency>

    </dependencies>

2. 定义dao接口和映射文件

  • 接口
package com.itheima.dao;

import com.itheima.bean.Brand;
import org.springframework.stereotype.Repository;

import java.util.List;


public interface BrandDao {

    List<Brand> findAll();

}

  • 注解形式配置SQL语句

    @Results(id="brandMap" , value = {
                @Result(column = "brand_name" , property = "brandName"),
                @Result(column = "company_name" , property = "companyName"),
        })
        @Select("select * from tb_brand")
        List<Brand> findAll();
    
  • 映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.dao.BrandDao">

    <resultMap id="brandMap" type="Brand">
        <result column="brand_name" property="brandName"/>
        <result column="company_name" property="companyName"/>
    </resultMap>

    <select id="findAll"  resultMap="brandMap">
        select * from tb_brand
    </select>
</mapper>

3. 定义service接口和实现

  • 接口
package com.itheima.service;

import com.itheima.bean.Brand;

import java.util.List;

public interface BrandService {

    /**
     * 查询所有
     * @return
     */
    List<Brand> findAll();
}

  • 实现
package com.itheima.service.impl;

import com.itheima.bean.Brand;
import com.itheima.dao.BrandDao;
import com.itheima.service.BrandService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/*
    需求:
        在service里面调用dao的findAll方法。
    步骤:
        1. 不写mybatis的核心配置文件了,但是核心配置文件的内容还是需要有的。由spring来接管这个工作。
        2.  mybatis的核心配置文件里面包含两个部分的内容: 环境配置和映射文件配置
            2.1 环境配置由 SqlSessionFactoryBean类来接管
            2.2 映射文件配置由MapperScannerConfigure类来接管
        3. 以上的两个类需要在applicationContext.xml中定义出来!

        4. 在service类上打注解: @Service
        5. 在service里面定义出来dao的属性,然后在属性上打注解 : @Autowired
 */
@Service
public class BrandServiceImpl implements BrandService {

    @Autowired
    private BrandDao brandDao;

    @Override
    public List<Brand> findAll() {
        System.out.println("调用了BrandServiceImpl的findAll方法~!");
        return brandDao.findAll();
    }
}

4. 定义配置文件

  • db.properties
db.driverClass=com.mysql.jdbc.Driver
db.jdbcUrl=jdbc:mysql://localhost:3306/day29_demo
db.user=root
db.password=root
  • AppConfig.java

@Configuration // 表示这个类是一个核心配置类,等价于:applicationContext.xml
@ComponentScan("com.itheima") // 组件扫描
@PropertySource("classpath:db.properties") // 导入properties文件
public class AppConfig {

    @Value("${db.driverClass}")
    private String driverClass;

    @Value("${db.jdbcUrl}")
    private String jdbcUrl;

    @Value("${db.user}")
    private String user;

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


    @Bean
    public DataSource ds() throws PropertyVetoException {

        ComboPooledDataSource ds = new ComboPooledDataSource();

        
        ds.setDriverClass("com.mysql.jdbc.Driver");
        ds.setJdbcUrl("jdbc:mysql://localhost:3306/day29_demo");
        ds.setUser("root");
        ds.setPassword("root");

        return ds;
    }

    @Bean   
    public SqlSessionFactoryBean factoryBean(DataSource ds){
         SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
         bean.setTypeAliasesPackage("com.itheima.bean");
         bean.setDataSource(ds);
         return bean;
    }

    @Bean
           //单独这样写会报错
    public MapperScannerConfigurer configurer(){
        MapperScannerConfigurer m = new MapperScannerConfigurer();
        m.setBasePackage("com.itheima.dao");
        return m;
    }
}

扫描mapper的这个方法会有问题:

  1. 首先要理解整个代码的执行过程:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qVSIt1kB-1664458497654)(imgs/image-20220929201354742.png)]

  1. 原因分析:
/*
    1. 如果在类当中使用了MapperScannerConfigurer ,那么将会导致 AppConfig类被初始化的时机提前,使得属性都无法完成注入。
    2. 解决的办法:
        2.1 把这个方法标记成 static 静态方法
        2.2 把这个方法放到隔壁的配置类中,然后在这个类里面使用 @Import来导入它
        2.3 不写这个方法了,只需要在配置类上打上注解 @MapperScan("com.itheima.dao")    */
    @Bean
    public MapperScannerConfigurer msc() {
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
        msc.setBasePackage("com.itheima.dao");
        return msc;
    }

5. 单元测试

package com.itheima.test;

import com.itheima.service.BrandService;
import com.itheima.service.impl.BrandServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestBrandServiceImpl {

    @Test
    public void testFindAll(){

        //1. 创建工厂
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        //2. 问工厂要对象
        BrandService bs = context.getBean(BrandServiceImpl.class);

        //3. 调用方法
        System.out.println(bs.findAll());
    }
}

五、Spring整合Junit【掌握】

​ 在上边的CURD中,单元测试类里还需要我们自己去创建ApplicationContext,并自己去获取bean对象。Spring提供了整合Junit的方法,让单元测试更简洁方便。

注解简介

注解说明
@RunWith用在测试类上,用于声明不再使用Junit,而是使用Spring提供的运行环境
@ContextConfiguration用在测试类上,用于指定Spring配置类、或者Spring的配置文件

Spring提供了单元测试的运行环境:SpringJunit4ClassRunner,配置到@RunWith注解上:

@RunWith(SpringJunit4ClassRunner.class)

  • 要使用以上注解,需要导入jar包依赖:spring-testjunit
 <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.1.2.RELEASE</version>
        </dependency>

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

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

使用示例

步骤
  1. 在pom.xml文件中增加依赖:spring-testjunit

  2. 修改单元测试类

    1. 在单元测试类上增加注解:@RunWith(SpringJunit4ClassRunner.class)

      目的:使用Spring的单元测试运行器,替换Junit原生的运行器

    2. 在单元测试类上增加注解:@ContextConfiguration()

      目的:指定配置文件或配置类

    3. 在测试类里的依赖项上,直接使用@Autowired注入依赖

实现
  1. 在pom.xml文件中增加依赖:spring-testjunit

     <dependencies>
            <!-- Spring -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.1.2.RELEASE</version>
            </dependency>
    
            <!--spring单元测试的依赖-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>5.1.2.RELEASE</version>
            </dependency>
    
            <!--Junit的依赖-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
            </dependency>
    
        </dependencies>
    
  2. UserService接口

package com.itheima.service;

public interface UserService {
    void add();
}
  1. UserServiceImpl实现类
package com.itheima.service.impl;

import com.itheima.service.UserService;

public class UserServiceImpl implements UserService {
    public void add() {
        System.out.println("调用了UserServiceImpl的add方法!~");
    }
}

  1. applicationContext.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="us" class="com.itheima.service.impl.UserServiceImpl"/>
</beans>
  1. 修改单元测试类
package com.itheima.test;

import com.itheima.service.UserService;
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.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;


/*
    @RunWith
        1. 表示使用的单元测试的环境,不再是以前的Junit的测试环境,而是spring针对Junit提供的测试环境
        2. 这套spring提供的测试环境在背后会帮助我们创建工厂。
    @ContextConfiguration
        1. 告诉spring的测试环境,配置文件在哪里?
        2. classpath: 这是固定写法,表示要在类路径底下找配置文件。
 */

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestUserServiceImpl02 {

    //让spring把想要用到的对象给注入进来!
    // 这个注解是自动注入的意思,让spring把对象注入进来。明天讲!
    @Autowired
    private UserService us;

    @Test
    public void testAdd(){

        /*ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        UserService us = (UserService) context.getBean("us");
        */
        us.add();

    }
}

小结

  1. 导入依赖

  2. 在测试类上打注解

  3. 直接在测试类里面使用@Autowired注入对象。

六、Lombok

/*
    使用lombok的先决条件;
        1. idea安装lombok插件 : 目的是为了生成代码
        2. 项目导入lombok的依赖: 目的是为了写注解

        @AllArgsConstructor :  用来创建满参的构造函数
        @NoArgsConstructor: 用来创建无参的构造函数

        @Setter : 用来生成set方法
        @Getter : 用来生成get方法
        @ToString: 用来生成 toString方法

        @Data :
            创建get 和 set 和 toString方法

        @Builder:
            会生成构建者对象,使用它可以更加灵活的构建的JavaBean对象!
 */

@Builder
@Data
@ToString
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class Brand {
    private int id;
    private String brandName;
    private String cName;
    private String description;
    private int status;
    private int ordered;

    private List<String> list = new ArrayList<>();
}

@Data 其实还包含equals那些方法

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值