当然,上面说到spring它会先按name尝试注入,name不存在则按类型注入。那我们试试name不存在时,看看如何运行:
比如我们对Config类的一些代码进行更改,我们把要注入对象的参数的名字从userDao改为udao:
@Bean //会按name尝试注入,name不存在则按类型注入 public UserService userService(UserDao udao){ UserService userService=new UserService(); System.out.println("已创建userServices"); userService.setUserDao(userDao); System.out.println("调用setUserDao"+userDao); return userService; }
然后运行,其实也是不会报错的。因为spring他会在去找容器内相同类型的bean进行注入。
但是,如果在传入要注入的bean的name不正确的情况下,容器中又存在两个注入类型相同的bean,就会报错了,比如我们下面创建两个UserDao的bean。
@Bean public UserDao userDao(){ UserDao userDao=new UserDao(); System.out.println("已创建userDao"); return userDao; } @Bean public UserDao userDao1(){ UserDao userDao=new UserDao(); System.out.println("已创建userDao"); return userDao; } @Bean //会按name尝试注入,name不存在则按类型注入 public UserService userService(UserDao udao){ UserService userService=new UserService(); System.out.println("已创建userServices"); userService.setUserDao(udao); System.out.println("调用setUserDao"+udao); return userService; }
这时候运行main方法就会报错了。
在这里插入图片描述
它显示发现两个相同类型的Bean,它不知道该注入哪一个bean。
解决这个问题的办法有很多,比如给给其中一个bean添加一个@Primary的注解。使其优先选择被注入。
@Bean public UserDao userDao(){ UserDao userDao=new UserDao(); System.out.println("已创建userDao"); return userDao; } @Bean @Primary public UserDao userDao1(){ UserDao userDao=new UserDao(); System.out.println("已创建userDao"); return userDao; } @Bean //会按name尝试注入,name不存在则按类型注入 public UserService userService(UserDao udao){ UserService userService=new UserService(); System.out.println("已创建userServices"); userService.setUserDao(udao); System.out.println("调用setUserDao"+udao); return userService; }
运行结果如下,这时就不会报错了:
下面介绍用@Scope注解配置bean的作用范围为singleton或prototype
@Bean @Scope("prototype") public UserController userController(UserService userService){ UserController userController=new UserController(); System.out.println("已创建userController"); userController.setUserService(userService); System.out.println("调用setUserService"+userService); return userController; }
其实Java Config可以和注解配置一起使用,只需要配置@ComponentScan注解,代表扫描包内组件的注解,里面用basePackages来指定要扫描注解的包。
@Configuration @ComponentScan(basePackages = "com.haiexijun") public class Config { //Java Config利用方法创建对象,将方法返回对象放入容器中,beanId为方法名 @Bean public UserDao userDao(){ ``````````````` }
10.Spring与JUnit4整合—Spring Test测试模块
Spring Test 是Spring中用于测试的模块,Spring Test对JUnit单元测试框架有良好的整合。在日常开发中,最常用的一个功能就是与JUnit单元测试进行整合,通过Spring Test这个模块可以在JUnit单元单元测试时自动初始化IoC容器。
Spring与JUnit4的整合过程
1.配置Maven工程依赖spring-test和junit4的依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.3.13</version> </dependency>
2.利用@RunWith与@ContextConfiguration描述测试用例类。通过@RunWith可以让spring接管JUnit4的控制权,完成IoC的初始化工作,@ContextConfiguration则用于说明在初始化IoC容器过程中到底要加载哪个配置文件。
3.测试用例类从容器获取对象完成测试用例的执行。
下面来演示一下:
创建好userDao类和UserService类后,配置xml文件
package com.haiexijun.ioc.dao; public class UserDao { public void insert(){ System.out.println("插入一条数据"); } }
package com.haiexijun.ioc.service; import com.haiexijun.ioc.dao.UserDao; public class UserService { private UserDao userDao; public void createUser(){ System.out.println("调用创建用户的业务代码"); userDao.insert(); } public UserDao getUserDao() { return userDao; } public void setUserDao(UserDao userDao) { this.userDao = userDao; } }
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userDao" class="com.haiexijun.ioc.dao.UserDao"> </bean> <bean id="userService" class="com.haiexijun.ioc.service.UserService"> <property name="userDao" ref="userDao"/> </bean> </beans>
之后再test包下面创建一个测试用例类SpringTestor:
import com.haiexijun.ioc.service.UserService; import org.junit.Test; import org.junit.runner.RunWith; import javax.annotation.*; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; //将Junit4的执行权交给Spring Test,再测试用例执行前自动初始化IoC容器 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:applicationContext.xml"}) public class SpringTestor { @Resource private UserService userService; @Test public void testUserService(){ userService.createUser(); } }