1 什么是注入
1.1 为什么需要注入
注入:通过Spring的配置文件,为成员变量赋值
Set注入:Spring调用Set方法 通过配置文件 为成员变量赋值
构造注入:Spring调用构造方法 通过配置文件 为成员变量赋值
1.2 注入的好处
解耦合
属性的值都写在xml配置文件里面, 以后修改可以直接修改xml文件里面的内容,代码层面不需要修改
2 Set注入详解
2.1 Set注入的原理分析(简易版)
Spring通过底层调用对象属性对应的set方法,完成成员变量的赋值,
这种方式我们也称之为set注入****
2.2如何进行Set注入[开发步骤]
- 类的成员变量提供set get方法
- 配置spring的配置文件applicationContext.xml
properties name 要和类的属性名一致
<bean id="person" class="com.baizhiedu.basic.Person">
<property name="id">
<value>10</value>
</property>
<property name="name">
<value>xiaojr</value>
</property>
</bean>
2.3成员变量的不同类型
标签代表调用变量的set方法,针对于不同类型的成员变量,在标签里面,需要嵌套其他标签
<property>
xxxxx
</property>
2.4 JDK内置类型
2.4 .1 String+8种基本类型
<value>suns</value>
2.4 .2 数组
目标赋值成员变量:
private String[] emails;
赋值方式:
<property name="emails">
<list>
<value>huosiyan@qq.com</value>
<value>xuguanghan@qq.com</value>
<value>dilireba@qq.com</value>
</list>
</property>
2.4 .3 Set集合(无序)
目标赋值成员变量:
private Set<String> phone;
赋值方式:
<property name="phone">
<set>
<value>15633339999</value>
<value>15633339988</value>
<value>15633339977</value>
<value>15633339999</value>
</set>
</property>
注意: Set集合最核心的标签是,里面存什么是根据set的泛型来的, 如果没有指定泛型, 标签里面就什么都可以放,例如
目标赋值成员变量(没有给set集合设置泛型):
private Set message;
赋值方式(set里面除了能存基本类型,也可以嵌套set,或者用户的自定义类型等等):
<property name="message">
<set>
<value>1111</value>
<set></set>
<list></list>
<ref bean=""/>
</set>
</property>
2.4.4 List集合(有序)
目标赋值成员变量:
private List<String> address;
赋值方式:
<property name="address">
<list>
<value>1111</value>
<value>浙江杭州</value>
<value>江苏南京</value>
<value>安徽合肥</value>
</list>
</property>
注意: 和set类似,list集合最核心的标签是 里面存什么是根据set的泛型来的, 如果没有指定泛型, 标签里面就什么都可以放
<list>
<ref bean
<set
</list>
2.4.5 Map集合
目标赋值成员变量:
private Map<String,String> family;
赋值方式:
一个entry标签代表一个键值对,
key需要用特定的标签 包起来,,
值根据对应类型选择对应类型的标签
<property name="family">
<map>
<entry>
<key><value>父亲</value></key>
<value>13699996666</value>
</entry>
<entry>
<key><value>母亲</value></key>
<value>16333333333</value>
</entry>
</map>
</property>
注意: Map集合最核心的标签是
<map>
<entry>
<key><value>chenyn</value></key>
<ref bean
</entry>
</map>
2.4.6 Properties集合
目标赋值成员变量:
private Properties p;
赋值方式:
<property name="p">
<props>
<prop key="userName">张三</prop>
<prop key="password">zhangsan</prop>
</props>
</property>
注意: Properties集合里面存的只能是字符串类型,不会出现其它类型的情况, 所以省略了标签不写
2.5 自定义类型
例如:UserService的实现类里面需要调用 UserDao访问数据库,通过Spring的方式完成成员注入,先声明UserDao成员变量,然后为成员变量提供set get方法
(提示:要想为UserService的成员变量UserDao赋值,需要先创建UserService对象)
public class UserServiceImpl implements UserService {
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void register(User user) {
userDao.save(user);
}
@Override
public void login(String name, String password) {
userDao.queryUserByNameAndPassWord(name,password);
}
}
2.5.1 第一种方式
配置文件中进行注入(赋值)
<bean id="userService" class="com.tcgroup.service.UserServiceImpl">
<property name="userDao">
<bean class="com.tcgroup.Dao.UserDaoImpl"/>
</property>
</bean>
2.5.2 第二种方式
- 第一种赋值方式存在的问题
- 配置文件代码冗余
- 被注入的对象(UserDAO),多次创建,浪费(JVM)内存资源
- 第二种方式:先创建好UserDao对象,userService调用userDao的时候 直接用标签调用即可
<bean id="userDao" class="com.tcgroup.Dao.UserDaoImpl"/>
<bean id="userService" class="com.tcgroup.service.UserServiceImpl">
<property name="userDao">
<ref bean="userDao"/>
</property>
</bean>
<bean id="orderService" class="com.tcgroup.service.OrderServiceImpl">
<property name="userDao">
<ref bean="userDao"/>
</property>
</bean>
3. Set注入的简化写法
3.1 基于属性简化
8种基本类型+String类型的属性注入标签 也就是value标签简化
<property name="age">
<value>10</value>
</property>
<property name="age" value="10"/>
用户自定义类型的引用简化:
<bean id="userService" class="com.tcgroup.service.UserServiceImpl">
<property name="userDao">
<ref bean="userDao"/>
</property>
</bean>
<bean id="userService" class="com.tcgroup.service.UserServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>
3.2 基于p命名空间简化
先在bean标签里面引入p命名空间,先写一个“p:” 然后按ALT+回车引入,在xml文件最上面可以看到xmlns:p=“http://www.springframework.org/schema/p”
8种基本类型+String类型的属性注入原来的写法:
<bean id="person" class="com.tcgroup.entity.Person">
<!-- 基于属性的简化写法 -->
<property name="age" value="10"/>
<property name="name">
<value>张三</value>
</property>
</bean>
通过P命名空间简化之后
<bean id="person" class="com.tcgroup.entity.Person" p:name="张三" p:age="10" />
用户自定义类型的引用之前的写法:
<bean id="userService" class="com.tcgroup.service.UserServiceImpl">
<property name="userDao">
<ref bean="userDao"/>
</property>
</bean>
通过P命名空间简化之后
<bean id="userService" class="com.tcgroup.service.UserServiceImpl" p:userDao-ref="userDao"/>
4. 构造注入
4.1. 开发步骤
- 提供有参构造方法
public class Customer implements Serializable {
private String name;
private int age;
private String gender;
public Customer(String name, int age) {
this.name = name;
this.age = age;
}
public Customer(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
@Override
public String toString() {
return "Customer{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}
- Spring的配置文件(applicationContext.xml)
通过标签赋值, 一个标签对应一个属性,顺序需要和构造参数的顺序一致
<bean id="customer" class="com.tcgroup.entity.Customer">
<constructor-arg>
<value>张三三</value>
</constructor-arg>
<constructor-arg>
<value>12</value>
</constructor-arg>
<constructor-arg>
<value>男</value>
</constructor-arg>
</bean>
4.2 构造方法重载
2.1 参数个数不同时
参数个数不同时,Spring会根据构造方法的形参个数来确定调用哪个构造方法,
2.2 构造参数个数相同时
但是如果有两个构造方法的形参个数相同,且都是用同一个标签赋值时, 我们需要在XML文件里面通过在标签引入 type属性 进行类型的区分
public Customer(String name) {
this.name = name;
}
public Customer(int age) {
this.age = age;
}
<bean id="customer" class="com.tcgroup.entity.Customer">
<constructor-arg type="int">
<value>12</value>
</constructor-arg>
</bean>
constructor-arg标签里面还有很多其他属性,可以参加下面这位大佬的博文介绍
https://blog.csdn.net/S_Tian/article/details/103824017
实战大量应用的是set注入,因为构造方法重载麻烦,且Spring底层也大量应用了Set注入
5.反转控制和依赖注入
5.1 反转控制概念![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/8ab4f7167c176931011e08cc54851254.png)
反转(转移)控制(IOC Inverse of Control)
控制:对于成员变量赋值的控制权
反转控制:把对于成员变量赋值的控制权,从代码中反转(转移)到Spring工厂和配置文件中完成
好处:解耦合
底层实现:工厂设计模式
5.2 依赖注入 (Dependency Injection DI)
依赖注入是一种Spring的编程方式
注入:通过Spring的工厂及配置文件,为对象(bean,组件)的成员变量赋值
依赖注入:当一个类需要另一个类时,就意味着依赖,一旦出现依赖,就可以把另一个类作为本类的成员变量,最终通过Spring配置文件进行注入(赋值)。
好处:解耦合