Spring框架学习--xml和Annotation方式实现IOC

Annotation+Xml的spring-IOC和全Annotation的spring-IOC

文章目录

  • Annotation+Xml的spring-IOC和全Annotation的spring-IOC
    • 学习目标
    • 第二章 基于Annotation+Xml的spring-IOC【重点】
      • 1、annotation+xml【入门案例】(5)
        • 【1】目标
        • 【2】实现
          • 【2.1】创建项目
          • 【2.3】改写AccountDaoImpl
          • 【2.4】改写AccountServiceImpl
          • 【2.5】改写AccountController
          • 【2.6】测试
        • 【3】入门案例小结
    • 第三章 spring基础注解【重点】
      • 1、注解和xml对照表
      • 2、bean实例化相关
        • 【1】@Component
        • 【2】@Controller、@Service、@Repository(6)
          • 【2.1】目标
          • 【2.2】实现
            • 【2.2.1】创建服务
            • 【2.2.2】修改AccountController
            • 【2.2.3】修改AccountServiceImpl
            • 【2.2.4】修改AccountDaoImpl
            • 【2.2.5】测试
          • 【2.3】衍生小结
      • 3、bean依赖注入相关
        • 【1】@Autowired、@Qualifier(7)
          • 【1.1】目标
          • 【1.2】实现
            • 【1.2.1】创建项目
            • 【1.2.2】第一次运行
            • 【1.2.3】新增AccountDaoImplB
            • 【1.2.4】修改AccountServiceImpl
            • 【1.2.5】第二次运行
            • 【1.2.6】再次修改AccountServiceImpl
            • 【1.2.7】第三次运行
            • 【1.2.8】再次修改AccountServiceImpl
            • 【1.2.9】第四次运行
          • 【1.3】@Autowired、@Qualifier小结
        • 【2】@Resource(8)
          • 【2.1】目标
          • 【2.2】实现
            • 【2.2.1】创建项目
            • 【2.2.2】修改AccountServiceImpl
            • 【2.2.3】第一次运行
            • 【2.2.4】再次修改AccountServiceImpl
            • 【2.2.5】第二次运行
            • 【2.2.6】修改dao层
            • 【2.2.7】再次修改AccountServiceImpl
            • 【2.2.8】第三次运行
            • 【2.2.9】再次修改AccountServiceImpl
            • 【2.2.10】第四次运行
          • 【2.3】@Resource小结
        • 【3】@Value(9)
            • 【3.1】创建项目
            • 【3.2】添加DbConfig类
            • 【3.3】添加DbConfigTest测试
            • 【3.4】运行结果
            • 【3.5】@Value小结
      • 4、bean作用域@Scope (10)
        • 【1】目标
        • 【2】实现
          • 【2.1】创建项目
          • 【2.2】修改DbConfig
          • 【2.3】修改DbConfigTest
          • 【2.4】运行DbConfigTest
        • 【3】作用域@Scope小结
      • 5、bean生命周期(11)
        • 【1】目标
        • 【2】实现
          • 【2.1】创建项目
          • 【2.2】修改DbConfig
          • 【2.3】修改DbConfigTest
          • 【2.4】运行结果
        • 【3】bean生命周期小结
    • 第四章 基于全Annotation的spring-IOC【重点】
      • 1、思考
      • 2、annotation案例(12)
        • 【1】配置类注解与XML对照表
        • 【2】加载方式
        • 【3】目标
        • 【4】实现
          • 【4.1】创建项目
          • 【4.2】编写SpringConfig类
          • 【4.3】编写DbConfig类
          • 【4.4】修改ClientControllergTest
          • 【4.5】测试
      • 3、小结
    • 第五章 Spring整合junit【掌握】
      • 1、思考
      • 2、测试注解说明
      • 3、XML方式(13)
        • 【1】目标
        • 【2】实现
          • 【2.1】创建项目
          • 【2.2】导入spring-test依赖
          • 【2.3】修改ClientControllerTest
          • 【2.4】测试结果
        • 【3】小结
      • 4、全注解方式(14)
        • 【1】目标
        • 【2】实现
          • 【2.1】创建项目
          • 【2.2】导入spring-test依赖
          • 【2.3】修改AccountControllerTest
          • 【2.4】测试结果
        • 【3】小结

学习目标

1、了解JdbcTemplate使用
2、完成spring-ioc-xml案例
3、完成spring-ioc-xml+annotation案例
4、完成spring-ioc-annotation全注解案例
5、掌握spring的配置注解
6、完成spring整合junit

第二章 基于Annotation+Xml的spring-IOC【重点】

1、annotation+xml【入门案例】(5)

​ 前面的课程使用xml方式配置spring IOC我都已经会了,在我们前面学习的知识点中,好像注解也是用于配置的。不知道在spring框架中,该如何使用注解实现配置呢?

入门案例中使用到的annotation和xml标签对照表

XMLAnnotation说明
< bean >@Component声明一个bean交于spring容器管理
ref属性@Autowired输入赋值(DI机制)

【注解生效】–>约定大于配置

标签说明
context:component-scan启动自动扫描机制,使用base-package属性指定扫描包位置

通常情况下我们在创建spring项目的时候在xml配置文件中都会配置这个标签,配置完这个标签后,spring就会去自动扫描base-package对应的路径或者该路径的子包下面的java文件,如果扫描到文件中带有@Component这个注解的类,则把这些类注册为bean ,如果在类的属性上有@Autowired注解,我们就会按属性的类型去找对应的bean去注入

【1】目标

1、掌握spring的使用@Component创建bean-<bean>(IOC)
2、掌握@Autowired的di注入(依赖注入)
3、掌握bean.xml中配置标签context:component-scan使注解生效(约定大于配置)

【2】实现

步骤:
	1、修改bean.xml
	2、修改AccountDaoImpl
	3、修改AccountServiceImpl
	4、修改AccountController
【2.1】创建项目

创建spring-day02-05annotation-xml-ioc

在这里插入图片描述

【2.2】修改bean.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
">

    <!--约定大于配置扫描-->
    <context:component-scan base-package="com.test.spring"/>
    <!--读取配置文件-->
    <context:property-placeholder location="classpath:db.properties"/>

    <!--
    - c3p0数据源:com.mchange.v2.c3p0.ComboPooledDataSource
    - dbcp数据源:org.apache.commons.dbcp.BasicDataSource
    - druid数据源:com.alibaba.druid.pool.DruidDataSource
    -->
    <!--1、创建数据源(API)-->
    <!--配置出druidDataSource数据源-->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${dataSource.driverClassName}"></property>
        <property name="url" value="${dataSource.url}"></property>
        <property name="username" value="${dataSource.username}"></property>
        <property name="password" value="${dataSource.password}"></property>
    </bean>

    <!--2、为jdbctemplate注入数据源(API)-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="druidDataSource"/>
    </bean>

<!--    &lt;!&ndash;3、为dao层注入jdbctemplate&ndash;&gt;-->
<!--    <bean id="accountDao" class="com.test.spring.dao.impl.AccountDaoImpl">-->
<!--        <property name="jdbcTemplate" ref="jdbcTemplate"/>-->
<!--    </bean>-->

<!--    &lt;!&ndash;4、为service层注入dao&ndash;&gt;-->
<!--    <bean id="accountService" class="com.test.spring.service.impl.AccountServiceImpl">-->
<!--        <property name="accountDao" ref="accountDao"/>-->
<!--    </bean>-->

<!--    &lt;!&ndash;5、为controller层注入service&ndash;&gt;-->
<!--    <bean id="clientController" class="com.test.spring.controller.ClientController">-->
<!--        <property name="accountService" ref="accountService"/>-->
<!--    </bean>-->

</beans>

