欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 社会 > Spring框架---IOC注解方式,Spring整合Junit单元测试

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

2025/1/3 3:09:02 来源:https://blog.csdn.net/jlihan/article/details/143431450  浏览:    关键词: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包

<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>

创建数据库,创建表结构

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的类

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


​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;}
​@Overridepublic String toString() {return "Account{" +"id=" + id +", name='" + name + '\'' +", money=" + money +'}';}
}

 编写AccountDao的接口和实现类

AccountDao接口

public interface AccountDao {public List<Account> findAll();}

AccountDaoImpl实现类

public class AccountDaoImpl implements AccountDao {  // 注入连接池对象private DataSource dataSource;public void setDataSource(DataSource dataSource) {this.dataSource = dataSource;}
​/*** 查询所有的数据* @return*/@Overridepublic 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接口

public interface AccountService {
​public List<Account> findAll();
​}

AccountServiceImpl实现类

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

编写测试文件applicationConfig.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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://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>

编写测试类

public class Demo1 {
​@Testpublic 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管理的类及其属性和属性值 

编写接口和实现类

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

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

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

package com.qcby.demo2;/*
* 用户模块实现类实现用户模块接口
* 实现其抽象方法
* 耦合度低
* */import com.qcby.demo2.UserService;// 组件,作用:把当前类使用IOC容器进行管理,如果没有指定名称,默认使用类名,首字母是小写。userServiceImpl。或者自己指定名称
@Component(value = "us")
public class UserServiceImpl implements UserService{//实现入门@Overridepublic void hello() {System.out.println("Hello IOC!!");}

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

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

<?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.xsdhttp://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>

编写测试方法

​
public class Demo2 {
​/*** IOC注解方式的入门*/@Testpublic 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类

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方法进行初始化操作*/@PostConstructpublic 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;}*/@Overridepublic String toString() {return "Car{" +"cname='" + cname + '\'' +", money=" + money +", person=" + person +'}';}
}

创建Person类 

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;@Overridepublic String toString() {return "Person{" +"pname='" + pname + '\'' +'}';}}

在配置文件中开启扫描

<?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/beanshttp://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>

 创建测试类

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 {@Testpublic void run1(){ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");Car car = (Car) ac.getBean("c");System.out.println(car);}
}

测试结果:

IOC纯注解的方式

 IOC纯注解方式

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

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

编写实体类

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

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

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 {
​
}

测试方法的编写

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 {
​/*** 编写程序,需要加载配置类*/@Testpublic void run1(){// 创建工厂,加载配置类ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);// 获取到对象Order order = (Order) ac.getBean("order");System.out.println(order);}
​
}

常用的注解总结

        @Configuration 声明是配置类

        @ComponentScan 扫描具体包结构的

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

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

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;}
}
// 声明当前类是配置类
@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的坐标依赖

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

编写类和方法

package com.qcby.demo6;import org.springframework.stereotype.Component;@Component
public class Customer {public void save(){System.out.println("保存客户");}
}

编写配置类

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)为固定写法

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 {// 测试哪一个对象,把该对象注入进来,在测试环境下,可以使用注解的方式注入测试的对象// 按类型自动注入@Autowiredprivate Customer customer;@Testpublic void run1(){// 创建工厂,加载配置文件......// 调用对象的方法customer.save();}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com