Spring第二天
回顾:
- IOC:控制反转,把对象的创建权利反转给spring框架。
- IOC的作用:解耦
- Spring中的工厂:
- ApplicationContext
- ClassPathXmlApplicationContext
- FileSystemXmlApplicationContext
- BeanFactory
- ApplicationContext
- spring的配置文件
- bean标签
- id
- class
- scope:singleton/prototype
- init-method
- destroy-method
- import标签
- bean标签
- Spring中生成bean的三种方式
- 无参构造
- 静态工厂方式实例化
- 实例工厂方式实例化
- DI:依赖注入
- 构造方法注入
- Set方法注入:先找无参构造实例对象,再调用属性的set方法注入值
- P命名空间的写法
- SpEl的写法
- 特殊类型的注入
- List/Array
- Set
- Map
- Properties
- Spring IOC注解的快速入门
- 创建Java工程并导入jar包
- 需要导入IOC容器需要的6个jar包+spring-aop.jar:
-
- 创建包结构并编写Java类
- 创建UserService接口
package cn.itcast.service;
public interface UserService {
/**
* 业务层:用户保存
*/
public void saveUser();
}
- 创建UserService的实现类UserServiceImpl
package cn.itcast.service.impl;
import cn.itcast.service.UserService;
public class UserServiceImpl implements UserService {
public void saveUser() {
System.out.println("业务层:用户保存...");
}
}
-
- 在Java类上添加注解
- 在UserServiceImpl实现类上添加注解@Component,相当于<bean id=”” class=””>,value属性给bean指定id,value属性的名字也可以不写
@Component("userService")
public class UserServiceImpl implements UserService{
public void saveUser() {
System.out.println("业务层:用户保存...");
}
}
-
- 在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>
-
- 在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>
-
- 编写测试代码
- 创建单元测试类TestIOC,在其中创建单元测试方法test1
/**
* 测试注解
*/
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
userService.saveUser();
}
- Spring框架中bean管理的常用注解
Spring中用于管理bean的注解分为四大类:
- 用于创建对象
- 用于给对象中的属性注入值
- 用于改变作用范围
- 用于定义生命周期
- 用于创建对象的(重点)
用于创建对象的有四个:@Component,@Controller,@Service,@Repository
-
-
- @Component注解
-
作用:
把资源让spring来管理。相当于在xml中配置一个bean。
属性:
value:指定bean的id。如果不指定value属性,默认bean的id是当前类的类名。首字母小写。
-
-
- @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 {
}
说明:这三个注解是为了让标注类本身的用途清晰
-
- 用于注入数据的
用于注入数据的注解有:
- @Value
- @Autowired
- @Qualifier
- @Resource
相当于:<property name="" ref="">
<property name="" value="">
-
-
- @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方法,测试结果如下:
-
-
- @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方法,测试结果如下:
-
-
- @Qualifer
-
作用:
在自动按照类型注入的基础之上,再按照Bean的id注入。它在给字段注入时不能独立使用,必须和@Autowire一起使用;但是给方法参数注入时,可以独立使用。
属性:
value:指定bean的id。
- 创建UserDao接口的第二个实现类UserDaoImpl2
@Repository("userDao2")
public class UserDaoImpl2 implements UserDao {
@Override
public void save() {
System.out.println("持久层:用户保存2222...");
}
}
运行TestIOC中的test1方法,测试结果如下:
- 测试发现,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;测试结果如下:
-
-
- @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();
}
}
-
- 用于改变作用域范围的
- @Scope(重点)
- 用于改变作用域范围的
作用:
指定bean的作用范围。
属性:
value:指定范围的值。
取值:singleton prototype request session globalsession
- @Scope指定bean的作用域,默认值是singleton,单例的。
- 修改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();
}
}
- 在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);
}
- 测试发现:当scope指定为prototype时,两次获取UserService的对象是不一致的。测试结果如下:
-
- 和生命周期相关的
相当于:<bean id="" class="" init-method="" destroy-method="" />
-
-
- @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方法,测试结果如下:
-
-
- @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();
}
测试结果如下:
- XML和注解的比较
注解的优势:
配置简单,维护方便。(我们找到了类,就相当于找到了配置)
XML的优势:
修改时,不用改源码。不涉及重新编译和部署。
Xml和注解的比较
- 案例:Spring整合DBUtils实现增删改查
- 2第一步:创建工程,导入jar包
需要导入的jar包有:spring ioc必要的六个jar包+c3p0+mysql驱动包。完成的jar包如下图所示:
-
- 第二步:创建业务层接口及实现类
创建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;
}
}
-
- 第三步:创建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;
}
}
-
- 第四步:编写spring配置文件
在src下创建spring的配置文件applicationContext.xml,把Service、Dao、QueryRunner、DataSource配置到Spring中
- Service中需要注入DAO
- DAO中需要注入QueryRunner
- QueryRunner中需要注入DataSource
- 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文件
-
- 第五步:编写测试类
创建单元测试类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);
}
}
在这里测试的时候,实体类的属性名字要和数据库的属性名字一一对应,不然数据不能回显;
测试结果如下:
- 案例:采用注解把Spring和DBUtils进行整合
可以把第四章的工程里直接改成注解的形式
-
- 第一步:导入spring-aop.jar
注意:注解开发需要额外导入spring-aop.jar包
-
- 第二步:在类上加对应的注解
修改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;
}
}
-
- 第三步:修改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的配置是一样的。
- 案例:采用Spring全注解整合DBUtils
全注解整合的思路:要想实现全注解,得把applicationContext.xml的所有内容用一个类来配置。@Configuration注解可以表示一个类是配置类;@ComponentScan注解可以实现包扫描;还得想办法把QueryRunner和DataSource这两个bean用注解来配置。这个两个bean都是来自于jar包中的,用传统的注解配置方法是不可能实现的。得用@Bean注解,这个注解可以把某个方法的返回值存放到spring容器中。我们可以写两个方法,这两个方法分别返回QueryRunner对象和DataSource对象,然后在这两个方法上加@Bean注解,就可以保证spring容器中QueryRunner和DataSource这两个对象了。
-
- 第一步:创建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;
}
}
-
- 第二步:修改测试代码
因为已经用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方法,发现结果和之前是一致的。
-
- 第三步:把数据库连接相关的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 {
}
-
- 第四步:把数据库连接信息写到配置文件中
此时,我们发现,数据库的驱动类名、连接地址、用户名、密码都是直接写死在类中的,不便于修改,可以把与数据库相关的信息写到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
-
- 第五步:在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;
}
}
-
- 第六步:在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方法进行测试。
- Spring框架整合JUnit单元测试
- 目的
为了简化了JUnit的测试,使用Spring框架也可以整合测试。
-
- 具体步骤
要求:必须先有JUnit的环境(默认会使用Eclipse导入单元测试的环境)!!
-
-
- 步骤一:在程序中引入spring-test.jar
-
可以直接在spring4_day02中引入spring-test.jar包,把spring4_day02中的单元测试类全部改成spring的写法
注意:spring单元测试还得要有spring-aop.jar包,因为spring单元测试会用到注解
-
-
- 步骤二:在具体测试类上添加注解
-
修改单元测试类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();
}
}
- @RunWith注解:这个是指定使用的单元测试执行类,这里就指定的是SpringJUnit4ClassRunner.class;
- @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);
}
}
}