Spring框架---IOC注解方式,Spring整合Junit单元测试

目录

Spring框架开发程序的方式

IOC注解的方式

IOC注解方式的快速入门(半注解)

IOC常用的注解

IOC纯注解的方式

Spring框架整合JUnit单元测试


博主所使用的软件版本为

idea 2017

jdk版本 1.8.0

maven版本 3.5.4

Spring框架开发程序的方式

编写service和dao的类,持久层选择使用原始的JDBC的程序,连接池选择的是Druid连接池,演示代码,来理解Spring框架开发程序的方式。

创建maven工程,导入开发的jar包

java 复制代码
<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!--连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!--mysql驱动包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
    
    </dependencies>

创建数据库,创建表结构

java 复制代码
create database spring_db;
use spring_db;
create table account(
    id int primary key auto_increment,
    name varchar(40),
    money double
)character set utf8 collate utf8_general_ci;
​
insert into account(name,money) values('aaa',3000);
insert into account(name,money) values('bbb',3000);
insert into account(name,money) values('ccc',1000);
insert into account(name,money) values('熊大',1000);
insert into account(name,money) values('熊二',500);
insert into account(name,money) values('大大怪将军',5000);
insert into account(name,money) values('小小怪下士',3000);
insert into account(name,money) values('小心',1000);
insert into account(name,money) values('花',1000);

编写JavaBean的类

类中的属性要和数据库表中的属性相对应

java 复制代码
​public class Account {
​
​
    private Integer id;
    private String name;
    private Double 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 Double getMoney() {
        return money;
    }
    public void setMoney(Double money) {
        this.money = money;
    }
​
    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", money=" + money +
                '}';
    }
}

编写AccountDao的接口和实现类

AccountDao接口

java 复制代码
public interface AccountDao {
    public List<Account> findAll();

}

AccountDaoImpl实现类

java 复制代码
public class AccountDaoImpl implements AccountDao {  
 // 注入连接池对象
   private DataSource dataSource;
   public void setDataSource(DataSource dataSource) {
       this.dataSource = dataSource;
   }
​
   /**
    * 查询所有的数据
    * @return
    */
   @Override
   public List<Account> findAll() {
​
       /*
       DruidDataSource dataSource = new DruidDataSource();
       dataSource.setDriverClassName("com.mysql.jdbc.Driver");
       dataSource.setUrl("jdbc:mysql:///spring_db");
       dataSource.setUsername("root");
       dataSource.setPassword("root");
       */
​
       List<Account> list = new ArrayList<>();
​
       Connection connection = null;
       PreparedStatement stmt = null;
       ResultSet rs = null;
​
       try {
           // 获取连接
           connection = dataSource.getConnection();
           // 编写sql语句
           String sql = "select * from account";
           // 预编译
           stmt = connection.prepareStatement(sql);
           // 查询
           rs = stmt.executeQuery();
           // 遍历,封装数据
           while (rs.next()){
               Account account = new Account();
               account.setId(rs.getInt("id"));
               account.setName(rs.getString("name"));
               account.setMoney(rs.getDouble("money"));
               list.add(account);
           }
       } catch (SQLException e) {
           e.printStackTrace();
       }finally {
           try {
               connection.close();
           } catch (SQLException e) {
               e.printStackTrace();
           }
           try {
               stmt.close();
           } catch (SQLException e) {
               e.printStackTrace();
           }
           try {
               rs.close();
           } catch (SQLException e) {
               e.printStackTrace();
           }
       }
       return list;
   } 
 }

创建业务层AccountService接口和其AccountServiceImpl 实现类

AccountService接口

java 复制代码
public interface AccountService {
​
       public List<Account> findAll();
​
   }

AccountServiceImpl 实现类

java 复制代码
public class AccountServiceImpl implements AccountService {
​
       // 依赖注入
       private AccountDao accountDao;
       public void setAccountDao(AccountDao accountDao) {
           this.accountDao = accountDao;
       }
​
       /**
        * 查询所有的数据
        * @return
        */
       @Override
       public List<Account> findAll() {
           return accountDao.findAll();
       }
​
   }

编写测试文件applicationConfig.xml

java 复制代码
<?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="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql:///spring_db" />
        <property name="username" value="root" />
        <property name="password" value="root" />
    </bean>
​
    <!--管理bean-->
    <bean id="accountService" class="cn.tx.service.AccountServiceImpl">
        <property name="accountDao" ref="accountDao" />
    </bean>
    <bean id="accountDao" class="cn.tx.dao.AccountDaoImpl">
        <property name="dataSource" ref="dataSource" />
    </bean>
​
</beans>

编写测试类

java 复制代码
public class Demo1 {
​
    @Test
    public void run1(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        AccountService accountService = (AccountService) ac.getBean("accountService");
        // 调用方法
        List<Account> list = accountService.findAll();
        for (Account account : list) {
            System.out.println(account);
        }
    }
​
}

测试结果:

IOC注解的方式

IOC注解方式的快速入门(半注解)

