Spring使用純註解實現的小案例
項目結構
數據庫
配置文件
-
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>
-
jdbcConfig.properties
jdbc.driver = com.mysql.cj.jdbc.Driver jdbc.url = jdbc:mysql://localhost:3306/eesy jdbc.user = root jdbc.password = 123456
實體類
-
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 + '}'; } }
持久層
-
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); }
-
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); } } }
業務層
-
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); }
-
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); } }
配置類
-
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 { }
-
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); } } }
測試層
-
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); } }