Spring使用純註解實現的小案例+Spring-Junit整合

Spring使用純註解實現的小案例

項目結構

在這裏插入圖片描述

數據庫

在這裏插入圖片描述

配置文件

  1. pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.xiaoge</groupId>
        <artifactId>account_annoioc_withoutxml</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.0.2.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>5.0.2.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.13</version>
            </dependency>
    
            <dependency>
                <groupId>commons-dbutils</groupId>
                <artifactId>commons-dbutils</artifactId>
                <version>1.4</version>
            </dependency>
    
            <dependency>
                <groupId>c3p0</groupId>
                <artifactId>c3p0</artifactId>
                <version>0.9.1.2</version>
            </dependency>
    
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
            </dependency>
        </dependencies>
    
    </project>
    
  2. jdbcConfig.properties

    jdbc.driver = com.mysql.cj.jdbc.Driver
    jdbc.url = jdbc:mysql://localhost:3306/eesy
    jdbc.user = root
    jdbc.password = 123456
    

實體類

  1. Account

    package com.xiaoge.domain;
    
    import java.io.Serializable;
    
    /**
     * @Author: 瀟哥
     * @DateTime: 2020/4/7 下午10:16
     * @Description: 賬戶實體類
     */
    public class Account implements Serializable {
    
        private Integer id;
        private String name;
        private Float money;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Float getMoney() {
            return money;
        }
    
        public void setMoney(Float money) {
            this.money = money;
        }
    
        @Override
        public String toString() {
            return "Account{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", money=" + money +
                    '}';
        }
    }
    
    

持久層

  1. Account接口

    package com.xiaoge.dao;
    
    import com.xiaoge.domain.Account;
    
    import java.util.List;
    
    /**
     * @Author: 瀟哥
     * @DateTime: 2020/4/7 下午10:25
     * @Description: 賬戶的持久層接口
     */
    public interface AccountDao {
    
        /**
         * 查詢所有
         * @return
         */
        public List<Account> findAllAccount();
    
        /**
         * 查詢一個
         * @return
         */
        public Account findAccountById(Integer id);
    
        /**
         * 保存
         */
        public void saveAccount(Account account);
    
        /**
         * 更新
         * @param account
         */
        public void updateAccount(Account account);
    
        /**
         * 刪除
         * @param id
         */
        public void deleteAccount(Integer id);
    
    }
    
    
  2. AccountDaoImpl實現類

    package com.xiaoge.dao.impl;
    
    import com.xiaoge.dao.AccountDao;
    import com.xiaoge.domain.Account;
    import org.apache.commons.dbutils.QueryRunner;
    import org.apache.commons.dbutils.handlers.BeanHandler;
    import org.apache.commons.dbutils.handlers.BeanListHandler;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Repository;
    
    import java.sql.SQLException;
    import java.util.List;
    
    /**
     * @Author: 瀟哥
     * @DateTime: 2020/4/7 下午10:25
     * @Description: 賬戶的持久層實現類
     */
    @Repository("accountDao")
    public class AccountDaoImpl implements AccountDao {
    
        @Autowired
        private QueryRunner runner;
    
        public List<Account> findAllAccount() {
            try {
                return runner.query("select * from account", new BeanListHandler<Account>(Account.class));
            } catch (SQLException e) {
                throw  new RuntimeException(e);
            }
        }
    
        public Account findAccountById(Integer id) {
            try {
                return runner.query("select * from account where id = ? ", new BeanHandler<Account>(Account.class), id);
            } catch (SQLException e) {
                throw  new RuntimeException(e);
            }
        }
    
        public void saveAccount(Account account) {
            try {
                runner.update("insert into account(name, money) values(?, ?)", account.getName(), account.getMoney());
            } catch (SQLException e) {
                throw  new RuntimeException(e);
            }
        }
    
        public void updateAccount(Account account) {
            try {
                runner.update("update account set name = ?, money = ? where id = ? ", account.getName(), account.getMoney(), account.getId());
            } catch (SQLException e) {
                throw  new RuntimeException(e);
            }
        }
    
        public void deleteAccount(Integer id) {
            try {
                runner.update("delete from account where id = ? ", id);
            } catch (SQLException e) {
                throw  new RuntimeException(e);
            }
        }
    }
    
    

