Spring学习笔记(三)——Spring注解开发&spring与Junit整合测试

2022-09-24 09:51:02 浏览数 (1)

原文可以参考csdn

Spring注解开发

注解的分类

  • 曾经XML的配置: <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl" scope="" init-method="" destroy-method=""> <property name="" value="" | ref=""></property> </bean>
  • 用于创建对象的 他们的作用就和在XML配置文件中编写一个标签实现的功能是一样的 Component: 作用:用于把当前类对象存入spring容器中 属性: value:用于指定bean的id。当我们不写时,它的默认值是当前类名,且首字母改小写。 Controller:一般用在表现层 Service:一般用在业务层 Repository:一般用在持久层 以上三个注解他们的作用和属性与Component是一模一样。 他们三个是spring框架为我们提供明确的三层使用的注解,使我们的三层对象更加清晰
  • 用于注入数据的 他们的作用就和在xml配置文件中的bean标签中写一个标签的作用是一样的 Autowired:
代码语言:javascript复制
 作用:自动按照类型注入。只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功
     如果ioc容器中没有任何bean的类型和要注入的变量类型匹配,则报错。
     如果Ioc容器中有多个类型匹配时:
 出现位置:
     可以是变量上,也可以是方法上
  细节:
     在使用注解注入时,set方法就不是必须的了。
 ```
代码语言:javascript复制
如在service实现类中注入
@Autowired
private IAccountDao accountDao = null;
在dao实现类中 
public class AccountDaoImpl implements IAccountDao{}
即是变量名相同,可以注入变量
代码语言:javascript复制
 Qualifier:
代码语言:javascript复制
    作用:在按照类中注入的基础之上再按照名称注入。它在给类成员注入时不能单独使用。但是在给方法参数注入时可以
     属性:
         value:用于指定注入bean的id。
代码语言:javascript复制
Resource

    作用:直接按照bean的id注入。它可以独立使用
             属性:
             name:用于指定bean的id。 


 以上三个注入都只能注入其他bean类型的数据,而基本类型和String类型无法使用上述注解实现。
     另外,集合类型的注入只能通过XML来实现。
     Value
         作用:用于注入基本类型和String类型的数据
         属性:
             value:用于指定数据的值。它可以使用spring中SpEL(也就是spring的el表达式)
                     SpEL的写法:${表达式}
* 用于改变作用范围的
     他们的作用就和在bean标签中使用scope属性实现的功能是一样的
     Scope
         作用:用于指定bean的作用范围
         属性:
             value:指定范围的取值。常用取值:singleton prototype
* 和生命周期相关 了解
     他们的作用就和在bean标签中使用init-method和destroy-methode的作用是一样的
     PreDestroy
         作用:用于指定销毁方法
     PostConstruct
         作用:用于指定初始化方法

## Spring的新注解
* Configuration
  作用:指定当前类是一个配置类
   细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。
* ComponentScan
     作用:用于通过注解指定spring在创建容器时要扫描的包
     属性:
     value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。
         我们使用此注解就等同于在xml中配置了:
         <context:component-scan base-package="com.itheima"></context:component-scan>
* Bean
     作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中
     属性:
         name:用于指定bean的id。当不写时,默认值是当前方法的名称
     细节:
         当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象。
         查找的方式和Autowired注解的作用是一样的
* Import
     作用:用于导入其他的配置类
     属性:
         value:用于指定其他配置类的字节码。
                 当我们使用Import的注解之后,有Import注解的类就父配置类,而导入的都是子配置类
* PropertySource
     作用:用于指定properties文件的位置
     属性:
         value:指定文件的名称和路径。
                 关键字:classpath,表示类路径下

## 完全基于注解的配置(配置类)
1. SpringConfiguration.java
 ```
//@Configuration 用于通过注解指定spring在创建容器时要扫描的包
@ComponentScan("com.itheima")
@Import(    JdbcConfig.class)
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfiguration {
}
  1. JdbcConfig.java(jdbc配置)
代码语言:javascript复制
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.Scope;

import javax.sql.DataSource;

