【Spring IOC】注入、IOC、DI

参考自B站UP主视频《孙哥说Spring5》

概述

什么是注入?

注入:通过 Spring ⼯⼚及配置⽂件,为所创建对象的成员变量赋值

为什么要注入?

  • 通过编码的⽅式,为成员变量进⾏赋值,存在耦合。
  • 注入的好处:解耦合

举个例子

public void test4() {
    ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
    Person person = (Person) ctx.getBean("person");
    person.setId(1);
    person.setName("zhenyu");
    System.out.println(person);
}

通过代码为变量赋值,如果我们以后想修改变量的值,需要修改代码,重新编译,存在耦合

Spring 中如何注入

  • 类的成员变量提供 set get ⽅法【底层还是调用了get set方法注入】
  • 配置 spring 的配置⽂件
    <bean id="person" name="p" class="com.yusael.basic.Person">
        <property name="id">
            <value>10</value>
        </property>
        <property name="name">
            <value>yusael</value>
        </property>
    </bean>	
    

Spring中的注入原理分析

Spring 底层通过调用对象属性对应的 set 方法,完成成员变量的赋值,这种⽅式也称为 Set注入

在这里插入图片描述

Set注入的变量类型:

  • JDK内置类型
    8种基本类型 + String、数组类型、set集合、list集合、Map计划和、Properties集合。
  • 用户自定义类型

针对于不同类型的成员变量,在<property标签中,需要嵌套其他标签:

<property>
	xxxxx
</property>

对于不同类型的Set注入方式

在这里插入图片描述

JDK 内置类型

8种基本类型 + String

<property name="id">
	<value>10</value>
</property>
<property name="name">
	<value>yusael</value>
</property>

数组

<property name="emails">
    <list>
        <value>abc@qq.com</value>
        <value>123@qq.com</value>
        <value>hello@qq.com</value>
    </list>
</property>

Set集合

<property name="tels">
	<set>
		<!-- set会自动去重 -->
		<!-- set集合中如果没有约束泛型,那这里可以使用任何类型而不仅仅是value -->
		<!-- 甚至还可以是set里面嵌套set -->
		<value>138xxxxxxxxxx</value>
		<value>139xxxxxxxxxx</value>
		<value>138xxxxxxxxxx</value>
	</set>
</property>

List集合

<property name="addresses">
	<list>
		<value>China</value>
		<value>Earth</value>
		<value>hell</value>
	</list>
</property>

Map集合

<property name="qqs">
    <map>
        <entry>
            <key><value>hello</value></key>
            <value>12312312312</value>
        </entry>
        <entry>
            <key><value>world</value></key>
            <value>21314214214</value>
        </entry>
    </map>
</property>

Properites

<property name="p">
    <props>
        <prop key="key1">value1</prop>
        <prop key="key2">value2</prop>
        <prop key="key3">value3</prop>
    </props>
</property>

对于复杂JDK类型,如Date等,就需要程序员⾃定义类型转换器,处理。

用户自定义类型

第一种方式

  • 为成员变量提供 set get ⽅法
  • 配置⽂件中进⾏注入(赋值)
<bean id="userService" class="com.yusael.service.UserServiceImpl">
    <property name="userDAO">
        <bean class="com.yusael.dao.UserDAOImpl"/>
    </property>
</bean>

第⼀种赋值⽅式存在的问题:

  • 配置⽂件代码冗余;
  • 被注入的对象 (UserDAO)多次创建,浪费(JVM)内存资源。

第二种方式

  • 为成员变量提供 set get ⽅法;
  • 配置⽂件中进⾏配置;
<bean id="userDAO" class="com.yusael.dao.UserDAOImpl"></bean>

<bean id="userService" class="com.yusael.service.UserServiceImpl">
    <property name="userDAO">
        <ref bean="userDAO"/>
    </property>
</bean>

Spring4.x 废除了 <ref local=""/> 基本等效于 <ref bean=""/>

  • 区别在于 local 只能引用本配置文件的
  • 而 bean 不仅可以引用本配置文件的,还可以引用父配置文件的

简化Set注入

基于属性的简化

JDK 类型注入:

原来我们注入一个属性的写法:
<property name="id">
	<value>10</value>
</property>

