在spring使用里面,我用了一个小例子来简单介绍了spring的使用。里面提到了依赖注入DI,DI在spring容器里面有几种方式实现。在那个例子当中,我用的是使用setter方法注入。接下来我们详细讲一下DI注入的几种方式。
DI的实现方式有:
setter方法注入
在注入之前,我们首先要有配置好的Bean。在该Bean里面,还要有想要我们注入的属性。后续这一步不再重复提。
然后,我们要给需要注入的Bean类的属性设置一个setter方法,方法名通常为set + 属性名(首字母大写)。类里的属性名和 方法名的 set 后的属性名 可以不一样。
然后在Bean配置文件的对应的Bean配置处,在其标签<bean>的下面创建二级标签<property>,通过name属性寻找给属性的注入的setter方法。之后,value设置简单的属性,ref则用来注入对象(通常是其他Bean)。
运行结果:
除此之外,使用setter方法注入时要注意,配置文件里面,属性name寻找的setter方法,而不是直接寻找需要依赖注入的属性,如果你的一个属性设置了两个不同名的setter方法,在Bean配置文件了name会找到两个值,分别是这个两个setter方法的后缀名字(首字母去大写)。
name、setter方法、属性 这三者之间的关系如下图:
这张图可能还不懂,这里我们再创建一个setter方法,也是设置classroom类的属性student的:
然后我们回到bean的配置文件来查看 <bean>标签的 属性name 它的可选值 :
虽然name有两个可选值,而实际上Classroom类只有一个属性student。
value和ref都是用来注入值的。value用来注入基础值,例如int、boolean、String等。ref则用来注入一个对象,该对象是同样在当前XML配置文件里面申明了的其他Bean对象。
当然,同样要注意,当为单例模式的时候,一个IOC容器里面只能存在一个对象。此时多个其他Bean对象注入这个单例的Bean对象,那么其他Bean对象获取到的都是同一个对象(在内存当中),此时要注意多线程的问题。
构造器注入
构造器注入,也就是通过构造函数进行依赖注入。与使用setter方法类似,我们要在<bean>标签下使用二级标签<constructor-arg>来进行配置。
该标签用于指定创建Bean对象的参数,然后调用对应的有参构造方法。它主要有这几个属性:
name:用来指定参数名字,该参数名与构造函数里面的参数名一致
value/ref:用来输入值的数据,两者区别与property中的 value/ref 一致
type:当使用value时,可以使用该属性声明你所输入的值的类型
该属性是否使用主要看版本
不管我们输入的是什么也好,value值我们给的值原本都是是String类型,然后会自动转换我们所需要的数据类型。但在高版本的spring中,撤掉了自动类型转换,需要我们使用type声明我们输入的数据属于什么类型。
index:设置该参数位于传递的参数列表中的第几个。该属性和name只需要使用其中之一即可,都是用来设置传递的参数所构成的参数列表的。
当有多个参数的时候,便在<bean>下面创建多个<constructor-arg>传递多个参数值即可。注意,你所传递的参数所构成的参数列表必须与某个构造函数的参数列表一致。
自动注入:byName
该byName是基于前面的setter方法注入来实现的。我们只需要给<bean>标签的属性autowire设置属性为byName即可。
设置为byName后,spring容器会自动寻找name的可取值,与你Bean配置文件中的其他Bean的id/name进行对比,如果找到了相同的组合,就会将该Bean对象注入到你需要依赖注入的Bean对象里面。
自动注入:byType
如果你将属性autowire设置属性为byType,那么setter方法和用来注入的Bean的标识名是否一致就没有关系了。这个时候,spring容器是根据两者的数据类型来进行判断。
但是如果你给同一个类配置了多个Bean,然后又有一个Bean类需要注入该类的对象,那么此时就会报错。这个时候我们可以通过注解的方法来指定我们需要的那个Bean即可。但这样其实就回到了byName,byType一般在大场景用得比较少。