依赖注入
Spring框架的核心功能有两个:
Spring容器作为超级大工厂,负责创建、管理所有的Java对象,这些Java对象被称为Bean。
Spring容器管理容器中Bean之间的依赖关系,Spring使用一种被称为"依赖注入"的方式来管理Bean之间的依赖关系。
使用依赖注入,不仅可以为Bean注入普通的属性值,还可以注入其他Bean的引用。依赖注入是一种优秀的解耦方式,
其可以让Bean以配置文件组织在一起,而不是以硬编码的方式耦合在一起。
理解依赖注入
IoC(控制反转)和DI(依赖注入)的意思是相同的,只是表述方式不一样。
当某个Java对象(调用者)需要调用另一个Java对象(被依赖对象)的方法时,传统模式下通常有两种做法:
1.原始做法:调用者主动创建被依赖对象,然后再调用被依赖对象的方法。
就比如A类中要使用B类的方法,必须要先创建B类实例,再由B类实例调用B类的方法
2.简单工厂模式:调用者先找到被依赖对象的工厂,然后主动通过工厂去获取被依赖对象,最后再
调用被依赖对象的方法:
Phone p = PhoneFactory.getPhone();
p.callSomeOne(String phoneNum);
两种方式获取被依赖对象的方式都是主动的,这必然会导致调用者与被依赖对象之间的硬编码耦合,
非常不利于项目的升级和维护。使用Spring框架之后,调用者无需主动获取被依赖对象,调用者只需要
被动的接受Spring容器为调用者创建的依赖对象即可。
核心配置文件中的定义:
最后Java代码中就不需要主动去创建依赖对象了,这个依赖的过程由Spring实现:
由此可以见,使用了Spring后,调用者获取被依赖对象的方式由原来的主动获取,变成了被动接受 ,
所以Spring的创始人称之为控制反转。
但是从Spring的角度来看,Spring容器负责将被依赖的对象赋值给调用者的成员变量,相当于为调用者
注入它依赖的实例,另一个说法:依赖注入就是由此得来的。
实现依赖注入的方式
Spring支持3中依赖注入的方式,属性注入、构造器注入、工厂方法注入(使用较少)
1.属性注入
属性注入是指IoC容器通过成员变量的setter方法来注入bean的属性值或者被依赖对象。这种注入方式简单、
直观,因而再Spring的依赖注入里大量使用。属性注入使用<property>元素,使用name属性指定bean的属性
名称,value属性指定属性值
2.构造器注入
利用构造器来设置依赖关系的方式,被称为构造注入。通俗来说,就是驱动Spring在底层以反射方式
执行带指定参数的构造器,当执行带参数的构造器时,就可利用构造器参数对成员变量进行初始化:
bean类:
构造器注入的传参方式有三种:
1.按照索引匹配入参:
索引从0开始,表示构造器参数列表中的顺序,这种方式的缺点也很明显:
参数列表的顺序如果调整了,配置文件也需要跟着调整。
2.按类型匹配入参:
type的值是类型的全路径,这里constructor标签的顺序也表示参数列表的顺序,
如果构造器中列表是这样的:(String name , String sex , int age),那么为name
赋值的constructor标签应该放在第一位,sex第二,age第三。
3.根据属性名入参:
这种方式是最稳的了,不多BB。
自动装配
Spring IOC 容器可以自动装配 Bean,需要做的仅仅是在 <bean> 的 autowire 属性里指定自动装配的模式,
它能够将当前实例中所有的对象属性全部进行填充。
byType是根据类型自动装配,但要求是依赖Bean在容器中只能有一个实例。
若IoC容器中有多个与目标Bean类型一致的Bean,容器将无法判断哪个Bean最适合该属性,会报错。
byName是根据名称自动装配,要求是依赖的Bean的名称和属性名设置的完全相同。
这个属性名指的是Bean中定义的字段名:
那么在配置文件中对应的依赖bean的id值,也得是a:
自动装配的缺点:
1.在配置文件里设置autowire属性进行自动装配将会装配Bean的所有属性,如果只希望装配个别属性时,
autowire属性就不够灵活了。
2.autowire属性要么根据类型自动装配,要么根据名称自动装配,不能两者兼有之。