IOC注解的方式依赖没有变化

半注解的方式省去了在配置文件中配置<bean>并手写被Spring管理的类及其属性和属性值

编写接口和实现类

java 复制代码
package com.qcby.demo2;

/*
* 业务层接口
* 用户模块接口
* 目的:演示springIOC入门
*/
public interface UserService {
    //接口中的抽象方法
    public void hello();
}

在需要管理的类上添加@Component注解表示这个类交给Spring去管理

@Component(value = "us")相当于配置文件中<bean id="us" class="com.qcby.demo2.UserServiceImpl" />

java 复制代码
package com.qcby.demo2;

/*
* 用户模块实现类实现用户模块接口
* 实现其抽象方法
* 耦合度低
* */

import com.qcby.demo2.UserService;

// 组件,作用:把当前类使用IOC容器进行管理,如果没有指定名称,默认使用类名,首字母是小写。userServiceImpl。或者自己指定名称
@Component(value = "us")
public class UserServiceImpl implements UserService{
    //实现入门
    @Override
    public void hello() {
        System.out.println("Hello IOC!!");
    }

编写配置文件,重点是开启注解扫描。半注解一定要开启扫描。

扫描指定位置的包其下的类

java 复制代码
<?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="com.qcby.demo2" />
    -->
​
    <!--开启注解扫描 com.qcby.所有的包中的所有的类 -->
    <context:component-scan base-package="com.qcby" />
​
</beans>

编写测试方法

java 复制代码
​
public class Demo2 {
​
    /**
     * IOC注解方式的入门
     */
    @Test
    public void run1(){
        // 工厂
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext_anno.xml");
        // 获取对象
        UserService userService = (UserService) ac.getBean("us");
        userService.hello();
    }
​
}

IOC常用的注解

bean管理类常用的4个注解(作用相同,推荐使用在不同分层上)

@Component 普通的类

@Controller 表现层

@Service 业务层

@Repository 持久层

依赖注入常用的注解

@Value 用于注入普通类型(String,int,double等类型)

@Autowired 默认按类型进行自动装配(引用类型)

@Qualifier 和@Autowired一起使用,强制使用名称注入

@Resource Java提供的注解,也被支持。使用name属性,按名称注入对象生命周期(作用范围)注解

@Scope 生命周期注解,取值singleton(默认值,单实例)和prototype(多例)

初始化方法和销毁方法注解(了解)

@PostConstruct 相当于init-method

@PreDestroy 相当于destroy-method

注解的一些具体实现

创建Car类

java 复制代码
package com.qcby.demo3;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

// 默认当前类名就是ID名称,首字母小写
@Component(value = "c")
// @Controller
// @Service(value = "c")
// @Repository(value = "c")
// @Scope(value = "singleton")     // 默认值,单例的
// @Scope(value = "prototype")         // 多例的
public class Car {

    // 注解注入值,属性set方法是可以省略不写的。
    // 只有一个属性,属性的名称是value,value是可以省略不写的
    @Value("大奔2")
    private String cname;

    @Value(value = "400000")
    private Double money;

    // 也不用提供set方法
    // 按类型自动装配的注解,和id名称没有关系
    @Autowired
    // 按id的名称注入,Qualifier不能单独使用,需要Autowired一起使用。
    // @Qualifier(value = "person")
    // @Resource Java提供的注解,按名称注入对象,属性名称是name
    // @Resource(name = "person")
    private Person person;
    /**
     * Car对象创建完成后,调用init方法进行初始化操作
     */
    @PostConstruct
    public void init(){
        System.out.println("操作...");
    }
        /*
        public String getCname() {
            return cname;
        }
    ​
        public void setCname(String cname) {
            this.cname = cname;
        }
    ​
        public Double getMoney() {
            return money;
        }
    ​
        public void setMoney(Double money) {
            this.money = money;
        }
        */
    @Override
    public String toString() {
        return "Car{" +
                "cname='" + cname + '\'' +
                ", money=" + money +
                ", person=" + person +
                '}';
    }
}

创建Person类

java 复制代码
package com.qcby.demo3;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component(value = "person")
public class Person {
    @Value("张三")
    private String pname;

    @Override
    public String toString() {
        return "Person{" +
                "pname='" + pname + '\'' +
                '}';
    }

}

在配置文件中开启扫描

java 复制代码
<?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.tx.demo2" />
    -->

