第二章 Spring IOC
章节内容
- Spring IOC技术实现
- Spring IOC设值注入
- Spring IOC构造注入
章节目标
- 掌握Spring IOC技术实现
- 掌握Spring IOC设置注入
- 掌握Spring IOC构造注入
第一节 Spring简介
1. Spring 简介
Spring 是目前主流的 Java 开发框架,是 Java 世界最为成功的框架。其目的是用于简化企业级应用程序开发的难度和周期,任何 Java 应用都可以从 Spring 中受益。Spring 框架还是一个超级粘合平台,除了自己提供功能外,还提供粘合其他技术和框架的能力。
什么是框架? 框架是一个半成品,提供了基本的运行功能,但具体业务实现需要我们去编写。
2. Spring体系结构
EL = Expression Language 表达式语言
SpEL = Spring Expression Language Spring表达式语言
2.1 Data Access/Integration
Data Access/Integration表示数据访问/集成层,包含了JDBC、ORM、OXM、JMS、Transactions模块。
2.2 Web
Spring 的 Web 层包括 Web、Servlet、WebSocket 和 Portlet 组件。
2.3 Core Container
Spring 的核心容器是其他模块建立的基础,由 Beans 模块、Core 核心模块、Context 上下文模块和 SpEL 表达式语言模块组成,没有这些核心容器,也不可能有 AOP、Web 等上层的功能。
2.4 AOP、Aspects、Instrumentation和Messaging
在 Core Container 之上是 AOP、Aspects 等模块。
2.5 Test模块
第二节 Spring IOC
1. IOC 概念
IOC全称为 Inverse Of Control,表示控制反转。指的是程序员使用硬编码创建的对象转为由Spring容器来创建,对于对象生命周期的控制交给Spring容器来管理。控制反转解决了具有依赖关系的组件之间的强耦合,使得项目形态更加稳健
2. 如何使用 IOC
2.1 依赖包引入
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.11</version>
</dependency>
2.3 创建类
public class User {
}
2.2 编写配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--bean标签表示一个对象-->
<bean name="user" class="com.qf.spring.ioc.model.User" />
</beans>
2.4 编写测试案例
public class BeanTest {
@Test
public void getIocTest(){
//应用上下文使用的是类路径下XML文档作为当前应用上下文
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
//从上下文中根据bean的名称或者ID获取bean对象
User user = context.getBean("user", User.class);
System.out.println(user);
}
}
3. DI概念
DI全称为Dependency Injection,表示依赖注入。指的是在Spring创建对象的同时,为其属性赋值
4. 如何使用 DI
4.1 在类中添加属性
@Data
public class User {
private String username;
private String password;
}
4.2 修改配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--bean标签表示一个对象-->
<bean name="user" class="com.qf.spring.ioc.model.User">
<!--为对象的属性注入值:这里name属性的值必须与set方法保持一致-->
<property name="username" value="admin" />
<property name="password" value="123456" />
</bean>
</beans>
4.3 再次测试
5. 注入方式
5.1 设值注入
设值注入指的是通过set方法为属性注入值。设值注入必须保证存在无参构造,否则将报错。
@Data
public class Student {
private String name;
private String sex;
private int age;
private Date birthday;
}
<!--application.xml-->
<bean name="stu" class="com.qf.spring.ioc.model.Student">
<property name="name" value="张三" />
<property name="age" value="20" />
<property name="sex" value="男" />
<!--这里需要注意:日期类型的默认格式yyyy/MM/dd-->
<property name="birthday" value="2021/10/10" />
</bean>
@Test
public void studentTest(){
//应用上下文使用的是类路径下XML文档作为当前应用上下文
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
//从上下文中根据bean的名称或者ID获取bean对象
Student stu = context.getBean("stu", Student.class);
System.out.println(stu);
}
5.2 构造注入
构造注入指的是通过构造放入为属性注入值。
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private String name;
private String sex;
private int age;
private Date birthday;
}
<!--application.xml-->
<bean name="s" class="com.qf.spring.ioc.model.Student">
<!--这里按照顺序为属性注入值-->
<constructor-arg index="0" value="李四" />
<constructor-arg index="1" value="女" />
<constructor-arg index="2" value="22" />
<constructor-arg index="3" value="2020/05/05" />
</bean>
@Test
public void studentConstructorTest(){
//应用上下文使用的是类路径下XML文档作为当前应用上下文
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
//从上下文中根据bean的名称或者ID获取bean对象
Student stu = context.getBean("s", Student.class);
System.out.println(stu);
}
6. 注入类型
6.1 注入常用数据类型
常用数据类型指8种基本数据类型以及对应的包装类、日期类型、字符串等。
6.2 注入引用数据类型
对于引用数据类型,spring 提供了两种注入值的方式。一种是通过 ref 属性来引用 bean 对象进行值的注入,一种是通过 bean 标签来创建一个 bean 对象进行值的注入。
<property name="" ref="" />
<property name="">
<bean class=""></bean>
</property>
@Data
public class User {
private String username;
private String password;
private UserInfo userInfo;
}
@Data
public class UserInfo {
private int id;
private String name;
private String sex;
private int age;
}
<bean id="info" class="com.qf.spring.ioc.model.UserInfo">
<property name="id" value="1" />
<property name="name" value="张三" />
<property name="sex" value="男" />
<property name="age" value="20" />
</bean>
<!--bean标签表示一个对象-->
<bean name="user" class="com.qf.spring.ioc.model.User">
<!--为对象的属性注入值:这里name属性的值必须与set方法保持一致-->
<property name="username" value="admin" />
<property name="password" value="123456" />
<!--引用id为info的bean对象进行值的注入-->
<property name="userInfo" ref="info" />
</bean>
<bean name="u" class="com.qf.spring.ioc.model.User">
<!--为对象的属性注入值:这里name属性的值必须与set方法保持一致-->
<property name="username" value="admin" />
<property name="password" value="123456" />
<property name="userInfo">
<!--使用bean标签创建一个bean对象进行值的注入-->
<bean class="com.qf.spring.ioc.model.UserInfo">
<property name="id" value="2" />
<property name="name" value="李四" />
<property name="sex" value="女" />
<property name="age" value="22" />
</bean>
</property>
</bean>
6.3 注入数组
spring 提供了 array 标签来进行数组类型的属性值的注入。
@Data
public class Clazz {
private int id;
private String name;
private Student[] students;
}
<bean name="clazz" class="com.qf.spring.ioc.model.Clazz">
<property name="id" value="1" />
<property name="name" value="张三" />
<property name="students">
<array>
<!--引用数据类型 可以使用bean标签创建bean对象注入值-->
<!--<bean class=""></bean>-->
<!--引用数据类型 可以使用ref标签引用bean对象注入值-->
<ref bean="s" />
<ref bean="stu" />
<!--常用数据类型 可以使用value标签直接注入值-->
<!-- <value></value>-->
</array>
</property>
</bean>
6.4 注入集合
6.4.1 List集合
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private String name;
private String sex;
private int age;
private Date birthday;
private List<Double> scores;
}
<bean name="stu" class="com.qf.spring.ioc.model.Student">
<property name="name" value="张三" />
<property name="age" value="20" />
<property name="sex" value="男" />
<!--这里需要注意:日期类型的默认格式yyyy/MM/dd-->
<property name="birthday" value="2021/10/10" />
<property name="scores">
<list>
<value>80.0</value>
<value>90.0</value>
<value>81.0</value>
<value>82.0</value>
</list>
</property>
</bean>
<bean name="s" class="com.qf.spring.ioc.model.Student">
<!--这里按照顺序为属性注入值-->
<constructor-arg index="0" value="李四" />
<constructor-arg index="1" value="女" />
<constructor-arg index="2" value="22" />
<constructor-arg index="3" value="2020/05/05" />
<constructor-arg index="4">
<list>
<value>80.0</value>
<value>90.0</value>
<value>81.0</value>
<value>82.0</value>
</list>
</constructor-arg>
</bean>
6.4.2 Set集合
@Data
public class Person {
private String name;
private Set<String> friendNames;
}
<bean name="p" class="com.qf.spring.ioc.model.Person">
<property name="name" value="李刚" />
<property name="friendNames">
<set>
<value>李四</value>
<value>王五</value>
</set>
</property>
</bean>
6.4.3 注入Map
@Data
public class Person {
private String name;
private List<String> friendNames;
private Map<String, Object> map;
}
<bean name="p" class="com.qf.spring.ioc.model.Person">
<property name="name" value="李刚" />
<property name="friendNames">
<set>
<value>李四</value>
<value>王五</value>
</set>
</property>
<property name="map">
<map>
<entry key="hobby" value="聊天" />
<entry key="clazz" value-ref="clazz"/>
</map>
</property>
<property name="props">
<props>
<prop key="desc">我很帅</prop>
<prop key="secret">我有两个女朋友</prop>
</props>
</property>
</bean>
6.4.4 注入Properties
@Data
public class Person {
private String name;
private List<String> friendNames;
private Properties props;
}
<bean name="p" class="com.qf.spring.ioc.model.Person">
<property name="name" value="李刚" />
<property name="friendNames">
<set>
<value>李四</value>
<value>王五</value>
</set>
</property>
<property name="props">
<props>
<prop key="desc">我很帅</prop>
<prop key="secret">我有两个女朋友</prop>
</props>
</property>
</bean>