1.Spring IOC 与依赖注入课程笔记
课程简介
本节课介绍了 Spring 框架中的核心概念——IOC(控制反转)和 DI(依赖注入)。Spring 是 Java 生态中最重要的框架之一,几乎所有的 Java 项目开发都会使用它。理解 Spring 的 IOC 和 DI 是进入实际开发的关键。
课程重点
- Spring 的快速入门:理解 Spring 框架与传统开发方式的区别。
- Spring IOC 容器的配置:学习通过 XML 配置 Spring IOC 容器。
- 对象实例化与依赖注入:理解如何实例化对象并实现依赖注入。
- Spring 单元测试:如何在 Spring 中进行单元测试。
什么是 IOC(控制反转)
- 定义:IOC(Inversion of Control,控制反转)是一种软件设计理念,它将对象的控制权交给第三方进行管理。
- 现实案例:举例说明生活中的 IOC 控制反转,例如水果摊老板帮你挑选合适的苹果,这就是一种控制反转的应用场景。消费者不再直接控制对象的创建,而是通过代理人来获取对象。
核心概念
- 传统开发中的问题:消费者必须掌握每个对象的细节,并手动创建和管理对象。这增加了耦合度,导致代码复杂且不灵活。
- 引入代理人角色(IOC 容器):引入 IOC 后,对象的创建和管理由一个中间角色(如水果摊老板)负责。消费者只需通过这个中间人来获取对象。
- 容器管理对象:在 Spring 中,IOC 容器相当于一个“冷冻仓库”,负责存储和管理对象。对象的创建、销毁等生命周期管理都交由容器完成。
核心理念
- 解耦:IOC 的目的是降低对象之间的耦合度,消费者与对象之间通过容器进行间接交互。
- 对象灵活性:通过引入代理人,可以让对象的创建和管理变得更加灵活,消费者无需关心对象的创建细节。
什么是 DI(依赖注入)
- 定义:DI(Dependency Injection,依赖注入)是具体实现 IOC 的技术手段。在程序运行时,将对象的依赖关系注入到对象中。
- DI 与 IOC 的关系:IOC 是一种设计理念,而 DI 是实现这种理念的具体技术。DI 的本质是通过反射技术动态创建和设置对象的依赖关系。
- Java 中的 DI 实现:在 Java 中,DI 是通过反射机制实现的,反射可以在运行时动态创建对象、设置属性等。
DI 的应用
- 反射技术:DI 在 Java 中的底层实现依赖于反射技术,利用反射动态创建对象、设置属性并调用方法。
- 跨语言支持:DI 是一种普遍的技术,不仅限于 Java,在其他语言(如 Python、.NET)中也有类似的实现技术。
IOC 与 DI 的区别与联系
- IOC:宏观上的设计理念,强调控制权的反转。
- DI:具体的实现手段,在代码层面实现 IOC 的设计理念。
- Java 实现:在 Java 中,依赖注入的实现是通过反射技术。
课程总结
- IOC 的核心理念:将对象的创建权从消费者转移到代理人(IOC 容器),降低了对象之间的耦合度。
- 容器管理对象:IOC 容器(如 Spring 容器)负责管理所有对象的创建、销毁和生命周期管理。
- DI 的实现:DI 是 IOC 的具体实现手段,在 Java 中通过反射技术动态管理对象的依赖关系。
- Spring 框架中的应用:Spring 框架通过 IOC 和 DI 实现了灵活的对象管理和依赖注入,极大简化了开发工作。
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--bean标签默认通过默认构造方法创建对象-->
<bean id="apple1" class="com.imooc.spring.ioc.entity.Apple">
</bean>
<!--使用带参构造方法实例化对象-->
<bean name="apple2" class="com.imooc.spring.ioc.entity.Apple">
<constructor-arg name="title" value="红富士"/>
<constructor-arg name="color" value="红色"/>
<constructor-arg name="origin" value="欧洲"/>
<constructor-arg name="price" value="19.8"/>
</bean>
<bean id="apple3" class="com.imooc.spring.ioc.entity.Apple">
<constructor-arg index="0" value="红富士"/>
<constructor-arg index="1" value="欧洲"/>
<constructor-arg index="2" value="红色"/>
<constructor-arg index="3" value="19.8"/>
</bean>
<!--利用静态工厂获取对象-->
<bean id="apple4" class="com.imooc.spring.ioc.factory.AppleStaticFactory"
factory-method="createSweetApple"/>
<!--利用工厂实例方法获取对象-->
<bean id="factoryInstance" class="com.imooc.spring.ioc.factory.AppleFactoryInstance"/>
<bean id="apple5" factory-bean="factoryInstance" factory-method="createSweetApple"/>
</beans>
package com.imooc.spring.ioc;
import com.imooc.spring.ioc.entity.Apple;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringApplication {
public static void main(String[] args) {
String[] configLocations = new String[]{
"classpath:applicationContext.xml","classpath:applicationContext-1.xml"};
//初始化IoC容器并实例化对象
ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
/*Apple apple4 = context.getBean("apple4", Apple.class);
System.out.println(apple4.getTitle());
Apple apple3 = (Apple)context.getBean("apple3");
System.out.println(apple3.getTitle());*/
Apple apple2 = context.getBean("apple2", Apple.class);
System.out.println(apple2.getTitle());
Apple apple7 = context.getBean("apple7", Apple.class);
System.out.println(apple7.getTitle());
Apple apple = context.getBean("com.imooc.spring.ioc.entity.Apple", Apple.class);
System.out.println(apple.getTitle());
}
}
2.Spring IOC 容器中的依赖注入
2. 1. 依赖注入的概念
依赖注入是将对象之间的依赖关系通过Spring IOC容器动态注入,而不是通过代码中的 new
来创建依赖对象。
依赖注入的两种形式
- 基于Setter方法注入:通过Setter方法为对象的属性注入依赖。
- 基于构造方法注入:通过构造方法为对象注入依赖。
2.2. Setter方法注入对象
2.1 静态数值的注入
-
使用
property
标签进行属性的静态值注入。 -
property
标签的两个属性:name
:表示类中属性的名称。value
:表示属性的值。
例如,为
apple
对象的title
属性赋值为sweet apple
:<bean id="sweetApple" class="com.example.Apple"> <property name="title" value="红富士" /> <property name="color" value="红色" /> <property name="origin" value="欧洲" /> </bean>
-
注意:静态数值也能作为对象注入,因为在Java中,
String
和基本类型都有对应的包装类,可以作为对象处理。
2.2 测试Setter方法注入
在测试时,可以通过设置断点或在Setter方法中打印调试信息,验证Spring通过反射调用 set
方法为属性赋值。
例如:
public void setTitle(String title) {
System.out.println("Title属性设置为:" + title);
this.title = title;
}
3. Setter方法注入对象依赖
除了静态数值的注入,还可以通过Setter方法注入其他对象。