Spring IOC 工厂【二】注入、注入详解、反转控制与依赖注入
程序员文章站
2022-06-13 14:50:19
...
Spring IOC 工厂【二】注入、注入详解、反转控制与依赖注入
注入(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注入
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注入
反转控制与依赖注入
1、反转控制(IOC Inverse of Control)
- 控制
- 对于成员变量的赋值控制权
- 反转控制
- 把对于成员变量赋值的控制权,从代码反转(转移)到Spring工厂和配置文件中完成
- 好处
- 解耦合
- 底层实现
- 工程设计模式
2、依赖注入(DJ Dependency Injection)
-
注入
- 通过Spring的工厂和配置文件,为对象(bean、组件)的成员变量赋值
- 通过Spring的工厂和配置文件,为对象(bean、组件)的成员变量赋值
-
依赖注入
- 当一个类需要另一个类时,就意味着依赖,一旦出现依赖,就可以吧另一个类作为本类的成员变量
-
好处
- 解耦合
上一篇: CentOS7 分区格式转为GPT
下一篇: 记,NSProxy需要实现哪些方法?
推荐阅读