@Autowire 的 required 属性
将UserDao和UserDaoExt类上的@Repository注解注释,也就是说UserDao和UserDaoExt不会被注册到容器中,再次执行测试
当要装配的类型不存在时会报错,通过@Autowire(required=false),可以设置如果找不到Bean就装配为null,在UserService的@Autowire增加required=false,再次执行测试,此时不会在报Bean创建错误
@Autowire也可以放在方法上,此时@Autowire会把方法中的参数注入到容器中,而且这个方法也会在Bean创建的时候运行
@Qaulifier()也可以放在参数上,注入指定 ID的Bean
四、Spring单元测试
如何在单元测试中也可以使用@Autowire获取IoC容器中的元素?这就需要用到Spring Test
增加Spring Test的依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring-version}</version> </dependency> 复制代码
新建一个SpringTest测试类
@ContextConfiguration(locations = "classpath:annotation.xml") @RunWith(SpringJUnit4ClassRunner.class) public class SpringTest { @Autowired private UserService userService; @Test public void testSave(){ System.out.println(userService); userService.save(new User()); } } 复制代码
执行测试类
注解释义
- @ContextConfiguration, 用来指定Spring的配置文件的位置
- @RunWith(SpringJUnit4ClassRunner.class), 指定单元测试的驱动
五、泛型依赖注入
entity增加Product,Category dao层增加一个BaseDao,并定义好通用的save()方法,新增ProductDao和CategoryDao
public abstract class BaseDao<T> { public abstract void save(); } 复制代码
@Repository public class ProductDao extends BaseDao<Product> { @Override public void save() { System.out.println(this.getClass().getName() + "的save()方法被调用"); } } 复制代码
@Repository public class CategoryDao extends BaseDao<Category> { @Override public void save() { System.out.println(this.getClass().getName() + "的save()方法被调用"); } } 复制代码
service层增加ProductService,CategoryService
@Service public class ProductService { @Autowired private ProductDao productDao; public void save(){ productDao.save(); } } 复制代码
@Service public class CategoryService { @Autowired private CategoryDao categoryDao; public void save(){ categoryDao.save(); } } 复制代码
创建一个xml配置文件generic.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:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.citi"> </context:component-scan> </beans> 复制代码
新建测试类
@ContextConfiguration(locations = "classpath:generic.xml") @RunWith(SpringJUnit4ClassRunner.class) public class GenericTest { @Autowired private ProductService productService; @Autowired private CategoryService categoryService; @Test public void testSave(){ productService.save(); categoryService.save(); } } 复制代码
执行测试类
由于调用的ProducDao和CategoryDao其实都是调用的BaseDao,新建一个BaseService方法,调用BaseDao
public class BaseService<T> { @Autowired private BaseDao<T> baseDao; public void save(){ System.out.println(baseDao); baseDao.save(); } } 复制代码
修改ProductService和CategoryService
@Service public class CategoryService extends BaseService<Category> { } 复制代码
@Service public class ProductService extends BaseService<Product>{ } 复制代码
再次执行测试,同样可以成功执行save方法,那么Spring是如何确定执行的类?
ProductService继承了BaseService<Product>, BaseService中调用了BaseDao,因此通过BaseDao<Product>就可以找到ProductDao,因为ProductDao继承了BaseDao<>
Spring可以使用带泛型的父类类型来确定这个子类的类型。