1. jdbcConfig.properties配置
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/maven?serverTimezone=GMT%2B8
jdbc.username=root
jdbc.password=jh7851192
2.列出主要代码(没列出的就沿用之前的代码)
1.dao层
AccountDaoImpl实现类部分代码
@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {
@Autowired
private QueryRunner runner;
@Override
public List<Account> findAllAccount() {
try {
//这里是在Spring里应用数据库连接(sql语句查询);
//Account.class是查询的实体类关联,这里是List集合,用到BeanListHandler
return runner.query("select * from account",new BeanListHandler<Account>(Account.class));
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
2. service层
AccountServiceImpl部分代码
@Service("accountService")
public class AccountServiceImpl implements IAccountService {
@Autowired
private IAccountDao accountDao;
3. spring新注解
SpringConfiguration类是一个配置类:它的作用和bean.xml是一样的。
Spring中的新注解:
(1)Configuration
- 作用:指定当前类是一个配置类
- 细节:当该配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。
(2)ComponentScan
- 作用:用于通过注解指定Spring在创建容器时要扫描的包
- 属性:value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。
我们使用此注解就等同于在xml中配置了:
<context:component-scan base-package=“com.jh”></context:component-scan>
(3)Bean
- 作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中
- 属性: name:用于指定bean的id。当不写时,默认值是当前方法的名称
- 细节:
当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象。
查找的方式和Autowired注解的作用是一样的。
(4)Import
- 作用:用于导入其他的配置类
- 属性:value:用于指定其他配置类的字节码。
- 当我们使用Import的注解之后,有Import注解的类就父配置类,而导入的都是子配置类
(5)PropertySource
- 作用:用于指定properties文件的位置
- 属性:value:指定文件的名称和路径。
- 关键字:classpath,表示类路径
SpringConfiguration.java(主配置去调用其他配置)
package config;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.context.annotation.*;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
//@Configuration
//@ComponentScan({"com.jh","config"})
@ComponentScan("com.jh")
@Import(JdbcConfig.class)
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfiguration {
/*主配置类,导入了JdbcConfig其他配置类*/
}
JdbcConfig.java(其他配置)
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.Configuration;
import org.springframework.context.annotation.Scope;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
/**
* 和spring连接数据库相关的配置类(公共配置)
* */
//@Configuration//该注解不能省略,因为没有作为AnnotationConfigApplicationContext对象创建的参数
//如果想要省略@Configuration注解,则需要@Import注解,见SpringConfiguration.java
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对象
@Bean(name = "runner")
@Scope("prototype")
//@Qualifier该注解给方法参数注入时可以单独使用
public QueryRunner createQueryRunner(@Qualifier("ds1") DataSource dataSource){
return new QueryRunner(dataSource);
}
//用于创建数据源对象
@Bean(name = "ds1")//dataSource要和上面的DataSource dataSource一致
public DataSource createDataSource1(){
try {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setDriverClass(driver);
ds.setJdbcUrl(url);
ds.setUser(username);
ds.setPassword(password);
return ds;
} catch (PropertyVetoException e) {
throw new RuntimeException(e);
}
}
@Bean(name = "ds2")//dataSource要和上面的DataSource dataSource一致
public DataSource createDataSource2(){
try {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setDriverClass(driver);
ds.setJdbcUrl("jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8");
ds.setUser(username);
ds.setPassword(password);
return ds;
} catch (PropertyVetoException e) {
throw new RuntimeException(e);
}
}
}
AnnotationConfigApplicationContext注解获取容器
public void init(){
//1.使用注解获取容器
ac=new AnnotationConfigApplicationContext(SpringConfiguration.class);
//2.得到业务层对象(bean对象),name的id要与bean.xml中id一样accountService
as = ac.getBean("accountService",IAccountService.class);
4. spring和Junit整合
1、应用程序的入口
main方法
2、junit单元测试中,没有main方法也能执行
junit集成了一个main方法
该方法就会判断当前测试类中哪些方法有 @Test注解
junit就让有Test注解的方法执行
3、junit不会管我们是否采用spring框架
在执行测试方法时,junit根本不知道我们是不是使用了spring框架
所以也就不会为我们读取配置文件/配置类创建spring核心容器
4、由以上三点可知
当测试方法执行时,没有Ioc容器,就算写了Autowired注解,也无法实现注入
解决上述问题:
下面的2个注解会创建spring核心容器和bean对象,帮助我们省略测试代码创建容器和bean对象的步骤。
Spring整合junit的配置
1、导入spring整合junit的jar(坐标)
2、使用Junit提供的一个注解把原有的main方法替换了,替换成spring提供的: @Runwith
3、告知spring的运行器,spring和ioc创建是基于xml还是注解的,并且说明位置 :@ContextConfiguration
- locations:指定xml文件的位置,加上classpath关键字,表示在类路径下
- classes:指定注解类所在的位置
4.当我们使用spring 5.x版本的时候,要求junit的jar必须是4.12及以上
测试代码:AccountServiceTest
package com.jh.test;
import com.jh.domain.Account;
import com.jh.service.IAccountService;
import config.SpringConfiguration;
import org.junit.Before;
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单元测试,测试我们的配置
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)//没有xml配置文件,指定注解类
public class AccountServiceTest {
@Autowired
private IAccountService as = null;
/* @Before Spring整合junit的配置可以省略这些重复步骤
public void init(){
//1.使用注解获取容器
ac=new AnnotationConfigApplicationContext(SpringConfiguration.class);
//2.得到业务层对象(bean对象),name的id要与bean.xml中id一样accountService
as = ac.getBean("accountService",IAccountService.class);
}*/
@Test
public void testFindAll(){
//3.执行方法
List<Account> accounts=as.findAllAccount();
for (Account account:accounts){
System.out.println(account);
/*Account{id=1, name='aaa', money=1000.0}
Account{id=2, name='bbb', money=1000.0}
Account{id=3, name='ccc', money=1000.0}*/
}
}
@Test
public void testFindOne(){
//3.执行方法
System.out.println(as.findAccountById(2));
/*Account{id=2, name='bbb', money=1000.0}*/
}
@Test
public void testSave(){
Account account=new Account();
account.setName("郭会技");
account.setMoney(12782f);
//3.执行方法
as.saveAccount(account);
/*Account{id=5, name='郭会技', money=12782.0}*/
}
@Test
public void testUpdate(){
//3.执行方法
Account account=as.findAccountById(5);
account.setMoney(12213f);
account.setName("jh");
as.updateAccount(account);
}
@Test
public void testDelete(){
//3.执行方法
as.deleteAccount(4);
}
}