【2.3】改写AccountDaoImpl

在这里插入图片描述

package com.test.spring.dao.impl;

import com.test.spring.dao.AccountDao;
import com.test.spring.mapper.AccountMapper;
import com.test.spring.pojo.Account;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @Description:查询所有用户
 * 对于增删改使用update
 * 对于查询返回未list的使用query
 * 对于返回单个对象的使用queryForObject
 */
@Component("accountDao")
public class AccountDaoImpl implements AccountDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;


    @Override
    public int saveAccount(Account account) {
        String sql = "INSERT INTO `account` ( `account_name`, `money`) VALUES ( ?, ?)";
        return jdbcTemplate.update(sql, account.getAccountName(),account.getMoney());
    }

    @Override
    public int deleteAccountById(int id) {
        String sql = "delete from `account` where id =?";
        return jdbcTemplate.update(sql,id);
    }

    @Override
    public int updateAccountById(Account account) {
        String sql = "update account set account_name=?,money=? where id = ?";
        return jdbcTemplate.update(sql, account.getAccountName(),account.getMoney(),account.getId());
    }

    @Override
    public Account findAccountById(int id) {
        String sql = "select * from account where id =?";
        return jdbcTemplate.queryForObject(sql, new AccountMapper(),id);
    }

    @Override
    public List<Account> findAll() {
        String sql = "select * from account";
        return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Account.class));
    }

    @Override
    public Integer countAccount() {
        String sql = "select count(1) from account";
        return jdbcTemplate.queryForObject(sql, Integer.class);
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

}



【2.4】改写AccountServiceImpl

在这里插入图片描述

package com.test.spring.service.impl;

import com.test.spring.dao.AccountDao;
import com.test.spring.pojo.Account;
import com.test.spring.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @Description:业务实现类
 */
@Component("accountService")
public class AccountServiceImpl implements AccountService {

    //注入dao
    @Autowired
    private AccountDao accountDao;

    @Override
    public int saveAccount(Account account) {
        return accountDao.saveAccount(account);
    }

    @Override
    public int deleteAccountById(int id) {
        return accountDao.deleteAccountById(id);
    }

    @Override
    public int updateAccountById(Account account) {
        return accountDao.updateAccountById(account);
    }

    @Override
    public Account findAccountById(int id) {
        return accountDao.findAccountById(id);
    }

    @Override
    public List<Account> findAll() {

        return accountDao.findAll();
    }

    @Override
    public Integer countAccount() {
        return accountDao.countAccount();
    }

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


【2.5】改写AccountController

在这里插入图片描述

package com.test.spring.controller;

import com.test.spring.pojo.Account;
import com.test.spring.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @Description:客户端调用
 */
@Component("clientController")
public class ClientController {

    @Autowired
    private AccountService accountService;

    /**
     * 创建用户
     */
    public int saveAccount(Account account) {
        return accountService.saveAccount(account);
    }

    /**
     * 删除用户
     */
    public int deleteAccountById(int id) {
        return accountService.deleteAccountById(id);
    }

    /**
     * 修改用户
     */
    public int updateAccountById(Account account) {
        return accountService.updateAccountById(account);
    }


    /**
     * 按ID查询用户
     */
    public Account findAccountById(int id) {
        return accountService.findAccountById(id);
    }

    /**
     * 统计用户个数
     */
    public Integer countAccount() {
        return accountService.countAccount();
    }

    /**
     * 查询所有用户
     */
    public List<Account> findAll() {
        return accountService.findAll();
    }

    public void setAccountService(AccountService accountService) {
        this.accountService = accountService;
    }
}


【2.6】测试

执行ClientControllergTest的findAll()测试

在这里插入图片描述

【3】入门案例小结

@Component注解的作用: 标识了一个受Spring管理的组件
    使用方法:
      在类上使用该注解,把资源让spring来管理。
      相当于在xml中配置一个bean。 
      相当于:<bean id="" class=""> 
    value属性: 指定bean的id。
    如果不指定value属性,默认bean的id是当前类的类名。首字母小写。
    
@Autowired:
	使用方法:
	  在属性上使用该注解,相当于 bean标签的ref=""属性
	  
context:component-scan:
    使用自动扫描使得注解生效
	使用方式:
        第一步:导入空间和约束
        第二步:context:component-scan 申明扫描
               base-package:扫描的位置

第三章 spring基础注解【重点】

1、注解和xml对照表

注解xml说明
@Component父注解
@Controller:用于表现层的注解
@Service:用于业务层的注解
@Repository:一般用于持久层的注解
< bean id=“” class=“”>声明bean交于springIOC管理
@Scopescope=“singleton/prototype”生命周期
@PostConstructinit-method初始化方法
@PreDestroydestroy-method销毁方法
@Autowired、@Qualifier
@Resource
ref=“自定义类型”依赖注入
@Valuevalue=“基础数据类型”基本数据类型注入

2、bean实例化相关

【1】@Component

在入门案例中,我们有使用到@component注解,我们现在回顾一下:

@Component注解的作用: 标识了一个受Spring管理的bean
    使用方法:
      在类上使用该注解,把资源让spring来管理。
	  相当于在xml中配置一个bean:
      		<bean id="" class=""> 
    value属性: 
      指定bean的id,默认bean的id是当前类的类名。首字母小写。

【2】@Controller、@Service、@Repository(6)

@Controller @Service @Repository 
他们三个注解都是针对每层的衍生注解,他们的作用及属性都是一模一样的。 
他们只不过是提供了更加明确的语义化。 
    @Controller:一般用于表现层的注解。 
    @Service:一般用于业务层的注解。 
    @Repository:一般用于持久层的注解。
【2.1】目标
使用@Controller、@Service、@Repository注解完成controller,service和dao的bean装配
【2.2】实现
【2.2.1】创建服务

创建spring-day02-06annotation-xml-ioc-csr

在这里插入图片描述

【2.2.2】修改AccountController

使用@Controller注解

package com.test.spring.controller;

import com.test.spring.pojo.Account;
import com.test.spring.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import java.util.List;

/**
 * @Description:客户端调用
 */
@Controller("clientController")
public class ClientController {

    @Autowired
    private AccountService accountService;

    /**
     * 创建用户
     */
    public int saveAccount(Account account) {
        return accountService.saveAccount(account);
    }

    /**
     * 删除用户
     */
    public int deleteAccountById(int id) {
        return accountService.deleteAccountById(id);
    }

    /**
     * 修改用户
     */
    public int updateAccountById(Account account) {
        return accountService.updateAccountById(account);
    }


    /**
     * 按ID查询用户
     */
    public Account findAccountById(int id) {
        return accountService.findAccountById(id);
    }

    /**
     * 统计用户个数
     */
    public Integer countAccount() {
        return accountService.countAccount();
    }

    /**
     * 查询所有用户
     */
    public List<Account> findAll() {
        return accountService.findAll();
    }

    public void setAccountService(AccountService accountService) {
        this.accountService = accountService;
    }
}


【2.2.3】修改AccountServiceImpl

使用@service注解


/**
 * @Description:业务实现类
 */
@Service("accountService")
public class AccountServiceImpl implements AccountService {

    /**
     * @Description
     * Autowired:
     *      作用:
     * 	        默认按照bean的类型注入数据,如果类型相同,则按名称注入
     *      属性:
     * 	        required:指定目标bean是否必须存在于spring的IOC容器(true必须存在;false:可以不存在;默认true)
     * @return
     */
    @Autowired
    private AccountDao accountDao;

    @Override
    public int saveAccount(Account account) {
        return accountDao.saveAccount(account);
    }

    @Override
    public int deleteAccountById(int id) {
        return accountDao.deleteAccountById(id);
    }

