8.使用配置类(ConfigurationTest)来进行管理/替代Spring中bean.xml

1.看图

 8.使用配置类(ConfigurationTest)来进行管理/替代Spring中bean.xml

2.实体类:

package com.domin;

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 +
                '}';
    }
}

//(重写toString)

3.业务层接口:IAccountService

package com.service;

import com.domin.Account;

import java.util.List;

public interface IAccountService {

    /*查询所有*/
    List<Account> findAllAccount();
    /*查询一个*/
    Account findAccountById(Integer accountId);
    /*保存一个*/
    void saveAccount(Account account);
    /*更新*/
    void updateAccount(Account account);
    /*删除一个*/
    void deleteAccount(Integer accountId);

}

 4.业务层实现类(写入方法)AccountServiceImp:

package com.service.Imp;

import com.dao.IAccountDao;
import com.domin.Account;
import com.service.IAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/*交给spring容器去管理*/
@Service("accountService")
public class AccountServiceImp implements IAccountService {
    /*交给spring容器去管理:配置accountService中的accountDao*/
    @Autowired
    //调用持久层
    private IAccountDao accountDao;
    /*当使用注解的时候,set方法就不是必须的了*/
    /*public void setAccountDao(IAccountDao accountDao) {
        this.accountDao = accountDao;
    }*/

    @Override
    public List<Account> findAllAccount() {
        return accountDao.findAllAccount();
    }

    @Override
    public Account findAccountById(Integer accountId) {

        return accountDao.findAccountById(accountId);
    }

    @Override
    public void saveAccount(Account account) {
        accountDao.saveAccount(account);
    }

    @Override
    public void updateAccount(Account account) {
        accountDao.updateAccount(account);
    }

    @Override
    public void deleteAccount(Integer accountId) {
        deleteAccount(accountId);
    }
}

 5.持久层接口IAccountDao:

package com.dao;

import com.domin.Account;

import java.util.List;

public interface IAccountDao {

    /*查询所有*/
    List<Account> findAllAccount();
    /*查询一个*/
    Account findAccountById(Integer accountId);
    /*保存一个*/
    void saveAccount(Account account);
    /*更新*/
    void updateAccount(Account account);
    /*删除一个*/
    void deleteAccount(Integer accountId);
}

 6.持久层实现类:AccountDaoImp

package com.dao.Imp;

import com.dao.IAccountDao;
import com.domin.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.util.List;

/*交给spring去管理*/
@Repository("accountDao")
public class AccountDaoImp implements IAccountDao {
    @Autowired/*不指定的话默认类名为id*/
    private QueryRunner runner;/*自动注入它的方法:当使用注解的时候set的方法既不是必须的了*/
    /*public void setRunner(QueryRunner runner) {
        this.runner = runner;
    }*/

