您的位置:首页 > 编程语言 > Java开发

spring2

2018-11-15 09:38 85 查看

Spring第二天

回顾:

  1. IOC:控制反转,把对象的创建权利反转给spring框架。
  2. IOC的作用:解耦
  3. Spring中的工厂: ApplicationContext ClassPathXmlApplicationContext
  4. FileSystemXmlApplicationContext
  • BeanFactory
    1. spring的配置文件 bean标签 id
    2. class
    3. scope:singleton/prototype
    4. init-method
    5. destroy-method
  • import标签
  • Spring中生成bean的三种方式
      无参构造
    1. 静态工厂方式实例化
    2. 实例工厂方式实例化
    1. DI:依赖注入 构造方法注入
    2. Set方法注入:先找无参构造实例对象,再调用属性的set方法注入值 P命名空间的写法
    3. SpEl的写法
  • 特殊类型的注入
      List/Array
    1. Set
    2. Map
    3.   Properties
    1. Spring IOC注解的快速入门 创建Java工程并导入jar包
    1. 需要导入IOC容器需要的6个jar包+spring-aop.jar

    1. 创建包结构并编写Java类
  • 创建UserService接口
  • package cn.itcast.service;

     

    public interface UserService {

      

       /**

        * 业务层:用户保存

        */

       public void saveUser();

      

    }

    1. 创建UserService的实现类UserServiceImpl

    package cn.itcast.service.impl;

     

    import cn.itcast.service.UserService;

     

    public class UserServiceImpl implements UserService {

     

       @Override

       public void saveUser() {

          System.out.println("业务层:用户保存...");

       }

     

    }

    1. 在Java类上添加注解
  • 在UserServiceImpl实现类上添加注解@Component,相当于<bean id=”” class=””>,value属性给bean指定id,value属性的名字也可以不写
  • @Component("userService")

    public class UserServiceImpl implements UserService{

     

       @Override

       public void saveUser() {

          System.out.println("业务层:用户保存...");

       }

     

    }

    1. 在applicationContext.xml中引入约束

    在src目录下,创建applicationContext.xml的配置文件,引入约束。注意:因为现在想使用注解,那么引入的约束发生了变化,需要context的约束。同时还要引入log4j.properties.

    【提示】:约束可以从spring开发文档中拷贝,也可以从笔记里拷贝。如果从spring开发文档中拷贝,可以参考spring开发文档的6.9节

    添加完context约束之后的applicationContext.xml内容如下:

    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xmlns:context="http://www.springframework.org/schema/context"

        xsi:schemaLocation="http://www.springframework.org/schema/beans

            http://www.springframework.org/schema/beans/spring-beans.xsd

            http://www.springframework.org/schema/context

            http://www.springframework.org/schema/context/spring-context.xsd">

         

    </beans>

    1. 在applicationContext.xml中开启注解扫描

    在applicationContext.xml通过context:component-scan标签开启spring注解扫描,扫描时是以包范围来扫描的:

    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xmlns:context="http://www.springframework.org/schema/context"

        xsi:schemaLocation="http://www.springframework.org/schema/beans

            http://www.springframework.org/schema/beans/spring-beans.xsd

            http://www.springframework.org/schema/context

            http://www.springframework.org/schema/context/spring-context.xsd">

          <!-- 开启注解扫描 -->

          <context:component-scan base-package="cn.itcast.service.impl"></context:component-scan>

    </beans>

    1. 编写测试代码
  • 创建单元测试类TestIOC,在其中创建单元测试方法test1
  • /**

        * 测试注解

    */

    @Test

    public void test1(){

          ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

          UserService userService = (UserService) applicationContext.getBean("userService");

          userService.saveUser();

    }

    1. Spring框架中bean管理的常用注解

    Spring中用于管理bean的注解分为四大类:

    1. 用于创建对象
    2. 用于给对象中的属性注入值
    3. 用于改变作用范围
    4. 用于定义生命周期 用于创建对象的(重点)

    用于创建对象的有四个:@Component,@Controller,@Service,@Repository

    1. @Component注解

    作用:

        把资源让spring来管理。相当于在xml中配置一个bean。

    属性:

        value:指定bean的id。如果不指定value属性,默认bean的id是当前类的类名。首字母小写。  

    1. @Controller @Service @Repository

    他们三个注解都是针对一个的衍生注解,他们的作用及属性都是一模一样的。

    他们只不过是提供了更加明确的语义化。

        @Controller一般用于表现层的注解。

        @Service一般用于业务层的注解。

        @Repository一般用于持久层的注解。

    @Service的用法:修改UserServiceImpl类,把@Component改成@Service

    //@Component("userService")

    @Service("userService")

    public class UserServiceImpl implements UserService{

     

       @Override

       public void saveUser() {

          System.out.println("业务层:用户保存...");

       }

     

    }

    @Repository的用法:

    创建UserDao接口:

    public interface UserDao {

     

       public void save();

      

    }

    创建UserDao接口的实现类UserDaoImpl,在该类上加@Repository注解

    @Repository("userDao")

    public class UserDaoImpl implements UserDao {

     

       @Override

       public void save() {

          System.out.println("持久层:用户保存...");

       }

     

    }

    注意:此处测试时,要把扫描的包定义为cn.itcast,不然的其它包的注解就不能识别了

    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xmlns:context="http://www.springframework.org/schema/context"

        xsi:schemaLocation="http://www.springframework.org/schema/beans

            http://www.springframework.org/schema/beans/spring-beans.xsd

            http://www.springframework.org/schema/context

            http://www.springframework.org/schema/context/spring-context.xsd">

          <!-- 开启注解扫描 -->

          <context:component-scan base-package="cn.itcast"></context:component-scan>

    </beans>

     

     

    @Controller的用法:创建UserAction类,在该类上加@Controller注解

    @Controller("userAction")

    public class UserAction {

     

    }

     

    说明:这三个注解是为了让标注类本身的用途清晰

    1. 用于注入数据的

    用于注入数据的注解有:

    1. @Value
    2. @Autowired
    3. @Qualifier
    4. @Resource

    相当于:<property name="" ref="">        

                  <property name="" value="">

    1. @Value

    作用:

        注入基本数据类型和String类型数据的

    属性:

        value:用于指定值

    修改UserServiceImpl类,增加一个字符串属性name,现在要通过@Value给name属性注入值

    @Service("userService")

    public class UserServiceImpl implements UserService {

      

       @Value("张三")

       private String name;

     

       @Override

       public void saveUser() {

          System.out.println("业务层:用户保存..." + name);

       }

     

    }

    运行TestIOC中的test1方法,测试结果如下:

    1. @Autowired(重点)

    作用:

        自动按照类型注入。当使用注解注入属性时,set方法可以省略。它只能注入其他bean类型。当有多个类型匹配时,使用要注入的对象变量名称作为bean的id,在spring容器查找,找到了也可以注入成功。找不到就报错。

    修改UserServiceImpl类,增加一个对象属性userDao,现在通过@Autowired给userDao注入值

    @Service("userService")

    public class UserServiceImpl implements UserService {

      

       @Value("张三")

       private String name;

      

       @Autowired

       private UserDao userDao;

     

       @Override

       public void saveUser() {

          System.out.println("业务层:用户保存..." + name);

          userDao.save();

       }

     

    }

    运行TestIOC中的test1方法,测试结果如下:

    1. @Qualifer

    作用:

        在自动按照类型注入的基础之上,再按照Bean的id注入。它在给字段注入时不能独立使用,必须和@Autowire一起使用;但是给方法参数注入时,可以独立使用。

    属性:

        value:指定bean的id。

     

    1. 创建UserDao接口的第二个实现类UserDaoImpl2

    @Repository("userDao2")

    public class UserDaoImpl2 implements UserDao {

     

       @Override

       public void save() {

          System.out.println("持久层:用户保存2222...");

       }

    }

    运行TestIOC中的test1方法,测试结果如下:

     

    1. 测试发现,UserServiceImpl中注入的还是第一个UserDaoImpl,因为当有多个bean都满足的情况下,优先注入bean的id与属性的名字一样的bean;想指定注入UserDaoImpl2,需要使用@Qualifier注解根据名字来注入

    @Service("userService")

    public class UserServiceImpl implements UserService {

      

       @Value("张三")

       private String name;

      

       @Autowired

       @Qualifier("userDao2")

       private UserDao userDao;

     

       @Override

       public void saveUser() {

          System.out.println("业务层:用户保存..." + name);

          userDao.save();

       }

     

    }

    再次运行TestIOC中的test1方法,发现UserServiceImpl中注入的是UserDaoImpl2;测试结果如下:

     

    1. @Resource

    作用:

        直接按照Bean的id注入。它也只能注入其他bean类型。

    属性:

        name:指定bean的id。

    修改UserServiceImpl类,使用@Resource给userDao注入值。@Resource是按照bean的id来注入,只能注入对象类型

    @Service("userService")

    public class UserServiceImpl implements UserService {

      

       @Value("张三")

       private String name;

      

    // @Autowired

    // @Qualifier("userDao2")

       @Resource(name="userDao2")

       private UserDao userDao;

     

       @Override

       public void saveUser() {

          System.out.println("业务层:用户保存..." + name);

          userDao.save();

       }

     

    }

     

    1. 用于改变作用域范围的 @Scope(重点)

    作用:

        指定bean的作用范围。

    属性:

        value:指定范围的值。

               取值:singleton  prototype request session globalsession

     

    1. @Scope指定bean的作用域,默认值是singleton,单例的。
    1. 修改UserServiceImpl,在该类上加@Scope注解,指定该类是多例的的,默认是单例的。给该类显示指定一个无参构造方法,方便测试

    @Service("userService")

    @Scope("prototype")

    public class UserServiceImpl implements UserService{

      

       @Value("张三")

       private String name;

      

    // @Autowired

    // @Qualifier("userDao2")

       @Resource(name="userDao2")

       private UserDao userDao;

     

     

    public UserServiceImpl() {

          System.out.println("调用了无参构造方法...");

       }

     

       @Override

       public void saveUser() {

          System.out.println("业务层:用户保存..." + name);

          userDao.save();

       }

     

    }

    1. 在TestIOC中创建test2单元测试方法

       @Test

       public void test2(){

          //创建ioc容器

          ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

          UserService userService1 = (UserService) ac.getBean("userService");

          UserService userService2 = (UserService) ac.getBean("userService");

          System.out.println(userService1 == userService2);

       }

    1. 测试发现:当scope指定为prototype时,两次获取UserService的对象是不一致的。测试结果如下:

    1. 和生命周期相关的

    相当于:<bean id="" class="" init-method="" destroy-method="" />

    1. @PostConstruct注解

    @PostConstruct加在方法上,指定bean对象创建好之后,调用该方法初始化对象,类似于xml的init-method方法。修改UserServiceImpl类,在其中增加一个init方法,在该方法上指定@PostConstruct注解

    @Service("userService")

    public class UserServiceImpl implements UserService {

      

       @Value("张三")

       private String name;

      

    // @Autowired

    // @Qualifier("userDao2")

       @Resource(name="userDao2")

       private UserDao userDao;

      

       public UserServiceImpl() {

          System.out.println("调用了无参构造方法...");

       }

      

       @PostConstruct

       public void init(){

          System.out.println("调用了init方法...");

       }

     

       @Override

       public void saveUser() {

          System.out.println("业务层:用户保存..." + name);

          userDao.save();

       }

    }

    运行TestIOC中的test1方法,测试结果如下:

    1. @PreDestory注解

    @PreDestory加在方法上,指定bean销毁之前,调用该方法,类似于xml的destory-method方法。修改UserServiceImpl类,在该类中增加一个destroy方法,在该方法上加@PreDestroy注解

    @Service("userService")

    public class UserServiceImpl implements UserService {

      

       @Value("张三")

       private String name;

      

    // @Autowired

    // @Qualifier("userDao2")

       @Resource(name="userDao2")

       private UserDao userDao;

      

       public UserServiceImpl() {

          System.out.println("调用了无参构造方法...");

       }

      

       @PostConstruct

       public void init(){

          System.out.println("调用了init方法...");

       }

     

       @Override

       public void saveUser() {

          System.out.println("业务层:用户保存..." + name);

          userDao.save();

       }

      

       @PreDestroy

       public void destroy(){

          System.out.println("调用了destroy方法...");

       }

     

    }

    注意:要看到@PreDestory的效果,需要调用ClassPathXmlApplicationContext.close方法,同时scope的值要是singleton。所以,还得修改test1方法,显示关闭ioc容器

    @Test

       public void test1(){

          //创建ioc容器

          ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

          UserService userService = (UserService) ac.getBean("userService");

          userService.saveUser();

          ((ClassPathXmlApplicationContext)ac).close();

       }

    测试结果如下:

    1. XML和注解的比较

    注解的优势:

        配置简单,维护方便。(我们找到了类,就相当于找到了配置)

    XML的优势:

        修改时,不用改源码。不涉及重新编译和部署。

     

    Xml和注解的比较

    1. 案例:Spring整合DBUtils实现增删改查 2第一步:创建工程,导入jar包

    需要导入的jar包有:spring ioc必要的六个jar包+c3p0+mysql驱动包。完成的jar包如下图所示:

    1. 第二步:创建业务层接口及实现类

    创建Customer实体类

    创建CustomerService接口

    public interface CustomerService {

     

       /**

        * 业务层:查询所有客户

        * @return

        */

       public List<Customer> findAllCustomer();

      

    }

    创建CustomerService接口的实现类CustomerServiceImpl

    public class CustomerServiceImpl implements CustomerService {

      

       private CustomerDao customerDao;

      

     

       public void setCustomerDao(CustomerDao customerDao) {

          this.customerDao = customerDao;

       }

     

     

       @Override

       public List<Customer> findAllCustomer() {

          List<Customer> list = customerDao.findAll();

          return list;

       }

     

    }

    1. 第三步:创建dao层接口及实现类

    创建UserDao接口

    public interface CustomerDao {

     

       public List<Customer> findAll();

    }

    创建UserDao接口的实现类

    public class CustomerDaoImpl implements CustomerDao {

      

       private QueryRunner queryRunner;//不需要实例化,通过spring依赖注入进来

      

     

       public void setQueryRunner(QueryRunner queryRunner) {

          this.queryRunner = queryRunner;

       }

     

     

       @Override

       public List<Customer> findAll() {

          List<Customer> list = null;

          try {

             list = queryRunner.query("select * from cst_customer", new BeanListHandler<Customer>(Customer.class));

          } catch (SQLException e) {

             e.printStackTrace();

          }

          return list;

       }

    }

    1. 第四步:编写spring配置文件

    在src下创建spring的配置文件applicationContext.xml,把Service、Dao、QueryRunner、DataSource配置到Spring中

    1. Service中需要注入DAO
    2. DAO中需要注入QueryRunner
    3. QueryRunner中需要注入DataSource
    4. DataSource中需要注入驱动、连接地址、用户名、密码

    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xsi:schemaLocation="http://www.springframework.org/schema/beans

            http://www.springframework.org/schema/beans/spring-beans.xsd">

           

            <bean id="customerService" class="cn.itcast.service.impl.CustomerServiceImpl">

              <property name="customerDao" ref="customerDao"></property>

            </bean>

             <bean id="customerDao" class="cn.itcast.dao.impl.CustomerDaoImpl">

              <property name="queryRunner" ref="queryRunner"></property>

            </bean> 

            <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">

              <constructor-arg name="ds" ref="dataSource"></constructor-arg>

            </bean>

            <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

              <property name="driverClass" value="com.mysql.jdbc.Driver"></property>

              <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/hibernate"></property>

              <property name="user" value="root"></property>

              <property name="password" value="123456"></property>

            </bean>

    </beans>

    注意:还得引入log4j.properties文件

    1. 第五步:编写测试类

    创建单元测试类TestFind,在其中创建test1方法

    @Test

       public void test1(){

          ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

          CustomerService customerService = (CustomerService) ac.getBean("customerService");

          List<Customer> customers = customerService.findAllCustomer();

          for (Customer customer : customers) {

             System.out.println(customer);

          }

       }

    在这里测试的时候,实体类的属性名字要和数据库的属性名字一一对应,不然数据不能回显;

    测试结果如下:

    1. 案例:采用注解把Spring和DBUtils进行整合

    可以把第四章的工程里直接改成注解的形式

    1. 第一步:导入spring-aop.jar

    注意:注解开发需要额外导入spring-aop.jar

    1. 第二步:在类上加对应的注解

    修改CustomerServiceImpl类,在该类上加@Service注解。在customerDao上加@Autowired注解,表示给该属性注入值

    @Service("customerService")

    public class CustomerServiceImpl implements CustomerService {

      

       @Autowired

       private CustomerDao customerDao;

     

       @Override

       public List<Customer> findAllCustomer() {

          List<Customer> list = customerDao.findAllCustomer();

          return list;

       }

     

    }

    修改CustomerDaoImpl类,在该类上加@Repository注解。在queryRunner上加@Autowired注解,表示给该属性注入值。

    @Repository("customerDao")

    public class CustomerDaoImpl implements CustomerDao {

      

       @Autowired

       private QueryRunner queryRunner;

      

     

       @Override

       public List<Customer> findAll() {

          List<Customer> list = null;

          try {

             list = queryRunner.query("select * from cst_customer", new BeanListHandler<Customer>(Customer.class));

          } catch (SQLException e) {

             e.printStackTrace();

          }

          return list;

       }

     

    }

    1. 第三步:修改spring配置文件

    在applicationContext.xml中开启spring注解扫描。

    注意:QueryRunner和DataSource这两个bean暂时没有办法用注解来配置,因为属于jar包里的bean.

    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xmlns:context="http://www.springframework.org/schema/context"

        xsi:schemaLocation="http://www.springframework.org/schema/beans

            http://www.springframework.org/schema/beans/spring-beans.xsd

            http://www.springframework.org/schema/context

            http://www.springframework.org/schema/context/spring-context.xsd">

           

            <context:component-scan base-package="cn.itcast"></context:component-scan>

            <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">

              <constructor-arg name="ds" ref="dataSource"></constructor-arg>

            </bean>

            <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

              <property name="driverClass" value="com.mysql.jdbc.Driver"></property>

              <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/hibernate"></property>

              <property name="user" value="root"></property>

              <property name="password" value="123456"></property>

            </bean>

    </beans>

    再次运行TestFind中的test1方法,结果和xml的配置是一样的。

    1. 案例:采用Spring全注解整合DBUtils

    全注解整合的思路:要想实现全注解,得把applicationContext.xml的所有内容用一个类来配置。@Configuration注解可以表示一个类是配置类;@ComponentScan注解可以实现包扫描;还得想办法把QueryRunner和DataSource这两个bean用注解来配置。这个两个bean都是来自于jar包中的,用传统的注解配置方法是不可能实现的。得用@Bean注解,这个注解可以把某个方法的返回值存放到spring容器中。我们可以写两个方法,这两个方法分别返回QueryRunner对象和DataSource对象,然后在这两个方法上加@Bean注解,就可以保证spring容器中QueryRunner和DataSource这两个对象了。

    1. 第一步:创建spring配置类

    @Configuration//指定该类是spring的配置类,用来替换bean.xml

    @ComponentScan("cn.itcast")//指定要扫描的包

    public class SpringConfig {

     

       /**

        * Bean注解:把方法的返回值交给srping容器来管理

        * @param ds

        * @return

        */

       @Bean(name="queryRunner")

       public QueryRunner createQueryRunner(@Qualifier("dataSource") DataSource ds){

          return new QueryRunner(ds);

       }

      

       @Bean(name="dataSource")

       public DataSource createDataSource(){

          ComboPooledDataSource dataSource = new ComboPooledDataSource();

          try {

             dataSource.setDriverClass("com.mysql.jdbc.Driver");

             dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/hibernate");

             dataSource.setUser("root");

             dataSource.setPassword("123456");

          } catch (PropertyVetoException e) {

             e.printStackTrace();

          }

          return dataSource;

       }

    }

    1. 第二步:修改测试代码

    因为已经用SpringConfig类来代替applicationContext.xml了,所以,得更换ApplicationContext接口的实现类为AnnotationConfigApplicationContext

    @Test

       public void test1(){

    //    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

          ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);

          CustomerService customerService = (CustomerService) ac.getBean("customerService");

          List<Customer> customers = customerService.findAllCustomer();

          for (Customer customer : customers) {

             System.out.println(customer);

          }

       }

    运行test1方法,发现结果和之前是一致的。

    1. 第三步:把数据库连接相关的bean放到JdbcConfig类中

    下面,可以考虑优化SpringConfig配置类。在SpringConfig类中可能会出现很多方法,可以考虑实现分离。创建另一个配置类JdbcConfig,把createQueryRunner和createDataSource方法挪到JdbcConfig中:

    public class JdbcConfig {

      

       /**

        * Bean注解:把方法的返回值交给srping容器来管理

        * @param ds

        * @return

        */

       @Bean(name="queryRunner")

       public QueryRunner createQueryRunner(@Qualifier("dataSource") DataSource ds){

          return new QueryRunner(ds);

       }

      

       @Bean(name="dataSource")

       public DataSource createDataSource(){

          ComboPooledDataSource dataSource = new ComboPooledDataSource();

          try {

             dataSource.setDriverClass("com.mysql.jdbc.Driver");

             dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/hibernate");

             dataSource.setUser("root");

             dataSource.setPassword("123456");

          } catch (PropertyVetoException e) {

             e.printStackTrace();

          }

          return dataSource;

       }

    }

     

    在SpringConfig中引入JdbcConfig

    @Configuration//指定该类是spring的配置类,用来替换bean.xml

    @ComponentScan("cn.itcast")//指定要扫描的包

    @Import(JdbcConfig.class)

    public class SpringConfig {

     

     

    }

    1. 第四步:把数据库连接信息写到配置文件中

    此时,我们发现,数据库的驱动类名、连接地址、用户名、密码都是直接写死在类中的,不便于修改,可以把与数据库相关的信息写到jdbc.properties中。在src下创建jdbc.properties文件:

    jdbc.properties内容如下:

    jdbc.driverClass=com.mysql.jdbc.Driver

    jdbc.url=jdbc:mysql://localhost:3306/hibernate_itheima14

    jdbc.username=root

    jdbc.password=123456

    1. 第五步:在JdbcConfig中采用占位符读取配置文件中的信息

    修改JdbcConfig,定义四个成员变量,在每个成员变量上加@value注解,为该变量注入值,值来自于jdbc.properties.${}中写的是jdbc.properties中的键。

    public class JdbcConfig {

      

       @Value("${jdbc.driverClass}")

       private String driverClass;

       @Value("${jdbc.url}")

       private String jdbcUrl;

       @Value("${jdbc.username}")

       private String username;

       @Value("${jdbc.password}")

       private String password;

     

       @Bean(name="queryRunner")//把该方法的返回值放到ioc容器中,等价于<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">

       public QueryRunner createQueryRunner(@Qualifier("dataSource") DataSource ds){

          return new QueryRunner(ds);

       }

      

       @Bean(name="dataSource")//把该方法的返回值放到ioc容器中,  <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

       public DataSource createDataSource(){

          ComboPooledDataSource dataSource = new ComboPooledDataSource();

          try {

             dataSource .setDriverClass(driverClass);

             dataSource .setJdbcUrl(jdbcUrl);

             dataSource .setUser(username);

             dataSource .setPassword(password);

          } catch (PropertyVetoException e) {

             e.printStackTrace();

          }

          return ds;

       }

    }

     

    1. 第六步:在SpringConfig中配置占位符解析器

    在SpringConfig中需要通过@PropertySource注解引入外部属性文件jdbc.properties;还要在SpringConfig类中配置一个占位符$的解析器,这样才能解析${jdbc.username}这样的表达式

    @Configuration//指定该类是spring的配置类,用来替换bean.xml

    @ComponentScan("cn.itcast")//指定要扫描的包

    @Import(JdbcConfig.class)

    @PropertySource("classpath:cn/itcast/config/jdbc.properties")

    public class SpringConfig {

     

       @Bean

       public PropertySourcesPlaceholderConfigurer createPropertySourcesPlaceholderConfigurer(){

          return new PropertySourcesPlaceholderConfigurer();

       }

    }

    最后,再次运行test1方法进行测试。

    1. Spring框架整合JUnit单元测试 目的

    为了简化了JUnit的测试,使用Spring框架也可以整合测试。

    1. 具体步骤

    要求:必须先有JUnit的环境(默认会使用Eclipse导入单元测试的环境)!!

    1. 步骤一:在程序中引入spring-test.jar

    可以直接在spring4_day02中引入spring-test.jar包,把spring4_day02中的单元测试类全部改成spring的写法

    注意:spring单元测试还得要有spring-aop.jar包,因为spring单元测试会用到注解

    1. 步骤二:在具体测试类上添加注解

    修改单元测试类TestIOC,在该类上添加@RunWith和@ContextConfiguration两个注解。我们需要测试的是UserService,在TestIOC中声明一个UserService的属性,并在该属性上添加@Autowired注解,为该属性注入值。修改后的TestIOC如下:

    @RunWith(SpringJUnit4ClassRunner.class)

    @ContextConfiguration("classpath:applicationContext.xml")

    public class TestIOC {

      

       @Autowired

       private UserService userService;

      

       @Test

       public void test1(){

          userService.saveUser();

       }

      

    }

    1. @RunWith注解:这个是指定使用的单元测试执行类,这里就指定的是SpringJUnit4ClassRunner.class;
    2. @ContextConfiguration注解:这个指定spring配置文件所在的路径,可以同时指定多个文件; 纯注解的形式整合JUnit

    spring4_day02_springAndDBUtilsFullAnnotation这个工程是一个全注解的工程,没有applicaitonContext.xml文件,那么@ContextConfiguration注解就没办法指定applicationContext.xml了,只能指定SpringConfig这个配置类了。@ContextConfiguration中的classes属性指定配置类。修改TestFind单元测试类如下:

    @RunWith(SpringJUnit4ClassRunner.class)

    @ContextConfiguration(classes=SpringConfig.class)//指定加载配置类创建ioc容器

    public class TestFind {

     

       @Autowired

       private CustomerService customerService;

      

       @Test

       public void test1(){

          List<Customer> list = customerService.findAllCustomer();

          for (Customer customer : list) {

             System.out.println(customer);

          }

       }

    }

     

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签:  Spring Config Spring