    @Override
    public int updateAccountById(Account account) {
        return accountDao.updateAccountById(account);
    }

    @Override
    public Account findAccountById(int id) {
        return accountDao.findAccountById(id);
    }

    @Override
    public List<Account> findAll() {

        return accountDao.findAll();
    }

    @Override
    public Integer countAccount() {
        return accountDao.countAccount();
    }

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

【2.2.4】修改AccountDaoImpl

使用@Repository注解


/**
 * @Description:查询所有用户
 * 对于增删改使用update
 * 对于查询返回未list的使用query
 * 对于返回单个对象的使用queryForObject
 */
@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;


    @Override
    public int saveAccount(Account account) {
        String sql = "INSERT INTO `account` ( `account_name`, `money`) VALUES ( ?, ?)";
        return jdbcTemplate.update(sql, account.getAccountName(),account.getMoney());
    }

    @Override
    public int deleteAccountById(int id) {
        String sql = "delete from `account` where id =?";
        return jdbcTemplate.update(sql,id);
    }

    @Override
    public int updateAccountById(Account account) {
        String sql = "update account set account_name=?,money=? where id = ?";
        return jdbcTemplate.update(sql, account.getAccountName(),account.getMoney(),account.getId());
    }

    @Override
    public Account findAccountById(int id) {
        String sql = "select * from account where id =?";
        return jdbcTemplate.queryForObject(sql, new AccountMapper(),id);
    }

    @Override
    public List<Account> findAll() {
        String sql = "select * from account";
        return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Account.class));
    }

    @Override
    public Integer countAccount() {
        String sql = "select count(1) from account";
        return jdbcTemplate.queryForObject(sql, Integer.class);
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

}

【2.2.5】测试

执行ClientControllergTest的findAll()测试
在这里插入图片描述

【2.3】衍生小结
Spring提供了装配bean的四个注解:
1、@Component:装配的对象装配注解
2、@Controller:装配表现层的注解
3、@Service:装配业务层的注解
4、@Repository:装配持久层的注解

3、bean依赖注入相关

【1】@Autowired、@Qualifier(7)

@Autowired
作用:
默认按照bean的类型注入数据,如果类型相同,则按名称注入
属性:
required:指定目标bean是否必须存在于spring的IOC容器(true必须存在;false:可以不存在;默认true)

@Qualifier
作用:
@Autowired注解一起使用,指定在按照bean类型注入的基础上,再按照bean的名称注入
属性:
value:指定bean的名称

【1.1】目标
1、使用@Autowired,且理解他的匹配方式
2、@Qualifier与@Autowired一起使用,且理解他的使用方式

【1.2】实现
【1.2.1】创建项目

创建spring-day02-07annotation-xml-ioc-autowired
在这里插入图片描述

修改AccountDaoImpl添加打印

package com.itheima.spring.dao.impl;

import com.itheima.spring.dao.AccountDao;
import com.itheima.spring.mapper.AccountMapper;
import com.itheima.spring.pojo.Account;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @Description:账户dao接口定义实现
 */
@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {

.........

    @Override
    public List<Account> findAll() {
        System.out.println("执行了AccountDaoImpl(A)");
        String sql = "select * from account";
        return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Account.class));
    }
......
}

【1.2.2】第一次运行

执行AccountControllerTest的findAll()测试

此时AccountDao只有一个实现类AccountDaoImpl,AccountServiceImpl直接按照AccountDao这个类型注入

在这里插入图片描述

【1.2.3】新增AccountDaoImplB

指定@Repository(“accountDaoB”)

package com.test.spring.dao.impl;

import com.test.spring.dao.AccountDao;
import com.test.spring.mapper.AccountMapper;
import com.test.spring.pojo.Account;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @Description:查询所有用户B
 */
@Repository("accountDaoB")
public class AccountDaoImplB implements AccountDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public int saveAccount(Account account) {
        String sql = "INSERT INTO `account` ( `account_name`, `money`) VALUES ( ?, ?)";
        return jdbcTemplate.update(sql, account.getAccountName(),account.getMoney());
    }

    @Override
    public int deleteAccountById(int id) {
        String sql = "delete from `account` where id =?";
        return jdbcTemplate.update(sql,id);
    }

    @Override
    public int updateAccountById(Account account) {
        String sql = "update account set account_name=?,money=? where id = ?";
        return jdbcTemplate.update(sql, account.getAccountName(),account.getMoney(),account.getId());
    }

    @Override
    public Account findAccountById(int id) {
        String sql = "select * from account where id =?";
        return jdbcTemplate.queryForObject(sql, new AccountMapper(),id);
    }

    @Override
    public List<Account> findAll() {
        System.out.println("执行了AccountDaoImpl(B)");
        String sql = "select * from account";
        return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Account.class));
    }

    @Override
    public Integer countAccount() {
        String sql = "select count(1) from account";
        return jdbcTemplate.queryForObject(sql, Integer.class);
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

}

【1.2.4】修改AccountServiceImpl

@Service("accountService")
public class AccountServiceImpl implements AccountService {

    /**
     * @Description
     * Autowired:
     *      作用:
     * 	        默认按照bean的类型注入数据,如果类型相同,则按名称注入
     *      属性:
     * 	        required:指定目标bean是否必须存在于spring的IOC容器(true必须存在;false:可以不存在;默认true)
     * Qualifier
     * 作用:
     * 	与@Autowired注解一起使用,指定在按照bean类型注入的基础上,再按照bean的名称注入
     * 属性:
     */
    @Autowired
    private AccountDao accountDaoB;

    @Override
    public int saveAccount(Account account) {
        return accountDaoB.saveAccount(account);
    }

    @Override
    public int deleteAccountById(int id) {
        return accountDaoB.deleteAccountById(id);
    }

    @Override
    public int updateAccountById(Account account) {
        return accountDaoB.updateAccountById(account);
    }

    @Override
    public Account findAccountById(int id) {
        return accountDaoB.findAccountById(id);
    }

    @Override
    public List<Account> findAll() {

        return accountDaoB.findAll();
    }

    @Override
    public Integer countAccount() {
        return accountDaoB.countAccount();
    }

}

【1.2.5】第二次运行

执行AccountControllerTest的findAll()测试
此时AccountDao的实现类有2个:AccountDaoImpl和AccountDaoImplB,但是AccountDaoImplB由注解@Repository(“accountDaoB”)指定的名称为“accountDaoB”,AccountServiceImpl中的属性名称为accountDaoB,所以注入的为:AccountDaoImplB

在这里插入图片描述

【1.2.6】再次修改AccountServiceImpl

/**
 * @Description:业务实现类
 */
@Service("accountService")
public class AccountServiceImpl implements AccountService {

    /**
     * @Description
     * Autowired:
     *      作用:
     * 	        默认按照bean的类型注入数据,如果类型相同,则按名称注入
     *      属性:
     * 	        required:指定目标bean是否必须存在于spring的IOC容器(true必须存在;false:可以不存在;默认true)
     * Qualifier
     * 作用:
     * 	与@Autowired注解一起使用,指定在按照bean类型注入的基础上,再按照bean的名称注入
     * 属性:
     */
    @Autowired
    private AccountDao accountDaoC;

    @Override
    public int saveAccount(Account account) {
        return accountDaoC.saveAccount(account);
    }

    @Override
    public int deleteAccountById(int id) {
        return accountDaoC.deleteAccountById(id);
    }

    @Override
    public int updateAccountById(Account account) {
        return accountDaoC.updateAccountById(account);
    }

    @Override
    public Account findAccountById(int id) {
        return accountDaoC.findAccountById(id);
    }

    @Override
    public List<Account> findAll() {

        return accountDaoC.findAll();
    }

