DI-Dependency Injection,即“依赖注入”,组件之间的依赖关系由容器在运行期决定,即容器动态的将某个依赖关系注入到组件当中。
DI理解的关键点:“谁依赖谁,为什么需要依赖”
谁依赖谁:应用程序依赖IOC容器
为什么需要依赖:应用程序需要IOC容器来提供对象需要的外部资源
注入什么:注入某个对象所依赖的外部资源
<!--依赖注入方式1:有参构造-->
<bean id="user3" class="com.tulun.bean.User">
<!--id属性的注入-->
<constructor-arg name="id" value="22"></constructor-arg>
<!--name属性的注入-->
<constructor-arg name="name" value="zhangsan"></constructor-arg>
</bean>
有参构造函数的依赖注入主要使用
在类中必须包含有参构造函数,且和构造函数保持参数一致
<!--依赖注入方式2:set方法-->
<bean id="user4" class="com.tulun.bean.User">
<!--id属性注入-->
<property name="id" value="12"/>
<!--name属性赋值-->
<property name="name" value="李四"/>
</bean>
set方法注入依赖时,使用property标签,name属性表示类中的属性名,value属性表示当前属性的赋值
注入的属性可以是基本的类型,也可以是集合类型,也可以是自定义类型
<!--对象的注入-->
<!--在Person类中注入自定义的User-->
<bean id="user5" class="com.tulun.bean.User"/>
<bean id="person" class="com.tulun.bean.Person">
<!--user属性通过set方式注入-->
<!--value:会按照String类型的字符串做解析 ref:Spring中管理对象的ID名-->
<property name="user" ref="user5"/>
</bean>
集合类型
注入List类型的
<!--List的注入-->
<bean id="person1" class="com.tulun.bean.Person">
<property name="list">
<list>
<value>hello</value>
<value>你好</value>
<value>123</value>
</list>
</property>
</bean>
其他形式的集合配置
<!--数组的注入-->
<bean id="person2" class="com.tulun.bean.Person">
<property name="list">
<!--array标签:注入数字-->
<array>
<!--value是直接给定值-->
<value></value>
<!--ref是存储的引用对象-->
<!--<ref></ref>-->
</array>
</property>
</bean>
<!--set的注入-->
<bean id="person3" class="com.tulun.bean.Person">
<property name="list">
<!--set标签:注入set类型的集合-->
<set>
</set>
</property>
</bean>
<!--map的注入-->
<bean id="person4" class="com.tulun.bean.Person">
<property name="list">
<!--map标签:注入Map类型的集合-->
<map>
<entry key="1" value="zhangsan"/>
</map>
</property>
</bean>
@Component(value = "user")
public class User {
@Value("1")
private String id;
@Value("张三")
private String name;
注:使用Value注解注入依赖前提是Bean的装配支持注解扫描
@Component(value = "person")
public class Person {
//自定义类型属性
//和@Resource功能一样
@Autowired
private User user;
}
@Resource和@Autowired的异同点?
在Spring中,@Resource和@Autowired都是做Bean的注入时使用,@Resource和@Autowired可以替换使用。
相同点:
@Resource和@Autowired是可以作为注入属性的修饰,在接口仅有单一实现类时,两个注解效果一样,可互相替换,不影响使用。
不同点:
@Resource 是Java中提供的注解,@Resource存在两个属性,分别为name和type,在Spring中是通过name来解析bean的名字,而type属性则解析为bean的类型。所以如果使用name属性时,使用byName自动注入策略,而使用type属性时则使用byType自动注入策略,如果不指定name或者type属性时,这时将通过反射机制使用byName自动注入策略
@Autowired 是Spring提供的注解,在Spring2.5版本引入,@Autowired只根据type进行注入,不会去匹配name,如果type无法识别注入对象时,需要依赖@Qualifiler或者是Primary注解一起修饰
容器解析Bean的依赖过程:
容器在创建的时候,Spring容器会验证每一个bean的信息,在实际创建bean之前,bean的属性是不会被设置的。bean只会在需要他的时候被创建,创建bean的过程中可能会引起一系列的bean被创建,例如bean的依赖,其依赖的依赖等等会被一起创建和分配。注意:依赖之间解析不匹配可能会出现,即首循环创建有影响的bean。
循环依赖的问题
class User{
private Person person;
}
class Person{
private User user;
}
如果是通过构造方法的方式注入,就有可能造成无法解决的循环依赖
例如:ClassA需要通过构造方法注入一个ClassB的实例,ClassB同样需要通过构造方法注入ClassA的实例,如果为ClassA和ClassB配置bean并且相互注入,IOC容器在运行时会发现这个循环引用,抛出异常:BeanCurrentlyInCreationException
解决循环依赖的途径需要去编辑代码,让这些类通过setter方法注入,避免使用构造方法注入。