/**
 * 和spring连接数据库相关的配置类
 */
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(@Qualifier("ds2") DataSource dataSource){
        return new QueryRunner(dataSource);
    }

    /**
     * 创建数据源对象
     * @return
     */
    @Bean(name="ds2")
    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);
        }
    }

    @Bean(name="ds1")
    public DataSource createDataSource1(){
        try {
            ComboPooledDataSource ds = new ComboPooledDataSource();
            ds.setDriverClass(driver);
            ds.setJdbcUrl("jdbc:mysql://localhost:3306/eesy");
            ds.setUser(username);
            ds.setPassword(password);
            return ds;
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
}
  1. jdbcConfig.properties
代码语言:javascript复制
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/eesy
jdbc.username=root
jdbc.password=root

使用Junit单元测试:测试我们的配置

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(坐标)

代码语言:javascript复制
 <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>

2、使用Junit提供的一个注解把原有的main方法替换了,替换成spring提供的 @Runwith

代码语言:javascript复制
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class AccountServiceTest {

    @Autowired
    private IAccountService as = null;//类型注入

3、告知spring的运行器,spring和ioc创建是基于xml还是注解的,并且说明位置

代码语言:javascript复制
@ContextConfiguration
    locations:指定xml文件的位置,加上classpath关键字,表示在类路径下
    lasses:指定注解类所在地位置

当我们使用spring 5.x版本的时候,要求junit的jar必须是4.12及以上

注解开发和spring与Junit整合的CURD案例

  1. pom.xml
代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.qkongtao</groupId>
    <artifactId>Spring_anno_crud</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>commons-dbutils</groupId>
            <artifactId>commons-dbutils</artifactId>
            <version>1.4</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>

        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>


</project>
  1. bean.xml
代码语言:javascript复制
<?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">

    <!-- 告知spring在创建容器时要扫描的包 -->
    <context:component-scan base-package="dao"></context:component-scan>
    <context:component-scan base-package="service"></context:component-scan>
    <!--配置QueryRunner-->
    <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
        <!--注入数据源-->
        <constructor-arg name="ds" ref="dataSource"></constructor-arg>
    </bean>

    <!--导入配置文件-->
    <context:property-placeholder location="classpath:jdbcConfig.properties"/>

    <!-- 配置数据源 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--连接数据库的必备信息-->
        <property name="driverClass" value="${jdbc.driver}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="user" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
</beans>
  1. jdbc配置文件: jdbcConfig.properties
代码语言:javascript复制
<code class="language-clike line-numbers">jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/eesy
jdbc.username=root
jdbc.password=root
  1. javaBean封装类:User.java
代码语言:javascript复制
package domain;/*
 *Created by tao on 2020-03-30.
 */

import java.util.Date;

public class User {
    private int id;
    private  String name;
    private  String sex;
    private  int age;
    private String birthday;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getBirthday() {
        return birthday;
    }

    public void setBirthday(String birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "User{"  
                "id="   id  
                ", name='"   name   '''  
                ", sex='"   sex   '''  
                ", age="   age  
                ", birthday="   birthday  
                '}';
    }
}
  1. UserDao接口
代码语言:javascript复制
package dao;/*
 *Created by tao on 2020-03-30.
 */

import domain.User;

import java.util.List;

public interface UserDao {
    List<User> findAll();
    User findById(int id);
    void saveUser(User user);
    void updateUser(User user);
    void deleteUser(int id);
}
  1. UserDaoImpl.java(UserDao接口实现类)
代码语言:javascript复制
package dao.impl;/*
 *Created by tao on 2020-03-30.
 */

import dao.UserDao;
import domain.User;
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;

@Repository("userDao")
public class UserDaoImpl implements UserDao {
    @Autowired
    private QueryRunner runner;

    public List<User> findAll() {
        try {
            return runner.query("select * from user", new BeanListHandler<User>(User.class));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public User findById(int id) {
        try {
            return runner.query("select * from user where id =?", new BeanHandler<User>(User.class), id);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void saveUser(User user) {
        try {
            runner.update("insert into user(name,sex,age,birthday)values(?,?,?,?)", user.getName(), user.getSex(), user.getAge(), user.getBirthday());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void updateUser(User user) {
        try {
            runner.update("update user set name=?,sex=?,age=?,birthday=? where id=?", user.getName(), user.getSex(), user.getAge(), user.getBirthday(), user.getId());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void deleteUser(int id) {
        try {
            runner.update("delete from user where id =?", id);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
  1. UserService(接口)
代码语言:javascript复制
package service;/*
 *Created by tao on 2020-03-30.
 */

import domain.User;

import java.util.List;

public interface UserService {
    List<User> findAll();
    User findById(int id);
    void saveUser(User user);
    void updateUser(User user);
    void deleteUser(int id);
}
  1. UserServiceImpl.java(UserService接口实现类)
代码语言:javascript复制
package service.impl;/*
 *Created by tao on 2020-03-30.
 */

import dao.UserDao;
import domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import service.UserService;

import java.util.List;

@Service("userService")
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userdao;


    public List<User> findAll() {
        return userdao.findAll();
    }

    public User findById(int id) {
        return userdao.findById(id);
    }

    public void saveUser(User user) {
        userdao.saveUser(user);
    }

    public void updateUser(User user) {
        userdao.updateUser(user);
    }

    public void deleteUser(int id) {
        userdao.deleteUser(id);
    }
}
  1. 测试类UserServiceTest.java(使用Junit单元测试:测试我们的配置)
代码语言:javascript复制
package test;/*
 *Created by tao on 2020-03-30.
 */

import domain.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import service.UserService;
import service.impl.UserServiceImpl;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/*
 * 使用Junit单元测试:测试我们的配置
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:bean.xml")
public class UserServiceTest {
    @Autowired
    private UserService userService;

    @Test
    public void testFindAll() {
        //执行方法
        List<User> users = userService.findAll();
        for (User user : users) {
            System.out.println(user);
        }
    }

    @Test
    public void testFindById() {
        //执行方法
        User users = userService.findById(2);
        System.out.println(users);
    }

    @Test
    public void testSaveUser() {
        //执行方法
        User user = new User();
        user.setName("香克斯");
        user.setSex("男");
        user.setAge(41);
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
        user.setBirthday(df.format(new Date()));
        userService.saveUser(user);
    }

    @Test
    public void testUpdateUser() {
        //执行方法
        User user = new User();
        user.setId(13);
        user.setName("尼克罗宾");
        user.setSex("女");
        user.setAge(41);
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
        user.setBirthday(df.format(new Date()));
        userService.updateUser(user);
    }

    @Test
    public void testDeleteUser() {
        //执行方法
        userService.deleteUser(13);
    }
}

附一个测试结果

0 人点赞