    @Override
    public Integer countAccount() {
        return accountDaoC.countAccount();
    }

}

【1.2.7】第三次运行

此时AccountDao的实现类有2个:AccountDaoImpl和AccountDaoImplB,AccountServiceImpl中的属性名称为accountDaoC,而AccountDaoImpl和AccountDaoImplB指定的名称为:accountDao、accountDaoB,并没有accountDaoC,所以报错

在这里插入图片描述

【1.2.8】再次修改AccountServiceImpl

添加@Qualifier(“accountDao”)


/**
 * @Description:业务实现类
 */
@Service("accountService")
public class AccountServiceImpl implements AccountService {

    /**
     * @Description
     * Autowired:
     *      作用:
     * 	        默认按照bean的类型注入数据,如果类型相同,则按名称注入
     *      属性:
     * 	        required:指定目标bean是否必须存在于spring的IOC容器(true必须存在;false:可以不存在;默认true)
     * Qualifier
     * 作用:
     * 	与@Autowired注解一起使用,指定在按照bean类型注入的基础上,再按照bean的名称注入
     * 属性:
     */
    @Autowired
    @Qualifier("accountDao")
    private AccountDao accountDaoC;

    @Override
    public int saveAccount(Account account) {
        return accountDaoC.saveAccount(account);
    }

    @Override
    public int deleteAccountById(int id) {
        return accountDaoC.deleteAccountById(id);
    }

    @Override
    public int updateAccountById(Account account) {
        return accountDaoC.updateAccountById(account);
    }

    @Override
    public Account findAccountById(int id) {
        return accountDaoC.findAccountById(id);
    }

    @Override
    public List<Account> findAll() {

        return accountDaoC.findAll();
    }

    @Override
    public Integer countAccount() {
        return accountDaoC.countAccount();
    }

}


【1.2.9】第四次运行

执行AccountControllerTest的findAll()测试

此时使用 @Autowired注入类型为AccountDao,这个时候bean名称不再为accountDao2,而是根据@Qualifier指定的名称accountDao

在这里插入图片描述

【1.3】@Autowired、@Qualifier小结
@Autowired
作用:
	默认按照bean的类型注入数据
属性:
	required:指定目标bean是否必须存在于spring的IOC容器(true必须存在;false:可以不存在;默认true)
细节:
	1.在spring容器中,如果同一个类型存在多个bean实例对象
	2.则先按照bean的类型进行注入,再按照bean的名称进行匹配
	3.匹配上注入成功;匹配不上注入失败
	
@Qualifier	
作用:
	与@Autowired注解一起使用,指定在按照bean类型注入的基础上,再按照bean的名称注入
属性:
	value:指定bean的名称
细节:
	1.在类的成员变量上,不能单独使用。需要与@Autowired注解一起使用
	2.在方法的成员变量上,可以单独使用

【2】@Resource(8)

@Resource
作用:
默认按照bean的名称注入数据,如果同一个接口有多个实现,可以通过指定属性进行注入
属性:
name:指定bean的名称注入数据
type:指定bean的类型注入数据
细节:
默认按照bean的名称匹配注入数据。如果注入失败,再按照bean的类型注入

【2.1】目标
使用@Resource,且理解他的匹配方式
【2.2】实现
【2.2.1】创建项目

创建spring-day02-08annotation-xml-ioc-resource
在这里插入图片描述

【2.2.2】修改AccountServiceImpl

此时@Resource按name="accountDao"注入

/**
 * @Description:业务实现类
 */
@Service("accountService")
public class AccountServiceImpl implements AccountService {


    /**
     * 1、不写,按照成员变量名称去找
     * 2、写name: 按name名称去找:@Resource(name = "accountDao")
     * 3、写type:按照类型去找:@Resource(type = AccountDaoImplB.class)
     */
    @Resource(name = "accountDao")
    private AccountDao accountDaoC;

    @Override
    public int saveAccount(Account account) {
        return accountDaoC.saveAccount(account);
    }

    @Override
    public int deleteAccountById(int id) {
        return accountDaoC.deleteAccountById(id);
    }

    @Override
    public int updateAccountById(Account account) {
        return accountDaoC.updateAccountById(account);
    }

    @Override
    public Account findAccountById(int id) {
        return accountDaoC.findAccountById(id);
    }

    @Override
    public List<Account> findAll() {

        return accountDaoC.findAll();
    }

    @Override
    public Integer countAccount() {
        return accountDaoC.countAccount();
    }

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


【2.2.3】第一次运行

此时AccountDao按照@Resource中的name="accountDao"注入

在这里插入图片描述

【2.2.4】再次修改AccountServiceImpl

此时@Resource按name="accountDaoB"注入

/**
 * @Description:业务实现类
 */
@Service("accountService")
public class AccountServiceImpl implements AccountService {


    /**
     * 1、不写,按照成员变量名称去找
     * 2、写name: 按name名称去找:@Resource(name = "accountDao")
     * 3、写type:按照类型去找:@Resource(type = AccountDaoImplB.class)
     */
    @Resource(name = "accountDaoB")
    private AccountDao accountDaoC;

    @Override
    public int saveAccount(Account account) {
        return accountDaoC.saveAccount(account);
    }

    @Override
    public int deleteAccountById(int id) {
        return accountDaoC.deleteAccountById(id);
    }

    @Override
    public int updateAccountById(Account account) {
        return accountDaoC.updateAccountById(account);
    }

    @Override
    public Account findAccountById(int id) {
        return accountDaoC.findAccountById(id);
    }

    @Override
    public List<Account> findAll() {

        return accountDaoC.findAll();
    }

    @Override
    public Integer countAccount() {
        return accountDaoC.countAccount();
    }

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

【2.2.5】第二次运行

此时AccountDao按照@Resource中的name="accountDaoB"注入

在这里插入图片描述

【2.2.6】修改dao层

去除AccountDaoImpl和AccountDaoImplB中的@Repository的name值:accountDao、accountDaoB

@Repository
public class AccountDaoImpl implements AccountDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public int saveAccount(Account account) {
        String sql = "INSERT INTO `account` ( `account_name`, `money`) VALUES ( ?, ?)";
        return jdbcTemplate.update(sql, account.getAccountName(),account.getMoney());
    }

    @Override
    public int deleteAccountById(int id) {
        String sql = "delete from `account` where id =?";
        return jdbcTemplate.update(sql,id);
    }

    @Override
    public int updateAccountById(Account account) {
        String sql = "update account set account_name=?,money=? where id = ?";
        return jdbcTemplate.update(sql, account.getAccountName(),account.getMoney(),account.getId());
    }

    @Override
    public Account findAccountById(int id) {
        String sql = "select * from account where id =?";
        return jdbcTemplate.queryForObject(sql, new AccountMapper(),id);
    }

    @Override
    public List<Account> findAll() {
        System.out.println("执行了AccountDaoImpl(A)");
        String sql = "select * from account";
        return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Account.class));
    }

    @Override
    public Integer countAccount() {
        String sql = "select count(1) from account";
        return jdbcTemplate.queryForObject(sql, Integer.class);
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

}


@Repository
public class AccountDaoImplB implements AccountDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public int saveAccount(Account account) {
        String sql = "INSERT INTO `account` ( `account_name`, `money`) VALUES ( ?, ?)";
        return jdbcTemplate.update(sql, account.getAccountName(),account.getMoney());
    }

    @Override
    public int deleteAccountById(int id) {
        String sql = "delete from `account` where id =?";
        return jdbcTemplate.update(sql,id);
    }

    @Override
    public int updateAccountById(Account account) {
        String sql = "update account set account_name=?,money=? where id = ?";
        return jdbcTemplate.update(sql, account.getAccountName(),account.getMoney(),account.getId());
    }

    @Override
    public Account findAccountById(int id) {
        String sql = "select * from account where id =?";
        return jdbcTemplate.queryForObject(sql, new AccountMapper(),id);
    }

    @Override
    public List<Account> findAll() {
        System.out.println("执行了AccountDaoImpl(B)");
        String sql = "select * from account";
        return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Account.class));
    }

    @Override
    public Integer countAccount() {
        String sql = "select count(1) from account";
        return jdbcTemplate.queryForObject(sql, Integer.class);
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

}