    <!--开启注解扫描 cn.tx.所有的包中的所有的类 -->
    <context:component-scan base-package="com.qcby"/>
</beans>

创建测试类

java 复制代码
package com.qcby.demo;

import com.qcby.demo3.Car;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Demo3 {
    @Test
    public void run1(){

        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Car car = (Car) ac.getBean("c");
        System.out.println(car);
    }
}

测试结果:

IOC纯注解的方式

IOC纯注解方式

省略了在配置文件,不需要开启扫描,使用配置类来代替配置文件

纯注解的目的是替换掉所有的配置文件。但是需要编写配置类。

编写实体类

java 复制代码
package com.qcby.demo4;
​
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Order {
​
    @Value("北京")
    private String address;
​
    @Override
    public String toString() {
        return "Order{" +
                "address='" + address + '\'' +
                '}';
    }
​
}

编写配置类,替换掉applicationContext.xml配置文件

java 复制代码
package com.qcby.demo4;
​
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
​
/**
 * Spring的配置类,替换掉applicationContext.xml
 *
 */
// 声明当前类是配置类
@Configuration
// 扫描指定的包结构
@ComponentScan(value = "com.qcby.demo4")
public class SpringConfig {
​
}

测试方法的编写

java 复制代码
package com.qcby.demo;

import com.qcby.demo4.OrderServiceImpl;
import com.qcby.demo4.SpringConfig1;
import com.qcby.demo401.Order01;
import com.qcby.demo4.Order;
import com.qcby.demo4.SpringConfig;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Demo4 {
​
    /**
     * 编写程序,需要加载配置类
     */
    @Test
    public void run1(){
        // 创建工厂,加载配置类
        ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
        // 获取到对象
        Order order = (Order) ac.getBean("order");
        System.out.println(order);
    }
​
}

常用的注解总结

@Configuration 声明是配置类

@ComponentScan 扫描具体包结构的

@Import注解 Spring的配置文件可以分成多个配置的,编写多个配置类。用于导入其他配置类

@Bean注解 只能写在方法上,表明使用此方法创建一个对象,对象创建完成保存到IOC容器中

java 复制代码
package com.qcby.demo4;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

import javax.sql.DataSource;

/**
 * 新的配置类
 */
@Configuration //声明配置类
public class SpringConfig1 {

    @Bean("dataSource")
    public DataSource createDataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///demotest");
        dataSource.setUsername("root");
        dataSource.setPassword("2020");
        return dataSource;
    }
}
java 复制代码
// 声明当前类是配置类
@Configuration
// 扫描指定的包结构
@ComponentScan(value = "com.qcby.demo4")
// @ComponentScan(value = {"com.qcby.demo4","com.qcby.demo3"})
// 引入新的配置类
@Import(value = {SpringConfig1.class})
public class SpringConfig {

Spring框架整合JUnit单元测试

每次进行单元测试的时候,都需要编写创建工厂,加载配置文件等代码,比较繁琐。Spring提供了整合Junit单元测试的技术,可以简化测试开发。

必须先有Junit单元测试的环境,也就是说已经导入Junit单元测试的jar包。咱们已经导入过了。使用的是4.12版本

再导入spring-test的坐标依赖

java 复制代码
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.0.2.RELEASE</version>
    <scope>test</scope>
</dependency>

编写类和方法

java 复制代码
package com.qcby.demo6;

import org.springframework.stereotype.Component;

@Component
public class Customer {
    public void save(){
        System.out.println("保存客户");
    }
}

编写配置类

java 复制代码
package com.qcby.demo6;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

//声明当前类是配置类
@Configuration
//扫描包结构
@ComponentScan(value = "com.qcby.demo6")
public class SpringConfig6 {
}

测试类

@RunWith(SpringJUnit4ClassRunner.class)为固定写法

java 复制代码
package com.qcby.demo;

import com.qcby.demo6.Customer;
import com.qcby.demo6.SpringConfig6;
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;

@RunWith(SpringJUnit4ClassRunner.class) // 运行单元测试
 加载类路径下的配置文件
@ContextConfiguration(classes = SpringConfig6.class)
public class Demo6 {

    // 测试哪一个对象,把该对象注入进来,在测试环境下,可以使用注解的方式注入测试的对象
    // 按类型自动注入
    @Autowired
    private Customer customer;

    @Test
    public void run1(){
        // 创建工厂,加载配置文件......
        // 调用对象的方法
        customer.save();
    }
}
相关推荐
小林学习编程6 小时前
从零开始理解Spring Security的认证与授权
java·后端·spring
feilieren6 小时前
SpringBoot 2.x 整合 Redis
java·开发语言·spring
阑梦清川6 小时前
SpringMVC案例学习(二)--表白墙/图书管理系统1.0版本
spring·mvc·springboot·案例
qq_433716957 小时前
Selenium+Pytest自动化测试框架 ------ 禅道实战
自动化测试·软件测试·selenium·单元测试·pytest·接口测试·压力测试
疯一样的码农11 小时前
Spring Security PasswordEncoder接口(密码编码)
java·spring·spring security
HaiFan.11 小时前
Spring MVC
java·spring·mvc
荆州克莱13 小时前
Redis | Redis常用命令及示例总结(API)
spring boot·spring·spring cloud·css3·技术
RainbowSea14 小时前
5. Spring Cloud OpenFeign 声明式 WebService 客户端的超详细使用
java·spring·spring cloud
听潮阁14 小时前
【SpringCloud详细教程】-02-微服务环境搭建
spring·spring cloud·微服务
Dreams°12314 小时前
【大数据测试ETL:从0-1实战详细教程】
大数据·数据仓库·python·单元测试·etl