菜鸟的成长之路——三种依赖注入方式

  同学们看到题目,就有疑惑了,上节课我们不是讲过属性的注入了吗?这节课的注入方式又是什么意思?
  上节课呢,我们对于不同类型的注入深入探讨了,针对的是不同类型。这节课我们主要来聊一聊有哪些方法可以注入。举个例子,今天晚上你们吃五花肉、羊肉还是牛肉,这是我们上节课探讨的问题,这节课我们探讨的是针对某种肉,你是炸着吃、蒸着吃、还是炒着吃。

1、题目中的注入方式为什么还要加上“依赖”两个字?

  我们第一节课就讲过了注入依赖,注入依赖我们提到是bean和bean之间的关系。我们上节课都是探讨的简单类型和集合以及数组注入bean,并没有提到bean注入bean。
  准确的说,我们上节课只是学习了注入,但称不上依赖的注入,所以我们这节课主要是从依赖注入来入手。

2、那依赖注入有哪三种方式?

  依赖注入有三种方式,分别是:属性注入、构造方法注入、工厂方式注入。

3、属性注入是怎么实现的?

  属性注入,我们没有提过这个概念,但是其实上节课我们就已经接触了,并一直在用。我们先看下面的代码。
pom.xml

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.12.RELEASE</version>
        </dependency>

Pet.java

package com.spring.test;

public class Pet {
    private String name;
    private String sex;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return "name==>"+getName()+"\nsex==>"+getSex()+"\nage==>"+getAge();
    }
}

People.java

package com.spring.test;

public class People {
    private String name;
    private Pet pet;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Pet getPet() {
        return pet;
    }
    public void setPet(Pet pet) {
        this.pet = pet;
    }

}

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

    <bean id="people" class="com.spring.test.People">
        <property name="pet" ref="pet"></property>
    </bean>
    <bean id="pet" class="com.spring.test.Pet">
        <property name="name" value="旺财"></property>
        <property name="sex" value="男"></property>
        <property name="age" value="3"></property>
    </bean>

</beans>

SpringTest.java

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.spring.test.People;
import com.spring.test.Pet;

public class SpringTest{
    public static void main(String[] args) {
        ApplicationContext content = new ClassPathXmlApplicationContext("applicationContext.xml");
        People people = (People) content.getBean("people");
        Pet pet = people.getPet();
        System.out.println(pet.toString());
    }
}

  我们发现,在bean的配置里面,我们使用ref属性引入了另一个bean,其实我们也可以这么写:

    <bean id="people" class="com.spring.test.People">
        <property name="name" value="wangdonghui"></property>
        <property name="pet">
            <bean id="pet" class="com.spring.test.Pet">
                <property name="name" value="旺财"></property>
                <property name="sex" value="男"></property>
                <property name="age" value="3"></property>
            </bean>
        </property>
    </bean>

  下面这种写法和上面的写法效果是一样的,我们称下面内层的bean叫“内部bean”,这样写比较安全,防止其他bean错误的引用这个内部bean。但是这个内部bean如果在其他bean中也需要引用,那这么写显得不十分聪明了。
  我们继续说回我们属性注入,观察代码,在People类或者Pet类中,我们实际是通过属性的setter方法进行注入的,如果想验证的话可以删除掉setter方法测试一下。由于通过属性setter方法将一个bean注入到另个bean的形式,我们称其为“属性注入”。

4、构造方法注入是怎么实现的?

  顾名思义,构造方法注入就是通过bean的构造方法进行注入另个bean,直接上代码:
People.java

package com.spring.test;

public class People {
    private String name;
    private Pet pet;
    public People(String name,Pet pet) {
        // TODO Auto-generated constructor stub
        this.name = name;
        this.pet = pet;
    }
    public Pet getPet() {
        return pet;
    }
    public void setName(String name) {
        this.name = name;
    }
}

pet.java

package com.spring.test;

public class Pet {
    private String name;
    private String sex;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return "name==>"+getName()+"\nsex==>"+getSex()+"\nage==>"+getAge();
    }
}

applicationContext.xml

    <bean id="people" class="com.spring.test.People">
        <constructor-arg name="name" value="wangdonghui"></constructor-arg>
        <constructor-arg name="pet" ref="pet"></constructor-arg>
    </bean>
    <bean id="pet" class="com.spring.test.Pet">
        <property name="name" value="旺财"></property>
        <property name="sex" value="男"></property>
        <property name="age" value="3"></property>
    </bean>