【2.2.7】再次修改AccountServiceImpl

添加@Resource(type = AccountDaoImpl.class)

@Service("accountService")
public class AccountServiceImpl implements AccountService {


    /**
     * 1、不写,按照成员变量名称去找
     * 2、写name: 按name名称去找:@Resource(name = "accountDao")
     * 3、写type:按照类型去找:@Resource(type = AccountDaoImplB.class)
     */
//    @Resource(name = "accountDaoB")
    @Resource
    private AccountDao accountDaoC;

    @Override
    public int saveAccount(Account account) {
        return accountDaoC.saveAccount(account);
    }

    @Override
    public int deleteAccountById(int id) {
        return accountDaoC.deleteAccountById(id);
    }

    @Override
    public int updateAccountById(Account account) {
        return accountDaoC.updateAccountById(account);
    }

    @Override
    public Account findAccountById(int id) {
        return accountDaoC.findAccountById(id);
    }

    @Override
    public List<Account> findAll() {

        return accountDaoC.findAll();
    }

    @Override
    public Integer countAccount() {
        return accountDaoC.countAccount();
    }

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

【2.2.8】第三次运行

默认按照bean的名称匹配注入数据。如果注入失败,再按照bean的类型注入
此时AccountServiceImpl按照@Resource的类型注入,但是发现2个实现,此时不知道走哪个类

在这里插入图片描述

只有一个实现类的情况下
在这里插入图片描述

【2.2.9】再次修改AccountServiceImpl

此时@Resource按type = AccountDaoImplB.class注入

@Service("accountService")
public class AccountServiceImpl implements AccountService {


    /**
     * 1、不写,按照成员变量名称去找
     * 2、写name: 按name名称去找:@Resource(name = "accountDao")
     * 3、写type:按照类型去找:@Resource(type = AccountDaoImplB.class)
     */
//    @Resource(name = "accountDaoB")
    @Resource(type = AccountDaoImplB.class)
    private AccountDao accountDaoC;

    @Override
    public int saveAccount(Account account) {
        return accountDaoC.saveAccount(account);
    }

    @Override
    public int deleteAccountById(int id) {
        return accountDaoC.deleteAccountById(id);
    }

    @Override
    public int updateAccountById(Account account) {
        return accountDaoC.updateAccountById(account);
    }

    @Override
    public Account findAccountById(int id) {
        return accountDaoC.findAccountById(id);
    }

    @Override
    public List<Account> findAll() {

        return accountDaoC.findAll();
    }

    @Override
    public Integer countAccount() {
        return accountDaoC.countAccount();
    }

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


【2.2.10】第四次运行

此时AccountServiceImpl按照@Resource按type = AccountDaoImpB.class注入

在这里插入图片描述

【2.3】@Resource小结
@Resource
作用:
	默认按照bean的名称注入数据,如果同一个接口有多个实现,可以通过指定类型进行注入
属性:
	name:指定bean的名称注入数据
	type:指定bean的类型注入数据
细节:
	默认按照bean的名称匹配注入数据。如果注入失败,再按照bean的类型注入

【3】@Value(9)

@Value

作用:给基本数据类型赋值

使用:适合配置属性文件的读取

【3.1】创建项目

创建spring-day02-09annotation-xml-ioc-value

在这里插入图片描述

【3.2】添加DbConfig类

在这里插入图片描述


/**
 * @Description:属性配置
 */
@Component
public class DbConfig {

    @Value("${dataSource.driverClassName}")
    private String driverClassName;

    @Value("${dataSource.url}")
    private String url;

    @Value("${dataSource.username}")
    private String username;

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

    public String getDriverClassName() {
        return driverClassName;
    }

    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "Dbconfig{" +
                "driverClassName='" + driverClassName + '\'' +
                ", url='" + url + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}


【3.3】添加DbConfigTest测试
package com.itheima.spring;

import com.itheima.spring.config.DbConfig;
import com.itheima.spring.controller.ClientController;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Description:测试
 */
public class DbConfigTest {

    private DbConfig dbConfig;

    @Before
    public void before(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
        dbConfig = (DbConfig) applicationContext.getBean("dbConfig");
    }

    @Test
    public void test(){
        System.out.println("dbConfig配置文件内容:"+dbConfig.toString());
    }
}


【3.4】运行结果

在这里插入图片描述

【3.5】@Value小结
【作用】
	1、基础数据类型的注入,
	2、我们常用的配置文件可以直接使用这种方式加载

4、bean作用域@Scope (10)

【1】目标

使用@Scope设置bean的作用范围。相当于xml配置方式中bean标签的scope属性

【2】实现

【2.1】创建项目

创建spring-day02-10annotation-xml-ioc-scope
在这里插入图片描述

【2.2】修改DbConfig

添加@Scope(value = “prototype”)


/**
 * @Description:配置
 */
@Component("dbConfig")
@Scope(value = "prototype")
public class DbConfig {

    @Value("${dataSource.driverClassName}")
    private String driverClassName;

    @Value("${dataSource.url}")
    private String url;

    @Value("${dataSource.username}")
    private String username;

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

    public DbConfig() {
    }

    public String getDriverClassName() {
        return driverClassName;
    }

    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "DbConfig{" +
                "driverClassName='" + driverClassName + '\'' +
                ", url='" + url + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}


【2.3】修改DbConfigTest

/**
 * @Description:测试
 */
public class DbConfigTest {

    private DbConfig dbConfigA;

    private DbConfig dbConfigB;

    @Before
    public void before(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
        dbConfigA = (DbConfig) applicationContext.getBean("dbConfig");
        dbConfigB = (DbConfig) applicationContext.getBean("dbConfig");
    }

    @Test
    public void test(){

        System.out.println("dbConfigA内存地址:"+dbConfigA.hashCode());
        System.out.println("dbConfigB内存地址:"+dbConfigB.hashCode());
    }
}


【2.4】运行DbConfigTest

在这里插入图片描述

【3】作用域@Scope小结

@Scope
作用:
	设置bean的作用范围。相当于xml配置方式中bean标签的scope属性
	
属性:
	value:指定作用范围取值
	属性取值:
         singleton:单例。默认值
         prototype:多例
         request:web项目中,把bean对象存入request域中【了解】
         session:web项目中,把bean对象存入session域中【了解】
         globalsession:web项目中,把bean对象存入全局session域中【了解】

5、bean生命周期(11)

@PostConstruct:初始化后bean之前进行的操作

@PreDestroy :销毁bean之后进行的操作

【1】目标

1、@PostConstruct替换xml配置方式中bean标签的init-method属性
2、@PreDestroy替换xml配置方式中bean标签的destroy-method属性

【2】实现

【2.1】创建项目

创建spring-day02-11annotation-xml-ioc-life

在这里插入图片描述

【2.2】修改DbConfig

/**
 * @Description:配置
 */
@Component("dbConfig")
public class DbConfig {

    @Value("${dataSource.driverClassName}")
    private String driverClassName;

    @Value("${dataSource.url}")
    private String url;

    @Value("${dataSource.username}")
    private String username;

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

    public DbConfig() {
        System.out.println("开始创建");
    }

    @PostConstruct
    public void init(){
        System.out.println("初始化");
    }

