您的位置:首页 > 编程语言 > Java开发

Spring依赖注入的详细理解

2017-09-16 11:38 281 查看

Spring依赖注入的详细理解

概念

让调用类对某一接口实现类的依赖关系由第三方z注入,以移除调用类对某一接口实现类的依赖。在一定程度上解除代码耦合。

属性注入

属性注入即通过setter方法注入Bean的属性值或者依赖对象。

要求Bean必须要提供一个无参构造函数以及需要注入的属性的setter方法,如果没有无参构造函数,则在配置文件中,注入属性值之前,要指定该bean的构造方法,否则会抛出异常。

<bean id="***" class="***">
<!-- 注意:该bean中对应的类,必须要有setHello这个方法,具体有没有hello属性,spring不做要求,因为利用属性注入时,使用反射机制调用的是setter方法而不是直接查找属性。 -->
<property name="hello">
<value>hello world!</value>
</property>
</bean>


构造方法注入

构造注入是另一种较为常用的注入方式,它可以保证创建实例的时候同时对一些必要的属性进行赋值,可以按照类型、索引等方式匹配参数。

按照类型匹配

public class Person{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
}

<bean id="person" class=***.Person">
<constructor-arg type="String">
<value>CSDN红枫</value>
</consturctor-arg>
<constructor-arg type="int">
<value>23</value>
</consturctor-arg>
</bean>


按照索引匹配

public class Person{
private String name;
private String sex;
private int age;
public Person(String name, String sex, int age){
...
}
}
<bean id="person" class=***.Person">
<!-- 此处由于构造方法中前两个参数的类型都为String,此时再通过类型入参,就会产生混淆,需要通过指定索引的方式入参。 -->
<constructor-arg index="1" value="CSDN红枫"/>
<constructor-arg index="2" value="男"/>
<constructor-arg index="3" value="23"/>
</bean>


联合类型和索引匹配

//使用联合类型和索引匹配是spring依赖注入中最安全,最不容易出错的匹配方式
public class Person{
private String name;
private int age;
public Person(String name, int age){
...
}
public Person(int age, String name){
...
}
}
<bean id="person" class=***.Person">
<!-- 此处Person类提供了两个构造函数,都是两个参数,所以按索引入参在此处就不适用了,而参数类型又都是一个String一个int,知识顺序不同,按照类型也无法满足要求,只能使用联合索引和类型的方式进行参数传入。 -->
<constructor-arg index="1" type="String" value="CSDN红枫"/>
<constructor-arg index="2" type="int" value="23"/>
</bean>


通过自身类型反射匹配

public class Person{
private House house;
private Car car;
public Person(House house, Car car){
...
}
}

<bean id="house" class="***"/>
<bean id="car" class="***"/>
<bean id="person" class=***.Person">
<!-- 此处Person类提供了的构造函数,参数类型对于Spring来说都是明确的,可以直接通过Spring对参数类型的反射进行传参 -->
<constructor-arg ref="house"/>
<constructor-arg ref="car"/>
</bean>


循环依赖问题

spring使用依赖注入时,所注入的对象必须是已经准备就绪的对象,那么,当BeanA依赖于BeanB,同时BeanB又依赖于BeanA时,则会造成一种类似线程死锁的问题。

public class Person{
private House house;
public Person(House house){
...
}
}
public class House{
private Person person;
public House(Person person){
...
}
}
<bean id="person" class="***">
<constructor-arg ref="house"/>
</bean>
<bean id="house" class="***">
<constructor-arg ref="person"/>
</bean>
<!-- 在这种情况下,必然后产生循环依赖问题,spring容器无法完成两个类的创建,此时需要手动的修改Bean的代码,将其中一个类的构造注入改为属性注入。 -->


工厂方法注入

工厂模式是实际应用中最常用的设计模式之一,但是由于spring框架中提供了工厂模式的实现,所以在引入spring后,手动编写工厂模式的需要越来越少,一般情况下都通过spring框架来实现。

非静态工厂方法

public class HouseFactory{
public House createHouse(){
return new House();
}
}

<bean id="houseFactory" class="***.HouseFactory"/>
<bean id="house" factory-bean="houseFactory" factory-method="createHouse"/>


静态工厂方法

public class HouseFactory{
public static House createHouse(){
return new House();
}
}

<bean id="house" class=="***.HouseFactory" factory-method="createHouse"/>


个人来说,比较偏向于属性注入,使用属性注入,可以减轻构造函数的职责,避免构造函数重载多次时的歧义,在存在继承的结构上,属性注入要远远优于构造注入,另外使用属性注入还可以避免循环依赖问题。

以上是我对个人对Spring依赖注入方式的理解,如有不到之处,欢迎各位大神批评指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring