啥叫DI
SpringDI,翻译过来叫做依赖注入,之前我们使用springIoc去把累交给spring管理,现在我们要把他取出来,就是通过DI(依赖注入的方式),也就是说
SpringDI是SpringIOC思想的具体实现
DI(依赖注入的三种方式)
- 属性注入
- 构造方法注入
- Setter方法注入
属性注入
首先,把另外一个类作为属性放到一个类中,作为属性的类必须提交给spring管理,否则使用DI注入的时候会报错
- 作为属性不交给spring管理
不交给spring管理,相当于你不往水壶里面倒水,怎么可能倒得出来水
- 不加@Autowired注解
不加注解,就会报空指针异常,就好像你往水壶里加水了,倒出来的时候没说去哪个水壶里面倒水
构造方法注入
首先在创建hello的时候,会先看到检查依赖,发现依赖service,就会先处理service这个依赖,然后去看ioc内有没有这个,没有就先尝试创建这个实例,如果这个类没有加注解就会报错,有的话就会注入,然后再创建controller同样的,这个也是需要service这个类交给spring去管理,否则就会报错
如果存在多个构造函数呢?
这里我们可以看出,默认实例化的时候是使用无参构造函数的,就会跳过检查依赖的步骤,直接就选中无参的并进行创建,由于service是空的,所以就会一直报空指针异常
如何解决,手动指定你要调用的
存在多个的时候,需要手动指定你要调用的加上@Autowired即可
Setter注入
Setter会由spring自动识别并注入,只要加了@Autowired的注解,就会自动注入,不加注解就无法执行
出现无法注入的问题,因为不知道注入给谁
三种注入的优缺点
属性注入
优点:简洁,使用方便
缺点:只能用于IOC容器,只有在使用的时候才会报空指针异常
不能注入一个final修饰的属性
不能注入final的原因:
执行构造函数的时候,final已经被赋值了,等对象创建好了之后,这个时候spring才刚刚通过反射拿到,时机已经错过了
构造函数注入
优点:1. 可以注入final修饰的(在执行构造函数的时候,也就final被赋值的时候,这个时候就可以注入)
2.注入的对象不会被修改(被final修饰的情况下)
如果是不被final修饰那就是可以被修改的
- 依赖的对象在使用前会被初始化,因为依赖在类的构造方法中
- 通用性强
缺点:注入对象多的时候,代码就会很繁琐
Setter注入
优点:在类实例化之后,可以重新对该对象进行注入或者配置
缺点:不能注入一个final修饰的属性
注入的对象可能会改变(setter被调用多次)
@Autowired存在的问题
有两个user的对象,提交给了spring进行管理,这个时候我们想要进行注入,就会报错,因为有两个对象,不知道注入哪个
如何解决这种问题spring提供了三种方式
@Primary
@Qualifier
@Resource
第一种@primary
加入注解@Primary,告诉编译器,实现的时候默认使用我加注解的
@Qualify
不能单独使用,需要配合注解@Autowired使用,指定使用注入是谁
使用@Qualifier,在ioc的多个同类的对象中,可以指定注入,不可单独使用,需要配合注解@Autowired使用
@Resource
JDK提供的注解
@Resource里面填写的是bean的名称,这个是由jdk内部提供的注解
@Autowired与@Resource区别
- @Autowired是spring架构提供的@Resource是JDK提供的
2. @Autowired默认是按照类型注入,@Resource默认是按照bean的名称注入