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); } }