简化后
<property name="id" value="10"/>

注意:value 属性只能简化  8种基本类型 + String

用户自定义类型注入:

简化前
<bean id="userDAO" class="com.yusael.dao.UserDAOImpl"></bean>

<bean id="userService" class="com.yusael.service.UserServiceImpl">
    <property name="userDAO">
        <ref bean="userDAO"/>
    </property>
</bean>

简化后:
<bean id="userDAO" class="com.yusael.dao.UserDAOImpl"></bean>

<bean id="userService" class="com.yusael.service.UserServiceImpl">
    <property name="userDAO" ref="userDAO"/>
</bean>

基于P命名空间的简化

pproperties的意思

先要在xml文件中引入命名空间

头部 beans 标签中加入
<beans xmlnx:p="http://www.springframework.org/schema/p">

JDK 类型注入:

简化前
<bean id="person" name="p" class="com.yusael.basic.Person">
	<property name="id">
		<value>10</value>
	</property>
	<property name="name">
		<value>yusael</value>
	</property>
</bean>

JDK 类型注入 - 基于p命名空间的简化后:
<bean id="person" name="p" class="com.yusael.basic.Person" p:name="yusael" p:id="10"/>

用户自定义类型注入:

简化前
<bean id="userDAO" class="com.yusael.dao.UserDAOImpl"></bean>

<bean id="userService" class="com.yusael.service.UserServiceImpl">
    <property name="userDAO">
        <ref bean="userDAO"/>
    </property>
</bean>

用户自定义类型注入 - 基于p命名空间的简化后:
<bean id="userDAO" class="com.yusael.dao.UserDAOImpl"></bean>

<bean id="userService" class="com.yusael.service.UserServiceImpl" p:userDAO-ref="userDAO"/>

构造注入

注入:通过 Spring 的配置⽂件,为成员变量赋值;
Set注入:Spring 调⽤ Set 方法 通过 配置⽂件 为成员变量赋值;
构造注入:Spring 调⽤ 构造方法 通过 配置⽂件 为成员变量赋值;

构造注入方式

  1. 提供有参构造方法
public class Customer {
    private String name;
    private int age;

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

    @Override
    public String toString() {
        return "Customer{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

}
  1. Spring 配置文件
<bean id="customer" class="com.yusael.constructor.Customer">
    <constructor-arg>
        <value>zhenyu</value>
    </constructor-arg>
    <constructor-arg>
        <value>21</value>
    </constructor-arg>
</bean>

构造方法是会重载的

参数不同

  • 参数个数不同时,通过控制 <constructor-arg> 标签的数量进⾏区分;
如果只有一个参数的话,只需要一对 <constructor-arg> 标签:
<bean id="customer" class="com.yusael.constructor.Customer">
    <constructor-arg>
        <value>zhenyu</value>
    </constructor-arg>
</bean>

如果有两个参数的话,用两对 <constructor-arg> 标签,以此类推
<bean id="customer" class="com.yusael.constructor.Customer">
    <constructor-arg>
        <value>zhenyu</value>
    </constructor-arg>
    <constructor-arg>
        <value>22</value>
    </constructor-arg>
</bean>

参数相同

  • 构造参数个数相同时,通过在标签引入 type 属性 进⾏类型的区分 <constructor-arg type="">
<bean id="customer" class="com.yusael.constructor.Customer">
	<constructor-arg type="int">
	    <value>20</value>
	</constructor-arg>
</bean>

总结

既然有两种注入方法,那一般会用哪一种呢?

set 注入更多

  • 构造注入麻烦(重载)
  • Spring 框架底层⼤量应⽤了 set注入。

在这里插入图片描述

反转控制 Inverse Of Control

反转控制(IOC Inverse of Control),也称为 转移控制

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

在这里插入图片描述

依赖注入 Dependency Injection

  • 注⼊:通过 Spring 的⼯⼚及配置⽂件,为对象(bean,组件)的成员变量赋值
  • 依赖注⼊:当⼀个类需要另⼀个类时,就意味着依赖,⼀旦出现依赖,就可以把另⼀个类作为本类的成员变量,最终通过 Spring 配置⽂件进⾏注⼊(赋值)
  • 好处:解耦合

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值