業務層

  1. AccountService接口

    package com.xiaoge.service;
    
    import com.xiaoge.domain.Account;
    
    import java.util.List;
    
    /**
     * @Author: 瀟哥
     * @DateTime: 2020/4/7 下午10:14
     * @Description: 賬戶的業務層接口
     */
    public interface AccountService {
    
        /**
         * 查詢所有
         * @return
         */
        public List<Account> findAllAccount();
    
        /**
         * 查詢一個
         * @return
         */
        public Account findAccountById(Integer id);
    
        /**
         * 保存
         */
        public void saveAccount(Account account);
    
        /**
         * 更新
         * @param account
         */
        public void updateAccount(Account account);
    
        /**
         * 刪除
         * @param id
         */
        public void deleteAccount(Integer id);
    }
    
    
  2. AccountServiceImpl實現類

    package com.xiaoge.service.impl;
    
    import com.xiaoge.dao.AccountDao;
    import com.xiaoge.domain.Account;
    import com.xiaoge.service.AccountService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    /**
     * @Author: 瀟哥
     * @DateTime: 2020/4/7 下午10:14
     * @Description: 賬戶的業務層實現類
     */
    @Service("accountService")
    public class AccountServiceImpl implements AccountService {
    
        @Autowired // 由於是唯一的所以  可以直接用Autowired註解, 用註解注入時  set方法可以不寫
        private AccountDao accountDao;
    
        public List<Account> findAllAccount() {
            return accountDao.findAllAccount();
        }
    
        public Account findAccountById(Integer id) {
            return accountDao.findAccountById(id);
        }
    
        public void saveAccount(Account account) {
            accountDao.saveAccount(account);
        }
    
        public void updateAccount(Account account) {
            accountDao.updateAccount(account);
        }
    
        public void deleteAccount(Integer id) {
            accountDao.deleteAccount(id);
        }
    }
    
    

配置類

  1. SpringConfiguration主配置類(重點註釋)

    package config;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Import;
    import org.springframework.context.annotation.PropertySource;
    
    /**
     * @Author: 瀟哥
     * @DateTime: 2020/4/8 下午10:56
     * @Description: 該類是一個配置類, 它的作用和bean.xml是一樣的
     *
     *
     * spring中的新註解
     *      Configuration
     *          作用: 指定當前類是一個配置類
     *          細節: 當配置類作爲AnnotationConfigApplicationContext對象創建的參數時, 該註解可以不寫.
     *
     *
     *      ComponentScan
     *          作用: 用於通過註解指定spring在創建容器時要掃描的包
     *          屬性:
     *              value: 它和basePackages的作用是一樣的, 都是用於指定創建容器時要掃描的包.
     *                     我們使用此註解就等同於在xml中配置了:
     *                          <context:component-scan base-package="com.xiaoge"></context:component-scan>
     *      Bean
     *          作用: 用於把當前方法的返回值作爲bean對象存入spring的ioc容器中
     *          屬性:
     *              name: 用於指定bean的id. 當不寫時, 默認是當前方法的名稱
     *          細節:
     *              當我們使用註解配置方法時, 如果方法有參數, spring框架會去容器中查找有沒有可用的bean對象.
     *              查找的方式和Autowired註解的作用是一樣的
     *
     *      Import
     *          作用: 用於導入其他的配置類
     *          屬性:
     *              value: 用於指定其他配置類的字節碼.
     *                     當我們使用Import的註解之後, 有Import註解的類就是父配置類, 而導入的都是子配置類
     *
     *      PropertySource
     *          作用: 用於指定properties文件的位置
     *          屬性:
     *              value: 指定文件的名稱和路徑.
     *                     關鍵字: classpath, 表示類路徑下
     *                     列:
     *                       沒有包, 直接寫文件名:
     *                          classpath:jdbcConfig.properties
     *                       有包, 就是包路徑 + 文件名
     *                          classpath: com/xiaoge/jdbcConfig.properties
     */
    // @Configuration
    @ComponentScan(basePackages = {"com.xiaoge"})
    @Import(JdbcConfig.class)
    @PropertySource("classpath:jdbcConfig.properties")
    public class SpringConfiguration {
    
    
    
    }
    
    
  2. JdbcConfig子配置類(重點註釋)

    package config;
    
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    import org.apache.commons.dbutils.QueryRunner;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Scope;
    
    import javax.sql.DataSource;
    
    /**
     * @Author: 瀟哥
     * @DateTime: 2020/4/9 下午11:12
     * @Description: 和spring連接數據庫相關的配置類
     *
     *
     * @Value
     *      作用: 用於注入基本類型和String類型的數據
     *      屬性:
     *          value: 用於指定數據的值. 它可以使用spring中SpEL(也就是spring的el表達式)
     *          SpEL的寫法: ${表達式}
     *
     *@Qualifier:(不能獨立使用, 依賴@Autowired)
     *         作用: 在按照類中注入的基礎之上在按照名稱注入. 它在給類成員注入時不能單獨使用. 但是在給方法參數注入時可以
     *         屬性:
     *             value: 用於指定注入bean的id.
     *
     */
    // @Configuration
    public class JdbcConfig {
    
        @Value("${jdbc.driver}")
        private String driver;
    
        @Value("${jdbc.url}")
        private String url;
    
        @Value("${jdbc.user}")
        private String username;
    
        @Value("${jdbc.password}")
        private String password;
    
    
        /**
         * 用於創建 QueryRunner
         * @param dataSource
         * @return
         */
        @Bean(name = "runner")
        @Scope("prototype") // 這裏用Qualifier註解是防止有多個bean對象都滿足時, 報錯, 這裏給指定一個id, 根據id來找bean對象
        public QueryRunner createQueryRunner(@Qualifier("dataSource") DataSource dataSource){
            return new QueryRunner(dataSource);
        }
    
    
        /**
         * 創建愛你數據源對象
         * @return
         */
        @Bean(name = "dataSource")
        public DataSource createDataSource(){
            try{
                ComboPooledDataSource ds = new ComboPooledDataSource();
                ds.setDriverClass(driver);
                ds.setJdbcUrl(url);
                ds.setUser(username);
                ds.setPassword(password);
                return ds;
            } catch(Exception e) {
                throw new RuntimeException(e);
            }
    
        }
    
    }
    
    