    @PreDestroy
    public void destroy(){
        System.out.println("回收");
    }

    public String getDriverClassName() {
        return driverClassName;
    }

    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "DbConfig{" +
                "driverClassName='" + driverClassName + '\'' +
                ", url='" + url + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}



【2.3】修改DbConfigTest
package com.itheima.spring;

import com.itheima.spring.config.DbConfig;
import com.itheima.spring.controller.ClientController;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Description:测试
 */
public class DbConfigTest {

    private DbConfig dbConfigA;

    private DbConfig dbConfigB;

    ApplicationContext applicationContext;

    @Before
    public void before(){
        applicationContext = new ClassPathXmlApplicationContext("bean.xml");
        dbConfigA = (DbConfig) applicationContext.getBean("dbConfig");
        dbConfigB = (DbConfig) applicationContext.getBean("dbConfig");

    }

    @Test
    public void test(){

        System.out.println("dbConfigA内存地址:"+dbConfigA.hashCode());
        System.out.println("dbConfigB内存地址:"+dbConfigB.hashCode());
    }

    @Test
    public void testB(){
        System.out.println("dbConfigA的内容"+dbConfigB.toString());
        ((ClassPathXmlApplicationContext)applicationContext).close();
    }

}

【2.4】运行结果

在这里插入图片描述

【3】bean生命周期小结

@PostConstruct:
	热加载数据
	初始化操作,相当于xml配置方式中bean标签的init-method属性
	
@PreDestroy:
	资源回收
	销毁操作,相当于xml配置方式中bean标签的destroy-method属性

第四章 基于全Annotation的spring-IOC【重点】

1、思考

前面我们使用了annotation+xml的混合模式配置了springIOC,但是一会配置注解,一会又配置XML,同学们是不是感觉挺麻烦?那下面的xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!--读取外部根目录下资源配置文件-->
    <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>

    <!--扫描-->
    <context:component-scan base-package="com.itheima"></context:component-scan>

    <!--配置出druidDataSource数据源-->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${dataSource.driverClassName}"></property>
        <property name="url" value="${dataSource.url}"></property>
        <property name="username" value="${dataSource.username}"></property>
        <property name="password" value="${dataSource.password}"></property>
    </bean>

    <!--配置jdbc查询模板,注入druidDataSource数据源-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="druidDataSource"></property>
    </bean>
    
</beans>

能不能完全舍弃呢?

2、annotation案例(12)

annotation案例中使用到的annotation和xml标签对照表

【1】配置类注解与XML对照表

XMLAnnotation说明
< context:property-placeholder >@PropertySource导入外部资源文件
< context:component-scan >@ComponentScan扫描包,约定大于配置
jdbcTemplate、dataSource非自定配置类@Bean声明bean装配到SpringIOC中
bean.xml@Configuration声明配置类,代替bean.xml的作用
@Import(了解)引入其他配置类

【2】加载方式

使用bean.xml的时候我们加载配置文件的方式

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");

全注解加载方式:

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);

【3】目标

·

1、使用配置类代替bean.xml配置文件,完成纯注解的配置方式,脱离xml的配置。

【4】实现

在这里插入图片描述

【4.1】创建项目

创建spring-day02-12annotation-ioc

在这里插入图片描述

【4.2】编写SpringConfig类

SpringConfig@Configuration注解替换bean.xml

请添加图片描述

SpringConfig@ComponentScan(value = {"com.test.spring"})注解替换如下:

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

完整SpringConfig

/**
 * @Description:springIOC的配置类
 * Configuration:声明此类为配置类
 */
@Configuration
@ComponentScan(basePackages = "com.test.spring")
public class SpringConfig {
}

【4.3】编写DbConfig类

DbConfig@Configuration声明是个配置类
@PropertySource(value={"classpath:db.properties"})导入外部文件

在这里插入图片描述

DbConfig@Bean替换非自定义的配置类

在这里插入图片描述

DbConfig代码

/**
 * @Description:声明数据库的配置类
 * PropertySource:读取外部配置文件,放入springIOC容器
 */
@Configuration
@PropertySource(value = "classpath:db.properties")
public class DbConfig {

    @Value("${dataSource.driverClassName}")
    private String driverClassName;

    @Value("${dataSource.url}")
    private String url;

    @Value("${dataSource.username}")
    private String username;

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

    /**
     * @Description
     * Bean
     *      作用:声明通过一个方法创建bean交于spring管理
     *      细节:如果不指定名称,则此bean的名称为方法名
     */
    @Bean("druidDataSource")
    public DruidDataSource druidDataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    /**
     * @Description
     * Qualifier:先从容器中找到bean名称为 druidDataSource的bean,然后赋值给传入参数使用
     */
    @Bean("jdbcTemplate")
    public JdbcTemplate jdbcTemplate(@Qualifier("druidDataSource") DataSource dataSource){
        return new JdbcTemplate(dataSource);
    }


}


【4.4】修改ClientControllergTest

在这里插入图片描述

/**
 * @Description:测试类
 */
public class ClientControllerTest {

    private  ClientController clientController;

    /**
     * @Description 执行测试方法之前需要构建容器==》IOC
     */
    @Before
    public void before(){
        //构建容器
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        //从容器中获得clientController对象
        clientController=applicationContext.getBean("clientController", ClientController.class);
    }

    /**
     * 创建用户
     */
    @Test
    public void saveAccount() {
        Account account = new Account();
        account.setAccountName("张三");
        account.setMoney(2000F);
        int flag = clientController.saveAccount(account);
        System.out.println("创建用户受影响行数:"+flag);

    }

    /**
     * 删除用户
     */
    @Test
    public void deleteAccountById() {
        int id = 21;
        int flag =clientController.deleteAccountById(id);
        System.out.println("删除用户受影响行数:"+flag);
    }

    /**
     * 修改用户
     */
    @Test
    public void updateAccountById() {
        Account account = new Account();
        account.setId(5);
        account.setAccountName("张三");
        account.setMoney(2000F);
        int flag =clientController.updateAccountById(account);
        System.out.println("修改用户受影响行数:"+flag);
    }


    /**
     * 按ID查询用户
     */
    @Test
    public void findAccountById() {
        int id = 5;
        Account account =clientController.findAccountById(id);
        System.out.println("按ID查询用户:"+account.toString());
    }

    /**
     * 查询所有用户
     */
    @Test
    public void findAll() {
        List<Account> list = clientController.findAll();
        list.forEach(n->{
            System.out.println("查询所有用户:"+n.toString());
        });
    }

    /**
     * 统计用户个数
     */
    @Test
    public void countAccount() {
        int flag =  clientController.countAccount();
        System.out.println("统计用户个数:"+flag);
    }
}



【4.5】测试

在这里插入图片描述

3、小结

配置类相关注解:

1@Configuration:声明配置类,代替bean.xml的作用
2@ComponentScan:配置注解扫描
3@Bean:将方法的返回值装配到IOC容器中
4@PropertySource:加载外部资源文件
5@Import:引入其他配置类

加载配置类,初始化IOC容器,获取工厂:

ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);

第五章 Spring整合junit【掌握】

1、思考

在以上的课程中我们一直使用junit方式测试程序:


/**
 * @Description:测试类
 */
public class ClientControllerTest {

    private  ClientController clientController;

    /**
     * @Description 执行测试方法之前需要构建容器==》IOC
     */
    @Before
    public void before(){
        //构建容器
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        //从容器中获得clientController对象
        clientController=applicationContext.getBean("clientController", ClientController.class);
    }

    /**
     * 创建用户
     */
    @Test
    public void saveAccount() {
        Account account = new Account();
        account.setAccountName("张三");
        account.setMoney(2000F);
        int flag = clientController.saveAccount(account);
        System.out.println("创建用户受影响行数:"+flag);

    }

