欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring IOC 工厂【二】注入、注入详解、反转控制与依赖注入

程序员文章站 2022-06-13 14:50:19
...

注入(Injection)

1、 什么是注入?

​ 通过Spring工程及配置文件,为所创建的对象的成员变量赋值

2、 为什么需要注入?

​ 通过编码的方式,为成员变量进行复制,存在耦合

3、 如何进行注入?

  • 为成员变量提供getter和setter方法
  • 配置spring的配置文件
<bean id="person" class="com.rick.domain.Person">
	<property name="name">
    	<value>Rick</value>
    </property>
    <property name="age">
    	<value>20</value>
    </property>
    <property name="gender">
    	<value>male</value>
    </property>
</bean>

4、 注入的好处

  • 解耦合

5、对Spring注入原理简单分析

Spring通过底层调(property标签)用对象的set方法,完成对成员变量的赋值,这种方法我们也称之为set注入

注入详解

1、 Set注入

Spring IOC 工厂【二】注入、注入详解、反转控制与依赖注入

1.1 JDK内置类型

  • String + 8种基本类型
<bean id="person" class="com.rick.domain.Person">
	<property name="name">
    	<value>Rick</value>
    </property>
    <property name="age">
    	<value>20</value>
    </property>
</bean>
  • 数组
<bean id="person" class="com.rick.domain.Person">
	<property name="friends">
    	<list>
            <value>Mike</value>
            <value>Rick</value>
            <value>Bob</value>
        </list>
    </property>
</bean>
  • Set集合
<bean id="person" class="com.rick.domain.Person">
	<property name="telephone">
    	<set>
            <value>10086</value>
            <value>10010</value>
            <value>110</value>
            <value>110</value>
            <value>110</value>
            <!-- 根据set集合语义,会自动过滤重复的值 -->
        </set>
    </property>
</bean>
  • List集合
<bean id="person" class="com.rick.domain.Person">
	<property name="something">
    	<list>
            <value>123</value>
            <value>456</value>
        </list>
    </property>
</bean>
<!-- List未添加泛型时 -->
<bean id="person" class="com.rick.domain.Person">
	<property name="something">
    	<list>
            <list>123</list>
            <set>456</set>
            <ref bean></ref>
        </list>
    </property>
</bean>
  • Map集合
<bean id="person" class="com.rick.domain.Person">
	<property name="addressBook">
    	<map>
            <entry>
                <key><value>Mike</value></key>
                <value>10086</value>
            </entry>
            <entry>
                <key><value>Bob</value></key>
                <value>110</value>
            </entry>
        </map>
    </property>
</bean>
  • Properties
<bean id="person" class="com.rick.domain.Person">
	<property name="properties">
    	<props>
            <prop key="key1">value1</prop>
            <prop key="key2">value2</prop>
        </props>
    </property>
</bean>
  • 复杂的JDK类型(如Date)
需要程序员自定义类型转换器进行处理

1.2 用户自定义类型

第一种方式

<bean id="userService" class="com.rick.serviceImpl.userServiceImpl">
	<property name="userDao">
   		<bean class="com.rick.daoImpl.userDaoImpl"/>
    </property>
</bean>
<bean id="orderService" class="com.rick.serviceImpl.orderServiceImpl">
	<property name="userDao">
   		<bean class="com.rick.daoImpl.userDaoImpl"/>
    </property>
</bean>
  • 存在的问题:
1. xml存在代码冗余
		<bean class="com.rick.daoImpl.userDaoImpl"/>
2. 当被注入的对象(UserDao)多次创建,浪费虚拟机资源

第二种方式

<bean id="userDao" class="com.rick.daoImpl.userDaoImpl" />

<bean id="userService" class="com.rick.serviceImpl.userServiceImpl">
	<property name="userDao">
   		<ref bean="userDao"/>
    </property>
</bean>

<bean id="orderService" class="com.rick.serviceImpl.orderServiceImpl">
	<property name="userDao">
   		<ref bean="userDao"/>
    </property>
</bean>
<!-- Spring4.x废除了<ref local=""/>,其等效于<ref bean=""/> -->

1.3 Set注入的简化写法

基于属性简化

<!-- JDK类型注入 -->
<bean id="person" class="com.rick.domain.Person">
	<property name="name">
    	<value>Rick</value>
    </property>
    <property name="age" value="20"/>
</bean>
<!-- 注意:对properties的value属性赋值的简化方式只能简化String + 8种基本类型-->
<!-- 用户自定义类型 -->
<bean id="userDao" class="com.rick.daoImpl.userDaoImpl" />

<bean id="userService" class="com.rick.serviceImpl.userServiceImpl">
	<property name="userDao">
   		<ref bean="userDao"/>
    </property>
    
 <bean id="orderService" class="com.rick.serviceImpl.orderServiceImpl">
	<property name="userDao" ref="userDao"/>
</bean>

基于p命名空间简化

<!-- 引入p命名空间规范:xmlns:p="http://www.springframework.org/schema/p" -->
<!-- JDK类型注入 -->
<bean id="person" class="com.rick.domain.Person" p:age="20">
	<property name="name">
    	<value>Rick</value>
    </property>
</bean>
<!-- 注意:对properties的value属性赋值的简化方式只能简化String + 8种基本类型-->
<!-- 用户自定义类型 -->
<bean id="userDao" class="com.rick.daoImpl.userDaoImpl" />

<bean id="userService" class="com.rick.serviceImpl.userServiceImpl">
	<property name="userDao">
   		<ref bean="userDao"/>
    </property>
    
 <bean id="orderService" class="com.rick.serviceImpl.orderServiceImpl" P:userDao-ref="userDao">
	<property name="userDao" ref="us2.2erDao"/>
</bean>

2、 构造注入

  • 提供有参的构造方法
package com.rick.domain;

public class Person {

    private String name;
    private String password;
    private int age;
    private Dog dog;

    public Person(){}

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

    public Person(String name, String password, int age, Dog dog) {
        this.name = name;
        this.password = password;
        this.age = age;
        this.dog = dog;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

    public String getName() {
        return name;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                ", dog=" + dog +
                '}';
    }
}
  • Spring的配置文件
<bean id="customer" class="com.rick.domain.Customer">
	<constructor-arg>
        <value>Rick</value>
    </constructor-arg>
    <constructor-arg>
        <value>1000</value>
    </constructor-arg>
</bean>
<!-- <constructor-arg>的顺序为参数顺序 -->

2.1 构造方法重载

  • 构造参数个数不同
	通过控制 <constructor-arg>个数进行区分
  • 构造参数个数相同
	通过引入type属性进行类型的区分<constructor-arg type="">

3、注入总结

未来的实战开发中,应用set注入还是构造注入?
	set注入更多
		1、构造注入麻烦(重载)
		2、Spring框架底层大量应用了Set注入

Spring IOC 工厂【二】注入、注入详解、反转控制与依赖注入

反转控制与依赖注入

1、反转控制(IOC Inverse of Control)

  • 控制
    • 对于成员变量的赋值控制权
  • 反转控制
    • 把对于成员变量赋值的控制权,从代码反转(转移)到Spring工厂和配置文件中完成
  • 好处
    • 解耦合
  • 底层实现
    • 工程设计模式

2、依赖注入(DJ Dependency Injection)

  • 注入

    • 通过Spring的工厂和配置文件,为对象(bean、组件)的成员变量赋值
      Spring IOC 工厂【二】注入、注入详解、反转控制与依赖注入
  • 依赖注入

    • 当一个类需要另一个类时,就意味着依赖,一旦出现依赖,就可以吧另一个类作为本类的成员变量
  • 好处

    • 解耦合