文章目录
-
依赖注入DI (Dependency Injection):从应用程序的角度描述,创建对象实例时,为这个对象注入属性值或其它对象实例,(依赖于容器注入它所需要的外部资源)。实现
-
控制反转:从容器的角度描述,创建对象实例的控制权从应用程序,反转到IOC容器控制(在xml文件控制),强调容器的作用。负责将被依赖对象赋值给调用者的成员变量,相当于为调用者注入了它依赖的实例,因此控制翻转也可以称之为依赖注入。概念
依赖注入的两种方式
- 构造器注入(构造方法)
- set方法注入
1 构造方法注入
1.1 基本数据类型
简单数据类型字符串。
1.为实体类添加构造方法
public class User {
private String name;
private String sex;
private int age;
public User(String name, String sex, Integer age) {
this.name = name;
this.sex = sex;
this.age = age;
}
2. 修改配置文件
- constructor-arg标签属性
- name属性:通过参数名找到参数列表中对应参数
- index属性:通过参数在参数列表中的索引找到参数列表中对应参数,index从0开始。
- type属性:通过参数数据类型找到参数列表中对应参数
- value属性:设置参数列表参数对应的值,用于设定基本数据类型和String类型的数据
- ref属性:如果参数值为非基本数据类型,则可通过ref为参数注入值,其值为另一个bean标签id或name属性的属性值
- constructor-arg子标签:
- ref子标签:对应ref属性,该标签name属性的属性值为另一个bean标签id或name属性的属性
- value子标签:对应value属性,用于设置基本数据类型或String类型的参数值;
- list子标签:为数组或List类型的参数赋值
- set子标签:为Set集合类型参数赋值
- map子标签:为Map集合类型参数赋值
- props子标签:为Properties类型的参数赋值
<bean id = "user" class="com.qlit.bean.User">
<constructor-arg name="name" value="张三"/>
<constructor-arg name="sex" value="男"/>
<constructor-arg name="age" value="22"/>
</bean>
1.2 拓展Lombok
使用lombok,快速生成常用方法提高开发速度。
-
idea安装插件
文件➡️设置➡️插件,搜索Lombok
-
引入依赖
中央仓库地址:https://mvnrepository.com/
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
- 修改实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String name;
private String sex;
private Integer age;
public void sayHello(){
System.out.println("hello");
}
}
- 其他说明
@Getter/@Setter: 作用类上,生成所有成员变量的getter/setter方法;
作用于成员变量上,生成该成员变量的getter/setter方法。@ToString: 作用于类,覆盖默认的toString()方法
@EqualsAndHashCode: 作用于类,覆盖默认的equals和hashCode
@NoArgsConstructor生成无参构造器;
@RequiredArgsConstructor生成包含final和@NonNull注解的成员变量的构造器;
@AllArgsConstructor生成全参构造器
@Data: 作用于类上,注解集合,使用它相当于使用下列注解:
- @ToString
- @EqualsAndHashCode
- @Getter
- @Setter
- @RequiredArgsConstructor
@Builder: 作用于类上,将类转变为建造者模式
@Log: 作用于类上,生成日志变量
1.3 自定义类型
- 定义idcard类,生成构造方法等。
- 实体类user中添加private IdCard idcard属性,并更新构造方法。
public class IdCard {
int id;
String code;
}
xml方式一
<bean id="idcard" class="com.yiwu.pojo.IdCard">
<constructor-arg name="id" value="1"/>
<constructor-arg name="code" value="2222222"/>
</bean>
<bean id = "user3" class="com.yiwu.pojo.User">
<constructor-arg name="name" value="张三"/>
<constructor-arg name="sex" value="男"/>
<constructor-arg name="age" value="22"/>
<constructor-arg name="idcard" ref="idcard"/>
</bean>
xml方式二
<bean id = "user4" class="com.yiwu.pojo.User">
<constructor-arg name="name" value="张三"/>
<constructor-arg name="sex" value="男"/>
<constructor-arg name="age" value="22"/>
<constructor-arg name="idcard">
<bean class="com.yiwu.pojo.IdCard">
<constructor-arg name="id" value="1"/>
<constructor-arg name="code" value="2222222"/>
</bean>
</constructor-arg>
</bean>
1.4 日期类型date
实体类中添加private Date brithday属性,并更新构造方法。
方式一
对于dete对象同样利用其构造方法。
<bean id="b" class="java.util.Date">
<constructor-arg name="year" value="10"/>
<constructor-arg name="month" value="11"/>
<constructor-arg name="date" value="2"/>
</bean>
<bean id = "user5" class="com.yiwu.pojo.User">
<constructor-arg name="name" value="张三"/>
<constructor-arg name="sex" value="男"/>
<constructor-arg name="age" value="22"/>
<constructor-arg name="brithday" ref="b"/>
</bean>
方式二
<bean id = "user6" class="com.yiwu.pojo.User">
<constructor-arg name="name" value="张三"/>
<constructor-arg name="sex" value="男"/>
<constructor-arg name="age" value="22"/>
<constructor-arg name="brithday">
<bean class="java.util.Date">
<constructor-arg name="year" value="10"/>
<constructor-arg name="month" value="10"/>
<constructor-arg name="date" value="2"/>
</bean>
</constructor-arg>
</bean>
1.5 集合类型
🔴List类型
-
实体类添加private List < String> product;属性,生成对应构造方法(此处仅仅生成了product的构造方法)
-
如果List集合元素为基本数据类型包装类或String类型,则可通过value标签设置值;如果为其它引用类型的数据则可以通过bean标签或ref标签设置元素值,每对标签设置一个集合元素。
<bean id = "user7" class="com.yiwu.pojo.User">
<constructor-arg name="product">
<list>
<value>aaa</value>
<value>bbb</value>
<!-- <ref bean="xxxx">-->
<!-- <bean class=xxxxx">-->
<!-- <constructor-arg value="xxx"></constructor-arg>-->
<!-- </bean>-->
</list>
</constructor-arg>
</bean>
🔴Set 类型
用法与list一致,仅需要将xml文件中的list标签改为set标签
🔴Map类型
如果Map集合的值为基本数据类型包装类或String类型,则可通过value属性直接设置;如果为引用类型(如String类型)的数据则可以通过entry 标签的value-ref标签属性(其值为另一个bean标签id或name属性的属性值)或entry 标签bean子标签、ref子标签、list子标签(如果Map集合值为List集合)、set子标签(如果Map集合值为Set集合)或map子标签(如果Map集合值为Map集合)进行设置。
<bean id = "user9" class="com.yiwu.pojo.User">
<constructor-arg name="myMap">
<map>
<entry key="k1" value="aaa"/>
<entry key="k2" value="bbb"/>
<entry key="k3" value="ccc"/>
</map>
</constructor-arg>
</bean>
1.6 Properties
实体类添加private Properties myProperties属性,添加构造方法,更新toString方法
<bean id = "user10" class="com.yiwu.pojo.User">
<constructor-arg name="myProperties">
<props>
<prop key="key1">aaa</prop>
<prop key="key2">aaa</prop>
</props>
</constructor-arg >
</bean>
2 set方法注入
分析:
在 Spring 实例化 Bean 的过程中,IoC 容器首先会调用默认的构造方法(无参构造方法)实例化 Bean(Java 对象),然后通过 Java 的反射机制调用这个 Bean 的 setXxx() 方法,将属性值注入到 Bean 中。
区别:
-
使用构造函数依赖注入时,Spring保证所有一个对象所有依赖的对象先实例化后,才实例化这个对象。
-
使用set方法依赖注入时,Spring首先实例化对象,然后才实例化所有依赖的对象。
步骤
- 在 Bean 中提供一个默认的无参构造函数(在没有其他带参构造函数的情况下),并为所有需要注入的属性提供一个 setter() 方法;
- 在applicationContext.xml配置文件中,使用bean标签对bean定义
- 在 property标签对各个属性进行赋值。
2.1基本数据类型
简单数据类型字符串。
<bean id = "user11" class="com.yiwu.pojo.User">
<property name="name" value="张三"></property>
<property name="sex" value="男"></property>
<property name="age" value="22"></property>
</bean>
2.2自定义类型
- 方式1:
<bean name="idcard2" class="com.yiwu.pojo.IdCard">
<property name="code" value="2222222"/>
<property name="id" value="33"/>
</bean>
<bean id = "user12" class="com.yiwu.pojo.User">
<property name="name" value="张三"/>
<property name="sex" value="男"/>
<property name="age" value="22"/>
<property name="idcard" ref="idcard2"/>
</bean>
- 方式2:
<bean id = "user13" class="com.yiwu.pojo.User">
<property name="name" value="张三"/>
<property name="sex" value="男"/>
<property name="age" value="22"/>
<property name="idcard">
<bean class="com.yiwu.pojo.IdCard">
<property name="code" value="2222222"/>
<property name="id" value="33"/>
</bean>
</property>
</bean>
2.3日期类型date
- 方式1:
<bean id="b2" class="java.util.Date">
<constructor-arg name="year" value="10"/>
<constructor-arg name="month" value="11"/>
<constructor-arg name="date" value="2"/>
</bean>
<bean id = "user14" class="com.yiwu.pojo.User">
<property name="name" value="张三"/>
<property name="sex" value="男"/>
<property name="age" value="22"/>
<property name="brithday" ref="b2"/>
</bean>
- 方式2:
<bean id = "user15" class="com.yiwu.pojo.User">
<property name="name" value="张三"/>
<property name="sex" value="男"/>
<property name="age" value="22"/>
<property name="brithday">
<bean class="java.util.Date">
<constructor-arg name="year" value="10"/>
<constructor-arg name="month" value="11"/>
<constructor-arg name="date" value="2"/>
</bean>
</property>
</bean>
2.4集合类型
🔴List
<bean id = "user16" class="com.yiwu.pojo.User">
<property name="product">
<list>
<value>aaa</value>
<value>bbb</value>
<!-- <ref bean="xxxx">-->
<!--<bean class=xxxxx">-->
<!-- <property value="xxx"></property>-->
<!-- </bean>-->
</list>
</property>
</bean>
🔴Set 类型
用法与list一致,仅需要将xml文件中的list标签改为set标签
🔴Map
<bean id = "user17" class="com.yiwu.pojo.User">
<property name="myMap">
<map>
<entry key="k1" value="aaaa"/>
<entry key="k2" value="bbbb"/>
<entry key="k3" value="cccc"/>
</map>
</property>
</bean>
2.5 Properties
<bean id = "user18" class="com.yiwu.pojo.User">
<property name="myProperties">
<props>
<prop key="key1">aaa</prop>
<prop key="key2">aaa</prop>
</props>
</property >
</bean>
3 自动装配
Spring在实例化当前bean的时候自动从Spring容器中找到匹配的实例赋值给当前bean的属性。
创建应用对象之间协作关系的行为称为装配。也就是说当一个对象的属性是另一个对象时,实例化时,需要为这个对象属性进行实例化。这就是装配
依赖注入的本质就是装配,装配是依赖注入的具体行为,这就是两者的关系
创建Product实体类。,在user中添加 Product pd;
package com.yiwu.pojo;
public class Product {
private String name;
private double Price;
public Product() {
}
}
public class User {
Product pd;
//其余省略,与上节内容不变
}
3.1 原始方式
<bean id = "product1" class="com.yiwu.pojo.Product">
<property name="name" value="java"/>
<property name="price" value="20"/>
</bean>
<bean id="user19" class="com.yiwu.pojo.User">
<property name="pd" ref="product1"/>
</bean>
3.2 自动装配
- autowire=“byName”
根据当前Bean的属性名,在Spring容器中寻找匹配的对象,如果根据Name找到了bean,但是类型不匹配则会抛出异常
bean标签的id值与类的属性名一致
<bean id = "pd" class="com.yiwu.pojo.Product">
<property name="name" value="java"/>
<property name="price" value="20"/>
</bean>
<bean id="user19" class="com.yiwu.pojo.User" autowire="byName">
</bean>
- autowire=“byType”
根据当前Bean的属性类型,在spring容器中寻找匹配的对象,如果根据类型找到了多个类型匹配的bean,也会抛出异常。
<bean id = "pd1" class="com.yiwu.pojo.Product">
<property name="name" value="java"/>
<property name="price" value="20"/>
</bean>
<bean id="user19" class="com.yiwu.pojo.User" autowire="byType">
</bean>