    /**
     * 删除用户
     */
    @Test
    public void deleteAccountById() {
        int id = 21;
        int flag =clientController.deleteAccountById(id);
        System.out.println("删除用户受影响行数:"+flag);
    }

    /**
     * 修改用户
     */
    @Test
    public void updateAccountById() {
        Account account = new Account();
        account.setId(5);
        account.setAccountName("张三");
        account.setMoney(2000F);
        int flag =clientController.updateAccountById(account);
        System.out.println("修改用户受影响行数:"+flag);
    }


    /**
     * 按ID查询用户
     */
    @Test
    public void findAccountById() {
        int id = 5;
        Account account =clientController.findAccountById(id);
        System.out.println("按ID查询用户:"+account.toString());
    }

    /**
     * 查询所有用户
     */
    @Test
    public void findAll() {
        List<Account> list = clientController.findAll();
        list.forEach(n->{
            System.out.println("查询所有用户:"+n.toString());
        });
    }

    /**
     * 统计用户个数
     */
    @Test
    public void countAccount() {
        int flag =  clientController.countAccount();
        System.out.println("统计用户个数:"+flag);
    }
}


但是在测试之前我们需要使用@Before注解去提前加载ApplicationContext容器和获得bean

/**
     * 提前加载配置文件
     */
    @Before
    public void beforeLoadConfig(){
        ApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("classpath:bean.xml");
        accountController = (AccountController) applicationContext.getBean("accountController");
    }

这样的操作是不是特别累赘?在最初介绍spring架构的时候我们是不是说到spring本身提供一个test工具,他可以给我们提供了一个运行器,可以读取配置文件(或注解)来创建容器。我们只需要告诉它配置文件在哪就行了。

2、测试注解说明

注解说明
@RunWith(SpringJUnit4ClassRunner.class)替换底层运行器
@ContextConfiguration(value = {“bean.xml”})Xml方式加载一个运行容器
@ContextConfiguration(classes = {SpringConfig.class})注解方式加载一个运行容器

3、XML方式(13)

【1】目标

1、掌握spring-test读取xml方式集成测试工具

【2】实现

【2.1】创建项目

创建spring-day02-13spring-test-xml

在这里插入图片描述

【2.2】导入spring-test依赖
	<!--spring-test-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
    </dependency>
	<!--必须4.12版本以上-->
	<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
【2.3】修改ClientControllerTest

添加

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = {“classpath:bean.xml”})

此时springIOC容器已经加载,我们可以使用

@Autowired
private ClientController clientController;

注入属性值
在这里插入图片描述


/**
 * @Description:测试
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:bean.xml")
public class ClientControllerTest {

    @Autowired
    private ClientController clientController;


//    @Before
//    public void before(){
//        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
//        clientController = (ClientController) applicationContext.getBean("clientController");
//    }

    /**
     * 创建用户
     */
    @Test
    public void saveAccount() {
        Account account = new Account();
        account.setAccountName("张三");
        account.setMoney(2000F);
        int flag = clientController.saveAccount(account);
        System.out.println("创建用户受影响行数:"+flag);

    }

    /**
     * 删除用户
     */
    @Test
    public void deleteAccountById() {
        int id = 7;
        int flag =clientController.deleteAccountById(id);
        System.out.println("删除用户受影响行数:"+flag);
    }

    /**
     * 修改用户
     */
    @Test
    public void updateAccountById() {
        Account account = new Account();
        account.setId(5);
        account.setAccountName("张三");
        account.setMoney(2000F);
        int flag =clientController.updateAccountById(account);
        System.out.println("修改用户受影响行数:"+flag);
    }


    /**
     * 按ID查询用户
     */
    @Test
    public void findAccountById() {
        int id = 5;
        Account account =clientController.findAccountById(id);
        System.out.println("按ID查询用户:"+account.toString());
    }

    /**
     * 查询所有用户
     */
    @Test
    public void findAll() {
        List<Account> list = clientController.findAll();
        list.forEach(n->{
            System.out.println("查询所有用户:"+n.toString());
        });
    }

    /**
     * 统计用户个数
     */
    @Test
    public void countAccount() {
        int flag =  clientController.countAccount();
        System.out.println("统计用户个数:"+flag);
    }
}

【2.4】测试结果

在这里插入图片描述

【3】小结

1、添加spring-test的依赖,使用@RunWith注解替换底层运行器
2、使用ContextConfiguration注解加载xml配置文件
3、在测试用例中直接使用注入bean的注解如:@Autowired将所需的bean对象注入到测试用例中即可

4、全注解方式(14)

【1】目标

1、掌握spring-test读取annotation方式集成测试工具

【2】实现

【2.1】创建项目

创建spring-day02-14spring-test-annotation

【2.2】导入spring-test依赖
	<!--spring-test-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
    </dependency>
	<!--必须4.12版本以上-->
	<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
【2.3】修改AccountControllerTest

添加

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={SpringConfig.class})

此时springIOC容器已经加载,我们可以使用

@Autowired
private AccountController accountController;

注入属性值
在这里插入图片描述


/**
 * @Description:测试类
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class ClientControllerTest {
    @Autowired
    private  ClientController clientController;

    /**
     * @Description 执行测试方法之前需要构建容器==》IOC
     */
//    @Before
//    public void before(){
//        //构建容器
//        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
//        //从容器中获得clientController对象
//        clientController=applicationContext.getBean("clientController", ClientController.class);
//    }
    /**
     * 创建用户
     */
    @Test
    public void saveAccount() {
        Account account = new Account();
        account.setAccountName("张三");
        account.setMoney(2000F);
        int flag = clientController.saveAccount(account);
        System.out.println("创建用户受影响行数:"+flag);

    }

    /**
     * 删除用户
     */
    @Test
    public void deleteAccountById() {
        int id = 21;
        int flag =clientController.deleteAccountById(id);
        System.out.println("删除用户受影响行数:"+flag);
    }

    /**
     * 修改用户
     */
    @Test
    public void updateAccountById() {
        Account account = new Account();
        account.setId(5);
        account.setAccountName("张三");
        account.setMoney(2000F);
        int flag =clientController.updateAccountById(account);
        System.out.println("修改用户受影响行数:"+flag);
    }


    /**
     * 按ID查询用户
     */
    @Test
    public void findAccountById() {
        int id = 5;
        Account account =clientController.findAccountById(id);
        System.out.println("按ID查询用户:"+account.toString());
    }

    /**
     * 查询所有用户
     */
    @Test
    public void findAll() {
        List<Account> list = clientController.findAll();
        list.forEach(n->{
            System.out.println("查询所有用户:"+n.toString());
        });
    }

    /**
     * 统计用户个数
     */
    @Test
    public void countAccount() {
        int flag =  clientController.countAccount();
        System.out.println("统计用户个数:"+flag);
    }
}


【2.4】测试结果

在这里插入图片描述

【3】小结

1、添加spring-test的依赖,使用@RunWith注解替换底层运行器
2、使用ContextConfiguration注解加载配置类
3、在测试用例中直接使用注入bean的注解如:@Autowired将所需的bean对象注入到测试用例中即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/2196.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

刷题记录(2023.3.14 - 2023.3.18)

[第五空间 2021]EasyCleanup 临时文件包含考点 分析源码&#xff0c;两个特殊的点&#xff0c;一个是 eval&#xff0c;另一个是 include eval 经过了 strlen filter checkNums 三个函数 include 经过了 strlen filter 两个函数 filter 检测是否包含特定的关键字或字符 fun…

【数据结构与算法】用栈实现队列

