Spring框架——使用构造函数或set实现的依赖注入

Spring 中的依赖注入

​ 依赖注入:Dependency Injection,它是 spring 框架核心 ioc 的具体实现

​ 我们的程序在编写时,通过控制反转,把对象的创建交给了 spring,但是代码中不可能出现没有依赖的情况,ioc 解耦只是降低他们的依赖关系,但不会消除

​ 例如:我们的业务层仍会调用持久层的方法,那这种业务层和持久层的依赖关系,在使用 spring 之后,就让 spring 来维护了,简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取

通过构造函数实现依赖注入

​ 顾名思义,就是使用类中的构造函数,给成员变量赋值,赋值的操作不是我们自己做的,而是通过配置的方式,让 Spring 框架来为我们注入的,下面我们来看具体代码:

​ AccountServiceImpl 类中存在着StringIntegerDate三种类型的变量。分别代表基本类型及 String其他特殊类型两大类,并提供他们的构造函数:

package com.lmh.service.impl;

import com.lmh.dao.IAccountDao;
import com.lmh.dao.impl.AccountDaoImpl;
import com.lmh.service.IAccountService;

import java.util.Date;

/**
 * 账户的业务层实现类
 */
public class AccountServiceImpl implements IAccountService {

    private String name;
    private Integer age;
    private Date birthday;

    public AccountServiceImpl(String name, Integer age, Date birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }

    @Override
    public void saveAccount() {
        System.out.println("save service");
        System.out.println(name + ", " + age + ", " + birthday);
    }

}

​ 在bean.xml中配置依赖注入:

<bean id="now" class="java.util.Date"/>
<bean id="accountService" class="com.lmh.service.impl.AccountServiceImpl">
    <constructor-arg name="name" value="test"/>
    <constructor-arg name="age" value="18"/>
    <constructor-arg name="birthday" ref="now"/>
</bean>

​ 这里需要注意,由于Date是其他特殊类型,不被包含在 Java 的基本类型或字符串中,所以我们需要为Date类型创建一个<bean>,然后在另一个<bean><constructor-arg>标签中使用ref属性来引用它,实现依赖注入

​ 这里我是使用<constructor-arg>标签的name属性来指定变量名实现依赖注入的,<constructor-arg>标签还支持使用typeindex两个属性,其中type是根据变量类型为变量赋值,这里存在使用的局限性,index通过变量在构造函数参数列表中的位置(从 0 开始)来为变量赋值,可以看到,使用name还是比较实用的

​ 而value标签是为基本类型变量直接赋值,它可以将" "中的值自动转换为相应的数据类型,ref是专门为特殊的类型进行赋值的,它通过引用定义好的<bean>来进行赋值

优缺点

​ 优势:在获取 bean 对象时,注入数据是必须的操作,否则对象无法创建成功

​ 弊端:改变了 bean 对象的实例化方式,在我们创建对象时,如果用不到这些数据,也必须提供

通过 Set 方法实现依赖注入

​ 该方法我们需要在类中为变量添加对应的 set 方法:

package com.lmh.service.impl;

import com.lmh.service.IAccountService;

import java.util.Date;

/**
 * 账户的业务层实现类
 */
public class AccountServiceImpl2 implements IAccountService {

    // 如果是经常变化的数据,并不适用于注入的方式
    private String name;
    private Integer age;
    private Date birthday;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Override
    public void saveAccount() {
        System.out.println("save service");
        System.out.println(name + ", " + age + ", " + birthday);
    }

}

​ 在bean.xml中配置依赖注入:

<bean id="accountService2" class="com.lmh.service.impl.AccountServiceImpl2">
    <property name="name" value="test"/>
    <property name="age" value="21"/>
    <property name="birthday" ref="now"/>
</bean>

​ 使用 set 方法实现依赖注入时,我们使用<bean>标签内部的<property>标签,<property>标签的使用以及内部的属性和<constructor-arg>标签相同,对于Date这种类型,同样需要使用引用的方式进行赋值

优缺点

​ 优势:创建对象时没有明确的限制,可以直接使用默认构造函数

​ 弊端:如果有某个成员必须有值,则获取对象时有可能 set 方法没有执行

集合类型变量的依赖注入

​ 集合类型的变量如何实现依赖注入呢?我们这里以 set 方法为例

package com.lmh.service.impl;

import com.lmh.service.IAccountService;

import java.util.*;

/**
 * 账户的业务层实现类
 */
public class AccountServiceImpl3 implements IAccountService {

    private String[] myStrs;
    private List<String> myList;
    private Set<String> mySet;
    private Map<String, String> myMap;
    private Properties myProps;

    public void setMyStrs(String[] myStrs) {
        this.myStrs = myStrs;
    }

    public void setMyList(List<String> myList) {
        this.myList = myList;
    }

    public void setMySet(Set<String> mySet) {
        this.mySet = mySet;
    }

    public void setMyMap(Map<String, String> myMap) {
        this.myMap = myMap;
    }

    public void setMyProps(Properties myProps) {
        this.myProps = myProps;
    }

    @Override
    public void saveAccount() {
        System.out.println("save service");
        System.out.println(Arrays.toString(myStrs));
        System.out.println(myList);
        System.out.println(mySet);
        System.out.println(myMap);
        System.out.println(myProps);
    }

}

​ 在bean.xml中配置依赖注入:

<bean id="accountService3" class="com.lmh.service.impl.AccountServiceImpl3">
    <property name="myStrs">
        <array>
            <value>AAA</value>
            <value>BBB</value>
            <value>CCC</value>
            <value>DDD</value>
        </array>
    </property>
    <property name="myList">
        <list>
            <value>AAA</value>
            <value>BBB</value>
            <value>CCC</value>
            <value>DDD</value>
        </list>
    </property>
    <property name="mySet">
        <set>
            <value>AAA</value>
            <value>BBB</value>
            <value>CCC</value>
            <value>AAA</value>
        </set>
    </property>
    <property name="myMap">
        <map>
            <entry key="testA" value="aaa"/>
            <entry key="testB" value="bbb"/>
        </map>
    </property>
    <property name="myProps">
        <props>
            <prop key="testc">ccc</prop>
            <prop key="testd">ddd</prop>
        </props>
    </property>
</bean>

​ 以上是集合类型变量使用 set 方法实现依赖注入的代码,这里需要注意一点,相同类型的集合可以使用相同的标签实现依赖注入,即array、List、Set属于同类型,Map、Properties属于同类型,例如array可以通过<list>标签实现依赖注入

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章