基于注解的IOC案例
Account.java
package com.how2java.domain;
import java.io.Serializable;
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 +
'}';
}
}
IAccountDao.java
package com.how2java.dao;
import com.how2java.domain.Account;
import java.util.List;
/**
* 账户的持久层接口
*/
public interface IAccountDao {
/**
* 查询所有账户
* @return
*/
List<Account> findAll();
/**
* 根据id查询账户
* @param id
* @return
*/
Account findById(Integer id);
/**
* 保存账户
* @param account
*/
void save(Account account);
/**
* 更新账户
* @param account
*/
void update(Account account);
/**
* 删除账户
* @param id
*/
void delete(Integer id);
}
AccountDaoImpl.java
package com.how2java.dao.impl;
import com.how2java.dao.IAccountDao;
import com.how2java.domain.Account;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import java.util.List;
/**
* 账户的持久层实现类
*/
public class AccountDaoImpl implements IAccountDao{
private QueryRunner runner;
public void setRunner(QueryRunner runner) {
this.runner = runner;
}
@Override
public List<Account> findAll() {
try{
return runner.query("select * from account", new BeanListHandler<Account>(Account.class));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public Account findById(Integer id) {
try{
return runner.query("select * from account where id = ?", id, new BeanHandler<Account>(Account.class));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void save(Account account) {
try{
runner.update("insert into account(name, money) values(?, ?)", account.getName(), account.getMoney());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void update(Account account) {
try{
runner.update("update account set name = ?, money = ? where id = ?", account.getName(), account.getMoney(), account.getId());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void delete(Integer id) {
try{
runner.update("delete from account where id = ?", id);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
IAccountService.java
package com.how2java.service;
import com.how2java.domain.Account;
import java.util.List;
/**
* 账户的业务层接口
*/
public interface IAccountService {
/**
* 查询所有账户
* @return
*/
List<Account> findAll();
/**
* 根据id查询账户
* @param id
* @return
*/
Account findById(Integer id);
/**
* 保存账户
* @param account
*/
void save(Account account);
/**
* 更新账户
* @param account
*/
void update(Account account);
/**
* 删除账户
* @param id
*/
void delete(Integer id);
}
AccountServiceImpl.java
package com.how2java.service.impl;
import com.how2java.dao.IAccountDao;
import com.how2java.domain.Account;
import com.how2java.service.IAccountService;
import java.util.List;
/**
* 业务层的实现类
*/
public class AccountServiceImpl implements IAccountService{
private IAccountDao accountDao;
public void setAccountDao(IAccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public List<Account> findAll() {
return accountDao.findAll();
}
@Override
public Account findById(Integer id) {
return accountDao.findById(id);
}
@Override
public void save(Account account) {
accountDao.save(account);
}
@Override
public void update(Account account) {
accountDao.update(account);
}
@Override
public void delete(Integer id) {
accountDao.delete(id);
}
}
SpringConfiguration.java
package com.how2java.config;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.context.annotation.*;
import javax.sql.DataSource;
/**
* 配置类:作用等于bean.xml
* Spring中的新注解:
* Configuration:
* 作用:指定当前类是配置类。
* 细节:当配置类作为AnnotationConfigApplicationContext对象的参数时,该注解可以不写,但不绝对。
* ComponentScan:
* 作用:指定创建容器时要扫描的包。
* 属性:value指定创建容器时要扫描的包,与basePackages一样。
* 相当于XML中<context:component-scan base-package="com.how2java"></context:component-scan>。
* Bean:
* 作用:把当前方法的返回值作为对象存入容器中。
* 属性:name指定bean的id。默认(不写)为当前方法的名称。
* 细节:当使用注解配置方法时,如果方法有参数,Spring框架会去容器中查找有无可用bean对象。查找的方式与Autowired注解相同。
* Import:
* 作用:导入其他的配置类。
* 属性:value指定其他配置类的字节码。
* 细节:注解后的类为父配置类,导入类为子配置类。
* PropertySource:
* 作用:指定properties文件的位置。
* 属性:value指定文件的名称和位置,classpath表示类路径。
*/
@Configuration
@ComponentScan("com.how2java")
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbcConfig.properties")
/**
* 主配置类,用于配置常用信息。
*/
public class SpringConfiguration {
}
JdbcConfig.java
package com.how2java.config;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import javax.sql.DataSource;
/**
* 子配置类,用于配置连接数据库的信息。
*/
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
/**
* 创建QueryRunner对象
* @param dataSource
* @return
*/
@Bean(name = "runner")
@Scope("prototype")
public QueryRunner createQueryRunner(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);
}
}
}
jdbcConfig.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring?characterEncoding=UTF-8
jdbc.username=root
jdbc.password=admin
TestAccount.java
package com.how2java;
import com.how2java.config.SpringConfiguration;
import com.how2java.domain.Account;
import com.how2java.service.IAccountService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
/**
* 使用junit测试配置
*/
public class TestAccount {
@Test
public void testFindAll() throws Exception {
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
IAccountService as = (IAccountService) ac.getBean("accountService");
List<Account> accounts = as.findAll();
for(Account account : accounts) {
System.out.println(account);
}
}
@Test
public void testFindOne() throws Exception {
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
IAccountService as = (IAccountService) ac.getBean("accountService");
Account account = as.findById(1);
System.out.println(account);
}
@Test
public void testSave() throws Exception {
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
IAccountService as = (IAccountService) ac.getBean("accountService");
Account account = new Account();
account.setName("ddd");
account.setMoney(1000F);
as.save(account);
}
@Test
public void testUpdate() throws Exception {
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
IAccountService as = (IAccountService) ac.getBean("accountService");
Account account = new Account();
account.setId(4);
account.setName("test");
as.update(account);
}
@Test
public void testDelete() throws Exception {
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
IAccountService as = (IAccountService) ac.getBean("accountService");
as.delete(4);
}
}
TestQueryRunner.java
package com.how2java;
import com.how2java.config.SpringConfiguration;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* 测试QueryRunner是否单例
*/
public class TestQueryRunner {
@Test
public void testQueryRunner() throws Exception {
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
QueryRunner runner1 = ac.getBean("runner", QueryRunner.class);
QueryRunner runner2 = ac.getBean("runner", QueryRunner.class);
System.out.println(runner1==runner2);
}
}
Spring整合junit
1、应用程序的入口是main方法。
2、junit单元测试中没有main方法也能执行,这是因为junit集成了一个main方法,该方法会判断当前测试类中哪些方法有@Test注解,然后执行这些有注解的方法。
3、junit在执行测试方法时并不知道使用了Spring框架,所以不会去读取配置文件或配置类并创建核心容器。
4、当测试方法执行时没有IOC容器,即使写@Autowire注解,也无法实现注入。
TestAccount.java
package com.how2java;
import com.how2java.config.SpringConfiguration;
import com.how2java.dao.IAccountDao;
import com.how2java.domain.Account;
import com.how2java.service.IAccountService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
/**
* 使用junit测试配置
* Spring整合junit:
* 1、导入Spring整合junit的jar包;
* 2、使用junit提供的注解RunWith替换原有main方法;
* 3、使用注解ContextConfiguration告知Spring运行器:
* SpringIOC创建是基于注解还是XML,并且说明位置。
* locations:指定XML文件的位置,classpath表示类路径。
* classes:指定注解类所在位置。
* 当使用Spring5.x版本时,要求junit的jar包必须是4.12以上。
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class TestAccount {
@Autowired
private IAccountService as;
@Test
public void testFindAll() throws Exception {
List<Account> accounts = as.findAll();
for(Account account : accounts) {
System.out.println(account);
}
}
@Test
public void testFindOne() throws Exception {
Account account = as.findById(1);
System.out.println(account);
}
@Test
public void testSave() throws Exception {
Account account = new Account();
account.setName("ddd");
account.setMoney(1000F);
as.save(account);
}
@Test
public void testUpdate() throws Exception {
Account account = new Account();
account.setId(4);
account.setName("test");
as.update(account);
}
@Test
public void testDelete() throws Exception {
as.delete(4);
}
}