文章目录&#x1f63b;前言如何用栈实现队列&#xff1f;用栈实现队列整体的实现代码&#x1f63c;写在最后&#x1f63b;前言 &#x1f61d;上一章我们用队列实现了一个栈&#xff08;-> 传送门 <-&#xff09;&#xff0c;而这一章就带大家用栈实现一个队列。 &#x1…

< 每日算法:在排序数组中查找元素的第一个和最后一个位置 >

每日算法 - JavaScript解析&#xff1a;在排序数组中查找元素的第一个和最后一个位置 一、任务描述&#xff1a;> 示例 1> 示例 2> 示例 3二、题意解析三、解决方案&#xff1a;往期内容 &#x1f4a8;一、任务描述&#xff1a; 给你一个按照非递减顺序排列的整数数组…

C++基础算法③——排序算法(选择、冒泡附完整代码)

排序算法 1、选择排序 2、冒泡排序 1、选择排序 基本思想&#xff1a;从头至尾扫描序列&#xff0c;每一趟从待排序元素中找出最小(最大)的一个元素值&#xff0c;然后与第一个元素交换值&#xff0c;接着从剩下的元素中继续这种选择和交换方式&#xff0c;最终得到一个有序…

冲击蓝桥杯-时间问题(必考)

目录 前言&#xff1a; 一、时间问题 二、使用步骤 1、考察小时&#xff0c;分以及秒的使用、 2、判断日期是否合法 3、遍历日期 4、推算星期几 总结 前言&#xff1a; 时间问题可以说是蓝桥杯&#xff0c;最喜欢考的问题了,因为时间问题不涉及到算法和一些复杂的知识&#xf…

第十四届蓝桥杯三月真题刷题训练——第 18 天

目录 第 1 题&#xff1a;排列字母 问题描述 运行限制 代码&#xff1a; 第 2 题&#xff1a;GCD_数论 问题描述 输入格式 输出格式 样例输入 样例输出 评测用例规模与约定 运行限制 第 3 题&#xff1a;选数异或 第 4 题&#xff1a;背包与魔法 第 1 题&#x…

1649_Excel中删除重复的数据

全部学习汇总&#xff1a; GreyZhang/windows_skills: some skills when using windows system. (github.com) 长久时间的开发工作性质导致我对Windows生态下的很多工具没有一个深度的掌握。有时候&#xff0c;别说深度&#xff0c;可能最为浅显的操作都是不熟悉的。这个不仅仅…

JVM学习.02 内存分配和回收策略

1、前言《JVM学习.01 内存模型》篇讲述了JVM的内存布局&#xff0c;其中每个区域是作用&#xff0c;以及创建实例对象的时候内存区域的工作流程。上文还讲到了关于对象存货后&#xff0c;会被回收清理的过程。今天这里就着重讲一下对象实例是如何被清理回收的&#xff0c;以及清…

5.方法(最全C#方法攻略)

目录 5.1 方法的结构 5.2 方法体内部的代码执行 5.3.1 类型推断和Var关键字 5.3.2 嵌套块中的本地变量 5.4 本地常量 5.5 控制流 5.6 方法调用 5.7 返回值 5.8 返回语句和void 方法 5.9 参数 5.9.1 形参 5.9.2 实参 位置参数示例 5.10 值参数 5.11 引用参数 5.12…

【vm虚拟机】vmware虚拟机下载安装

vmware虚拟机下载安装&#x1f6a9; vmware虚拟机下载&#x1f6a9; 安装虚拟机程序&#x1f6a9; 创建一个CentOS虚拟机&#x1f6a9; 异常情况&#x1f6a9; vmware虚拟机下载 vmware官网下载地址 &#x1f6a9; 安装虚拟机程序 双击安装包exe程序&#xff0c;无脑下一步即…

来到CSDN的一些感想

之所以会写下今天这篇博客&#xff0c;是因为心中实在是有很多话想说&#xff01;&#xff01;&#xff01; 认识我的人应该都知道&#xff0c;我是才来CSDN不久的&#xff0c;也可以很清楚地看见我的码龄&#xff0c;直到今天&#xff1a;清清楚楚地写着&#xff1a;134天&…

完美日记母公司再度携手中国妇基会,以“创美人生”助力女性成长

撰稿 | 多客 来源 | 贝多财经 当春时节&#xff0c;梦想花开。和煦的三月暖阳&#xff0c;唤醒的不止是满城春意&#xff0c;更有逸仙电商“创美人生”公益项目播撒的一份希望。 3月8日“国际妇女节”当日&#xff0c;为积极响应我国促进共同富裕的政策倡导&#xff0c;助力相…

C语言--自定义类型详解

目录结构体结构体的声明特殊的声明结构的自引用typedef的使用结构体变量的定义和初始化结构体的内存对齐为什么存在内存对齐&#xff1f;修改默认对齐数结构体传参位段位段的内存分配位段的跨平台问题枚举联合联合类型的定义联合在内存中开辟空间联合大小的计算结构体 结构体的…

Linux之磁盘分区、挂载

文章目录一、Linux分区●原理介绍●硬盘说明查看所有设备挂载情况挂载的经典案例二、磁盘情况查询基本语法应用实例磁盘情况-工作实用指令一、Linux分区 ●原理介绍 Linux来说无论有几个分区&#xff0c;分给哪一目录使用&#xff0c;它归根结底就只有一个根目录&#xff0c;…

可编程线性直流电源的特性有哪些?

可编程线性直流电源是一种高性能、高精度的电源设备&#xff0c;其主要特性包括以下几点&#xff1a;1、高稳定性&#xff1a;可编程线性直流电源具有极高的输出稳定性&#xff0c;能够保证输出电压、电流和功率的精度和稳定性。通常来说&#xff0c;稳定性能够达到0.01%或更高…

Linux的诞生过程

个人简介&#xff1a;云计算网络运维专业人员&#xff0c;了解运维知识&#xff0c;掌握TCP/IP协议&#xff0c;每天分享网络运维知识与技能。座右铭&#xff1a;海不辞水&#xff0c;故能成其大&#xff1b;山不辞石&#xff0c;故能成其高。个人主页&#xff1a;小李会科技的…

Android Lancet Aop 字节编码修复7.1系统Toast问题(WindowManager$BadTokenException)

近期在Bugly上出现7.1以下设备上出现大量BadTokenException&#xff1a; android.view.WindowManager$BadTokenExceptionUnable to add window -- token android.os.BinderProxy6c0415d is not valid; is your activity running?报错堆栈&#xff0c;如下所示&#xff1a; …

数据分析师CDA认证 Level Ⅰ笔记

**黑色字体部分为考纲&#xff0c;蓝色字体部分为笔记&#xff0c;仅供参考 PART 1 数据分析概念与职业操守 1、数据分析概念、方法论、角色 【领会】 数据分析基本概念&#xff08;数据分析、数据挖掘、大数据&#xff09; 数据分析目的及其意义 数据分析方法与流程 数据分析的…

【网络安全工程师】从零基础到进阶,看这一篇就够了

学前感言 1.这是一条需要坚持的道路&#xff0c;如果你只有三分钟的热情那么可以放弃往下看了。 2.多练多想&#xff0c;不要离开了教程什么都不会&#xff0c;最好看完教程自己独立完成技术方面的开发。 3.有问题多google,baidu…我们往往都遇不到好心的大神&#xff0c;谁…

【Leetcode】队列实现栈和栈实现队列

目录 一.【Leetcode225】队列实现栈 1.链接 2.题目再现 3.解法 二.【Leetcode232】栈实现队列 1.链接 2.题目再现 3.解法 一.【Leetcode225】队列实现栈 1.链接 队列实现栈 2.题目再现 3.解法 这道题给了我们两个队列&#xff0c;要求去实现栈&#xff1b; 首先&…