    @Override
    public List<Account> findAllAccount() {

        /*泛型使用字解码创建对象*/
        try{
            return runner.query("select * from account",new BeanListHandler<Account>(Account.class));
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    @Override
    public Account findAccountById(Integer accountId) {
        try{
            return runner.query("select * from account where id = ?",new BeanHandler<Account>(Account.class),accountId);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    @Override
    public void saveAccount(Account account) {
        try{
            runner.update("insert into account(name,money)value(?,?)",account.getName(),account.getMoney());
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    @Override
    public void updateAccount(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 deleteAccount(Integer accountId) {
        try{
            runner.update("delete from account where id=?",accountId);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
}

 7.配置类(大模块)ConfigurationTest

package 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对象创建的参数的时候,该注解可以不写。
*           (在测试类当中,直接通过类名.class传入,然后注解直接被扫描解读、、但是不绝对)
*       为什么:当你独立开始使用jdbcConfig的时候,那么AnnotationConfigApplicationContext里面的配置文件
*               不再进行整个包的扫描,而是只单独解析类,所以,我们的@Configuration得注上,预防隔离开来的单独一个文件,
*               所以进行扫描包的注解还是必须的
*
* ComponentScan
*       作用:用于通过注解指定spring在创建容器时要扫描的包。
*       属性:
*           value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。
*                   我们使用此注解就等同于在XML中配置了:扫描包的语法
*               <context:component-scan base-package="com"></context:component-scan>
* Bean
*       作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中
*               (容器是有键值对的[key,value],不写有默认值)
*       属性:
*           name:用于指定bean的id。默认值是当前方法的名称
*       细节:当我们使用注解配置方法的时候,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象
*               查找的方式和Autowired是一样的
*           Scope:作用域(单例singleton、多例prototype)
* Import
*       作用:用于导入其他的配置类 统一在大模块中导入,然后分别写小的子类模块就可以
*       属性:
*           value:用于指定其他配置类的字节码。
*                   当我们使用Import的注解之后,有Import注解的类就是父配置类,而导入的都是子配置类
* */
/*替代xml中的配置文件*/
@Configuration
//@ComponentScan({"com","config"}) 这里多个必须使用对象
@ComponentScan("com")
@Import(JdbcConfig.class)/*引入*/
public class ConfigurationTest {
   /*
   * 用于创建一个 QueryRunner对象
   *
   * */
   /*全部移入到JdbcConfig中去*/
//    @Bean(name="runner")/*用于把当前方法的返回值作为bean对象存入spring的ioc容器中*/
//    @Scope("prototype")/*默认单例,变为多例*/
//    public QueryRunner createQueryRunner(DataSource dataSource){
//         return new QueryRunner (dataSource);
//    }
//    /*
//    * 创建数据源对象
//    *
//    * */
//    /*和上面的dataSource一样:这样容器中就有了这个对象,就不会报错*/
//    @Bean(name = "dataSource")
//    public DataSource createDataSource(){
//        try {
//            ComboPooledDataSource dataSource = new ComboPooledDataSource();
//            dataSource.setDriverClass("com.mysql.jdbc.Driver");
//            dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/eesy");
//            dataSource.setUser("root");
//            dataSource.setPassword("123456");
//            return dataSource;
//        }catch (Exception e){
//            throw new RuntimeException(e);
//        }
//    }
}

8.配置类子模块:JdbcConfig

package config;


/*
* 使用Junit单元测试,测试我们的配置
*
* */

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

import javax.sql.DataSource;

//@Configuration 已经在大模块使用@Import了
public class JdbcConfig {

    @Bean(name="runner")/*用于把当前方法的返回值作为bean对象存入spring的ioc容器中*/
    @Scope("prototype")/*默认单例,变为多例*/
    public QueryRunner createQueryRunner(DataSource dataSource){
        return new QueryRunner (dataSource);
    }
    /*
     * 创建数据源对象
     *
     * */
    /*和上面的dataSource一样:这样容器中就有了这个对象,就不会报错*/
    @Bean(name = "dataSource")
    public DataSource createDataSource(){
        try {
            ComboPooledDataSource dataSource = new ComboPooledDataSource();
            dataSource.setDriverClass("com.mysql.jdbc.Driver");
            dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/eesy");
            dataSource.setUser("root");
            dataSource.setPassword("123456");
            return dataSource;
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
/*
* 总结一下:原来JdbcConfig里面的东西是放在ConfigurationTest里面的,相当于,大模块是ConfigurationTest 然后
*   1. 大模块里面需要扫描包@ComponentScan({"com"})[email protected]容器配置注解(当这样的时候,可以写,也可以不写这一个)
*       并且配置ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigurationTest.class);
*   2. 但是小模块分离出来之后JdbcConfig,
*       大模块里面的就变为了这样@ComponentScan({"com","config"})[email protected](/或者/dbcConfig.class)其中一个
*       在小模块中的注解才能被扫描到JdbcConfig中的注解
*   3.我也知道这种方式很繁琐,比较容易乱,所以想要原来的方式,就用到这个注释:@import
*       使用Import的注解就(细节:import可以传多个)
*       大模块ConfigurationTest中:@[email protected]("com")[email protected](JdbcConfig.class)+ ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigurationTest.class);
*       就可以了
*
* */
}

9.测试类:TestCode

package com.itheima;

import com.domin.Account;
import com.service.IAccountService;
import config.ConfigurationTest;
import config.JdbcConfig;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.List;

public class TestCode {
    @Test
    public void findAllAccount() {
        /*bean.xml 配置文件中*/
//        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        /*配置类的注解方式使用的*/
        ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigurationTest.class);
        IAccountService as = (IAccountService) ac.getBean("accountService");
        /*类型要注意*/
        List<Account> accounts = as.findAllAccount();
        for (Account account :accounts){
            System.out.println(account);
        }

    }
    @Test
    public void findAccountById() {
//      ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        /*配置类的注解方式使用的*/
        ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigurationTest.class);
        IAccountService as = (IAccountService) ac.getBean("accountService");
        Account acc = as.findAccountById(4);
        System.out.println(acc);

    }
    @Test
    public void saveAccount() {
//        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigurationTest.class);
        IAccountService as = (IAccountService) ac.getBean("accountService");
        Account acc = new Account();
        acc.setName("lalala");
        acc.setMoney((float)10000000.00);
        as.saveAccount(acc);
        System.out.println("执行成功");

    }
    @Test
    public void updateAccount() {
//        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigurationTest.class);
        IAccountService as = (IAccountService) ac.getBean("accountService");
        Account id =  as.findAccountById(9);
        id.setName("zhou");
        id.setMoney((float)100000.00);
        /*调用存放*/
        as.updateAccount(id);
    }
    @Test
    public void deleteAccount() {
        /*bean.xml可以删了*/
//        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigurationTest.class);
        IAccountService as = (IAccountService) ac.getBean("accountService");
        as.deleteAccount(9);
    }
}

注:检查单例和多例
10.QueryRunnerTest
package com.itheima;

import config.ConfigurationTest;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class QueryRunnerTest {
    @Test
    public void RunnerTest() {
        ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigurationTest.class);
        /*两种方式都可以,获取QueryRunner的对象runner1和runner2,查看是否单例还是多例*/
        QueryRunner runner1 = ac.getBean("runner",QueryRunner.class);
        QueryRunner runner2 = (QueryRunner) ac.getBean("runner");
        if (runner1 == runner2){
            System.out.println("一样:"+runner1+"\n"+runner2);
        }else{
            System.out.println("不一样:"+runner1+"\n"+runner2);
        }

    }
    /*执行sql语句的时候:在持久层的实现类,使用该方法可以会造成占用,所以变为多例*/
}

10.pom.xml依赖

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.11</version>
  <scope>test</scope>
</dependency>

  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
  </dependency>
  <!--spring框架依赖-->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.2.RELEASE</version>
  </dependency>
  <!--C3P0依赖-->
  <dependency>
    <groupId>c3p0</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.1.2</version>
  </dependency>
  <!--jdbc依赖-->
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.10</version>
    <scope>test</scope>
  </dependency>
  <!--dubcy依赖-->
  <dependency>
    <groupId>commons-dbutils</groupId>
    <artifactId>commons-dbutils</artifactId>
    <version>1.6</version>
  </dependency>
  <!--    mysql-->
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.6</version>
  </dependency>

总结:在配置类中的常用注解

* 该类是一个配置类,它的作用和bean.xml是一样的
* spring中的新注解
* Configuration
*       作用:指定当前类是一个配置类
*       细节:
*           当配置类作为AnnotationConfigApplicationContext对象创建的参数的时候,该注解可以不写。
*           (在测试类当中,直接通过类名.class传入,然后注解直接被扫描解读、、但是不绝对)
*       为什么:当你独立开始使用jdbcConfig的时候,那么AnnotationConfigApplicationContext里面的配置文件
*               不再进行整个包的扫描,而是只单独解析类,所以,我们的@Configuration得注上,预防隔离开来的单独一个文件,
*               所以进行扫描包的注解还是必须的
*
* ComponentScan
*       作用:用于通过注解指定spring在创建容器时要扫描的包。
*       属性:
*           value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。
*                   我们使用此注解就等同于在XML中配置了:扫描包的语法
*               <context:component-scan base-package="com"></context:component-scan>
* Bean
*       作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中
*               (容器是有键值对的[key,value],不写有默认值)
*       属性:
*           name:用于指定bean的id。默认值是当前方法的名称
*       细节:当我们使用注解配置方法的时候,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象
*               查找的方式和Autowired是一样的
*           Scope:作用域(单例singleton、多例prototype)
* Import
*       作用:用于导入其他的配置类 统一在大模块中导入,然后分别写小的子类模块就可以
*       属性:
*           value:用于指定其他配置类的字节码。
*                   当我们使用Import的注解之后,有Import注解的类就是父配置类,而导入的都是子配置类
*

注:本人是小白,学习上的错误还希望大家多多指教,共同进步才好,加油加油