【Spring04】DI依赖注入

1 概念

在Spring创建对象的同时,为其属性赋值的过程称之为依赖注入(Dependency Injection)。DI和IoC这两个概念其实是说的一码事,不过IoC更侧重于思想层面,DI更侧重于实操层面,要实现IoC的思想正是需要一次次的DI。

  • 注入:在工厂中为属性赋值的方式称之为注入。

  • 依赖注入:注入的是依赖关系而不是单纯的属性值。

2 Set注入

创建对象时候,Spring工厂会通过setter为对象的属性赋值的方式称之为Set注入。

创建一个具有各种各样类型属性的类来展示Set注入方法:

public class User {
    private Integer id;
    private String password;
    private String sex;
    private Integer age;
    private Date bornDate;
    private String[] hobbys;
    private Set<String> phones;
    private List<String> names;
    private Map<String,String> countries;
    private Properties files;
    private Address address;
    
    Setter and Getter

注意:使用Set注入一定要提供Setter和Getter。

Spring配置文件中书写好bean标签准备注入:

<bean id="user" class="com.qianglj.test2.entity.User">

</bean>

2.1 简单类型的注入

简单类型是指:基本数据类型、字符串类型以及日期类型。

对User的以下属性进行注入:

private Integer id;
private String password;
private String sex;
private Integer age;
private Date bornDate;

在Spring配置文件中进行注入:

<bean id="user" class="com.qianglj.test2.entity.User">
    <property name="id" value="1919"/>
    <property name="password" value="114514"/>
    <property name="sex" value="male"/>
    <property name="age" value="24"/>
    <property name="bornDate" value="1990/5/14"/>
</bean>
  • <property name="id" value="1919"/>

    • name写入属性名

    • 简单类型使用value属性来进行注入

  • <property name="bornDate" value="1990/5/14"/>

    • 注意时间类型的注入书写格式,需要按照年/月/日/ 时:分:秒的格式进行书写

2.2 容器类型的注入

容器类型是指:数组、Set、List、Mapo和Properties类型。

对User的以下属性进行注入:

private String[] hobbys;
private Set<String> phones;
private List<String> names;
private Map<String,String> countries;
private Properties files;

在Spring配置文件中进行注入:

<bean id="user" class="com.qianglj.test2.entity.User">
    ......
    <property name="hobbys">
        <array>
            <value>training</value>
            <value>football</value>
        </array>
    </property>
    <property name="phones">
        <set>
            <value>138114514</value>
            <value>1381919810</value>
        </set>
    </property>
    <property name="names">
        <list>
            <value>sennpai</value>
            <value>yaju</value>
        </list>
    </property>
    <property name="countries">
        <map>
            <entry key="kmr" value="kimura"/>
            <entry key="mur" value="miura"/>
        </map>
    </property>
    <property name="files">
        <props>
            <prop key="114514">iiyokoiyo</prop>
            <prop key="1919">ikuiku</prop>
        </props>
    </property>
</bean>
  • <array>

    • array标签表示需要注入类型的值是数组类型

    • 使用<value>标签包住注入的值

  • <set>

    • set标签表示需要注入类型的值是Set类型

    • 使用<value>标签包住注入的值

  • <list>

    • list标签表示需要注入类型的值是List类型

    • 使用<value>标签包住注入的值

  • <map>

    • map标签表示需要注入类型的值是Map类型

    • 使用entry标签写入需要注入的key-value

  • <props>

    • props标签表示需要注入类型的值是Property类型

    • 使用prop标签写入需要注入的key,并包住value

2.3 自建类型的注入

User中的自建类型Address具体如下:

public class Address {
    private Integer id;
    private String city;
	Getter and Setter

注入自建类型,首先需要在工厂中构造一个自建类型的bean:

<bean id="address" class="com.qianglj.test2.entity.Address">
    <property name="id" value="111"/>
    <property name="city" value="xiabeize"/>
</bean>

将这个bean注入给User:

<bean id="user" class="com.qianglj.test2.entity.User">
	......
    <property name="address" ref="address"/>
</bean>
  • 自建类型使用ref属性来进行注入

进行测试:

ApplicationContext ac = new ClassPathXmlApplicationContext("beans008.xml");
User user = (User) ac.getBean("user");
System.out.println("============");

在打印输出的地方打上断点,查看user变量的值可以发现:各属性值均已被正确地注入。

3 构造注入

构造注入是指创建对象时,Spring工厂会通过类的有参构造方法为对象的属性赋值。

定义目标Bean类型:

public class Student {
    private Integer id;
    private String name;
    private String sex;
    private Integer age;

    public Student(Integer id, String name, String sex, Integer age) {
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

Spring配置文件:

<bean id="student" class="com.qianglj.test2.entity.Student">
    <constructor-arg name="id" value="1"/>
    <constructor-arg name="name" value="Tom"/>
    <constructor-arg name="sex" value="male"/>
    <constructor-arg name="age" value="18"/>
</bean>
  • <constructor-arg name="id" value="1"/>

    • <constructor-arg>:表示一个构造方法的形参;

    • name属性:构造方法的形参名

    • value属性:简单类型的形参值;

    • ref属性:引用类型的形参值。

此时通过Debug模式查看赋值情况,可以看到student对象已经被赋值完毕:

构造注入还可以使用index属性表示参数的位置,构造方法参数从左往右的位置是0、1、2......示例如下:

<bean id="myConDIIndex2" class="com.jackqiang.ch002IoC.DIService">
    <constructor-arg value="1011"/>
    <constructor-arg value="conName3"/>
    <constructor-arg ref="myRef"/>
</bean>

也可以将index属性省略:

<bean id="myConDIIndex2" class="com.jackqiang.ch002IoC.DIService">
    <constructor-arg value="1011"/>
    <constructor-arg value="conName3"/>
    <constructor-arg ref="myRef"/>
</bean>

构造注入了解即可,具有一定的局限性,当想只注入部分的属性值时需要重写不同的构造方法,比较麻烦,不如set注入灵活。

4 自动注入

自动注入是指不需要在配置文件中指定为哪个属性赋值以及赋什么值,Spirng便可以自动地根据某个“规则”,在工厂中查找一个bean,为属性注入属性值。

自动注入的“规则”有两种:byName和byType。

  • byName(按名称注入):当Java类中引用类型的属性名称和spring容器中bean的id名称一样且数据类型一样,这样的bean能够赋值给引用类型

  • byType(按类型注入):当Java类中引用类型的数据类型和bean的class是同源的,这样的bean能够赋值给引用类型。同源关系是指:

    • Java中引用类型的数据和bean的class值是一样的;

    • Java中引用类型的数据和bean的class值是父子类关系的;

    • Java中引用类型的数据和bean的class的值是接口和实现类关系的

    • 在xml配置文件中,byType注入符合条件的对象只能有一个,多于一个得到情况是会报错的

byName注入示例:

public class UserServiceImpl implements UserService{

    private UserDao userDao;

    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void queryAllUsersPyPage() {
        System.out.println("UserService----queryAllUsersPyPage");
        userDao.queryAllUsers();
    }
  • 此处一定要提供Getter和Setter,否则会注入失败

Spring配置文件:

<bean id="userDao" class="com.qianglj.test1.dao.UserDaoImpl"/>
<bean id="userService" class="com.qianglj.test1.service.UserServiceImpl" autowire="byName"/>

 

版权声明:
作者:jackqiang
链接:http://www.jackqiang.com/framework/spring/1996/di/
来源:JackQiang's
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>
文章目录
关闭
目 录