引用类型自动装配DI
1 引用类型自动装配DI
1.1 设定场景
-
SoldierController 需要 SoldierService
-
SoldierService 需要 SoldierDao
同时在各个组件中声明要调用的方法 -
SoldierController中声明方法
@Controller(value = "tianDog")
public class SoldierController {
private SoldierService soldierService;
public void getMessage() {
soldierService.getMessage();
}
}
- SoldierService中声明方法
@Service("smallDog")
public class SoldierService {
private SoldierDao soldierDao;
public void getMessage() {
soldierDao.getMessage();
}
}
- SoldierDao中声明方法
@Repository
public class SoldierDao {
public void getMessage() {
System.out.print("I am a soldier");
}
}
1.2 自动装配实现
-
前提
参与自动装配的组件(需要装配、被装配)全部都必须在IoC容器中。
注意:不区分IoC的方式!XML和注解都可以!
-
@Autowired注解
在成员变量上直接标记@Autowired注解即可,不需要提供setXxx()方法,在项目中的正式用法就是这样。
- 给Controller装配Service
@Controller(value = "tianDog")
public class SoldierController {
@Autowired
private SoldierService soldierService;
public void getMessage() {
soldierService.getMessage();
}
}
- 给Service装配Dao
@Service("smallDog")
public class SoldierService {
@Autowired
private SoldierDao soldierDao;
public void getMessage() {
soldierDao.getMessage();
}
}
- 配置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 https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.lx.ioc_06"/>
</beans>
1.3 @Autowired注解细节
-
标记位置
-
成员变量
这是最主要的使用方式!
与xml进行bean ref引用不同,他不需要有set方法!
-
@Service("smallDog")
public class SoldierService {
@Autowired
private SoldierDao soldierDao;
public void getMessage() {
soldierDao.getMessage();
}
}
2. 构造器
@Controller(value = "tianDog")
public class SoldierController {
private SoldierService soldierService;
@Autowired
public SoldierController(SoldierService soldierService) {
this.soldierService = soldierService;
}
……
3. setXxx()方法
@Controller(value = "tianDog")
public class SoldierController {
private SoldierService soldierService;
@Autowired
public void setSoldierService(SoldierService soldierService) {
this.soldierService = soldierService;
}
……
-
工作流程
- 首先根据所需要的组件类型到 IOC 容器中查找
- 能够找到唯一的 bean:直接执行装配
- 如果完全找不到匹配这个类型的 bean:装配失败
- 和所需类型匹配的 bean 不止一个
- 没有 @Qualifier 注解:根据 @Autowired 标记位置成员变量的变量名作为 bean 的 id 进行匹配
- 能够找到:执行装配
- 找不到:装配失败
- 使用 @Qualifier 注解:根据 @Qualifier 注解中指定的名称作为 bean 的id进行匹配
- 能够找到:执行装配
- 找不到:装配失败
- 没有 @Qualifier 注解:根据 @Autowired 标记位置成员变量的变量名作为 bean 的 id 进行匹配
@Controller(value = "tianDog") public class SoldierController { @Autowired @Qualifier(value = "maomiService222") // 根据面向接口编程思想,使用接口类型引入Service组件 private ISoldierService soldierService;
- 首先根据所需要的组件类型到 IOC 容器中查找
1.4 佛系装配(不重要)
给 @Autowired 注解设置 required = false 属性表示:能装就装,装不上就不装。但是实际开发时,基本上所有需要装配组件的地方都是必须装配的,用不上这个属性
@Controller(value = "tianDog")
public class SoldierController {
// 给@Autowired注解设置required = false属性表示:能装就装,装不上就不装
@Autowired(required = false)
private ISoldierService soldierService;
1.5 @Resource
@Resource
: 标识一个需要注入的资源,是实现Java EE组件之间依赖关系的一种方式。- @Resource注解也可以完成属性注入。那它和@Autowired注解有什么区别?
- @Resource注解是JDK扩展包中的,也就是说属于JDK的一部分。所以该注解是标准注解,更加具有通用性。
- @Autowired注解是Spring框架自己的。
- @Resource注解默认根据Bean名称装配,未指定name时,使用属性名作为name。通过name找不到的话会自动启动通过类型装配。
- @Autowired注解默认根据类型装配,如果想根据名称装配,需要配合@Qualifier注解一起用。
- @Resource注解用在属性上、setter方法上。
- @Autowired注解用在属性上、setter方法上、构造方法上、构造方法参数上。
@Resource注解属于JDK扩展包,所以不在JDK当中,需要额外引入以下依赖:【高于JDK11或低于JDK8需要引入以下依赖】
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>2.1.1</version>
</dependency>
- @Resource使用
@Controller
public class XxxController {
/**
* 1. 如果没有指定name,先根据属性名查找IoC中组件xxxService
* 2. 如果没有指定name,并且属性名没有对应的组件,会根据属性类型查找
* 3. 可以指定name名称查找! @Resource(name='test') == @Autowired + @Qualifier(value='test')
*/
@Resource
private XxxService xxxService;
//@Resource(name = "指定beanName")
//private XxxService xxxService;
public void show(){
System.out.println("XxxController.show");
xxxService.show();
}
}
2 基本类型属性赋值 (DI)
@Value
通常用于注入外部化属性
@Value注解读取配置
@Component
public class CommonComponent {
/**
* 情况1: ${key} 取外部配置key对应的值!
* 情况2: ${key:defaultValue} 没有key,可以给与默认值
*/
@Value("${catalog:hahaha}")
private String name;
//private String name = "哈哈"//也可不适用@Value直接赋值
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}