Spring依赖注入的详细理解

来源:互联网 发布:项目管理分析软件 编辑:程序博客网 时间:2024/05/29 16:10

Spring依赖注入的详细理解

概念

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

属性注入

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

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

构造方法注入

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

  1. 按照类型匹配
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>
  1. 按照索引匹配
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>
  1. 联合类型和索引匹配
//使用联合类型和索引匹配是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>
  1. 通过自身类型反射匹配
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依赖注入方式的理解,如有不到之处,欢迎各位大神批评指正。
原创粉丝点击