Spring黑马:SpringIOC案例(JDBC数据库):Spring新注解(删除bean.xml文件)+Junit整合

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

4. spring和Junit整合

1、应用程序的入口
main方法
2、junit单元测试中,没有main方法也能执行
junit集成了一个main方法
该方法就会判断当前测试类中哪些方法有 @Test注解
junit就让有Test注解的方法执行
3、junit不会管我们是否采用spring框架
在执行测试方法时,junit根本不知道我们是不是使用了spring框架
所以也就不会为我们读取配置文件/配置类创建spring核心容器

4、由以上三点可知
当测试方法执行时,没有Ioc容器,就算写了Autowired注解,也无法实现注入


解决上述问题
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);
    }
}
发布了95 篇原创文章 · 获赞 15 · 访问量 5895

猜你喜欢

转载自blog.csdn.net/JH39456194/article/details/104400524