SrpingTest.java

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.spring.test.People;
import com.spring.test.Pet;

public class SpringTest{
    public static void main(String[] args) {
        ApplicationContext content = new ClassPathXmlApplicationContext("applicationContext.xml");
        People people = (People) content.getBean("people");
        Pet pet = people.getPet();
        System.out.println(pet.toString());
    }
}

  构造方法注入的bean也可以写成内部bean的形式。
  我们刚才在people的bean中使用constructor-arg标签,这个标签里的name,对应了构造方法的参数名,ref引入了被注入的bean。除了对应参数名,我们也可以使用对应参数位置的方式注入,配置如下:

<bean id="people" class="com.spring.test.People">
        <constructor-arg index="0" value="wangdonghui"></constructor-arg>
        <constructor-arg index="1" ref="pet"></constructor-arg>
    </bean>
    <bean id="pet" class="com.spring.test.Pet">
        <property name="name" value="旺财"></property>
        <property name="sex" value="男"></property>
        <property name="age" value="3"></property>
    </bean>

  constructor-arg标签中的index属性,指明了参数的位置,从0开始,分别代表第一个参数、第二个参数…

5、工厂方式注入是怎么实现的?

  工厂方式注入有两种,一种是静态工厂注入,一种是实例工厂注入。我们先来研究一下静态工厂注入,代码如下:
Pet.java

package com.spring.test;

public class Pet {
    private String name;
    private String sex;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return "name==>"+getName()+"\nsex==>"+getSex()+"\nage==>"+getAge();
    }
}

PetFactory.java

package com.spring.test;

public class PetFactory {

    public static Pet createPet(String name,String sex,int age) {
        Pet pet = new Pet();
        pet.setName(name);
        pet.setSex(sex);
        pet.setAge(age);
        return pet;
    }
}

People.java

package com.spring.test;

public class People {
    private String name;
    private Pet pet;
    public People(String name,Pet pet) {
        // TODO Auto-generated constructor stub
        this.name = name;
        this.pet = pet;
    }
    public Pet getPet() {
        return pet;
    }
    public void setName(String name) {
        this.name = name;
    }
}

applicationContext.xml

<bean id="people" class="com.spring.test.People">
        <constructor-arg index="0" value="wangdonghui"></constructor-arg>
        <constructor-arg index="1" ref="pet"></constructor-arg>
    </bean>
    <bean id="pet" class="com.spring.test.PetFactory" factory-method="createPet">   
        <constructor-arg name="name" value="旺财"></constructor-arg>
        <constructor-arg name="sex" value="男"></constructor-arg>
        <constructor-arg name="age" value="3"></constructor-arg>
    </bean>

SpringTest.java

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.spring.test.People;
import com.spring.test.Pet;

public class SpringTest{
    public static void main(String[] args) {
        ApplicationContext content = new ClassPathXmlApplicationContext("applicationContext.xml");
        People people = (People) content.getBean("people");
        Pet pet = people.getPet();
        System.out.println(pet.toString());
    }
}

  这种方式称为静态工厂注入,在工厂类中创建pet的方法是静态的,在工厂类被实例前,pet就已经存在了。我们再来看看非静态的工厂方式注入,很多人也叫这种方式为实例工厂注入。
  实例工厂方式注入相对静态工厂方式注入,首先不需要把PetFactory的createPet方法静态化,也就是不需要static关键字修饰,其次是bean的配置发生了变化,变化后如下:

    <bean id="people" class="com.spring.test.People">
        <constructor-arg index="0" value="wangdonghui"></constructor-arg>
        <constructor-arg index="1" ref="pet"></constructor-arg>
    </bean>
    <bean id="petFactory" class="com.spring.test.PetFactory"></bean>
    <bean id="pet" class="com.spring.test.Pet" factory-bean="petFactory" factory-method="createPet">    
        <constructor-arg name="name" value="旺财"></constructor-arg>
        <constructor-arg name="sex" value="男"></constructor-arg>
        <constructor-arg name="age" value="3"></constructor-arg>
    </bean>

  实例工厂方式注入,首先要把工厂类实例出来,然后pet类才会存在实例。
  无论是静态注入还是非静态注入,在工厂类中的方法中,参数都是通过constructor-arg标签传参的,标签的用法和构造方法传参相同,不再累述。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值