測試層

  1. AccountServiceTest測試類(重點註釋)

    package com.xiaoge.test;
    
    import com.xiaoge.domain.Account;
    import com.xiaoge.service.AccountService;
    import config.SpringConfiguration;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import java.util.List;
    
    /**
     * @Author: 瀟哥
     * @DateTime: 2020/4/7 下午10:52
     * @Description: 使用Junit單元測試, 測試我們的配置
     *
     * Spring整合junit的配置
     *      1. 導入spring整合junit的jar(座標)
     *      2. 使用junit提供的一個註解把原有的main方法替換了, 替換成spring提供的
     *          @Runwith
     *      3. 告知spring的運行器, spring和ioc的創建基於xml還是註解的, 並且說明位置
     *          @ContextConfiguration
     *              locations: 指定xml文件的位置, 加上classpath關鍵字, 表示在類路徑下
     *              classes: 指定註解類所在的位置
     *
     * 當我們使用spring 5.x版本的時候, 要求junit的jar必須是4.12及以上版本
     *
     */
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = SpringConfiguration.class)
    public class AccountServiceTest {
    
        @Autowired
        private AccountService accountService;
    
        @Test
        public void findAllTest() {
            // 1. 執行方法
            List<Account> allAccount = accountService.findAllAccount();
    
            for (Account account : allAccount) {
                System.out.println(account);
            }
    
        }
    
        @Test
        public void findOneTest() {
            // 1. 執行方法
            Account account = accountService.findAccountById(1);
    
            System.out.println(account);
    
        }
    
        @Test
        public void saveAccountTest() {
            // 1. 構造對象
            Account account = new Account();
            account.setName("ddd");
            account.setMoney(2000f);
    
            // 2. 執行方法
            accountService.saveAccount(account);
    
        }
    
        @Test
        public void updateAccountTest() {
            // 1. 構造對象
            Account account = new Account();
            account.setId(3);
            account.setName("ddd");
            account.setMoney(2000f);
    
            // 2. 執行方法
            accountService.updateAccount(account);
    
        }
    
        @Test
        public void deleteAccountTest() {
            // 1. 執行方法
            accountService.deleteAccount(3);
    
        }
    }
    
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章