本文纲要
Spring到底是什么?为什么要学它?
1.1Spring的地位与优势
1.2Spring家族与学习重点
1.3Spring Framework的系统架构- 两个核心概念:
IoC与DI
2.1 传统开发中的耦合问题
2.2IoC:控制反转
2.3DI:依赖注入 IoC入门案例:让Spring管理对象
3.1 项目结构一览
3.2 第一步:导入Spring坐标
3.3 第二步:创建Spring配置文件并声明Bean
3.4 第三步:获取IoC容器并取出Bean
3.5 完整代码展示与运行DI入门案例:解耦依赖关系
4.1 案例思路分析
4.2 改造Service实现类
4.3 在配置中绑定依赖关系
4.4 完整代码展示与运行- 总结
Spring 到底是什么?为什么要学它?
1 ) Spring 的地位与优势
在 Java 企业级开发领域,Spring 已经是事实上的标准。超过 90% 的项目都会采用 Spring 技术栈,如果你从事 Java 后端开发,Spring 几乎是一项必备技能。
它之所以如此流行,是因为它解决了两个根本性问题:
| 优势 | 说明 |
|---|---|
| 简化开发 | 降低企业级应用开发的复杂度,让开发者用更少的代码完成更多工作 |
| 框架整合 | 能够无缝整合市面上主流的框架(如 MyBatis、Struts、MyBatis-Plus 等),避免因框架堆砌造成的“组合爆炸” |
Spring 既能让开发变得更简单、高效,又能充当整个项目技术栈的“粘合剂”,这正是它不可替代的原因。
2 ) Spring 家族与学习重点
Spring 并非一个单一的技术,而是一个庞大的家族——常被称为 Spring 全家桶。官网将所有项目罗列在 spring.io/projects 中,其中最核心的三个项目是:
- Spring Framework:最早、最基础的项目,本课程的核心,提供 IoC、AOP、事务等基石能力。
- Spring Boot:在 Spring Framework 之上进一步简化配置,用于快速搭建应用。
- Spring Cloud:面向分布式、微服务架构的一站式解决方案。
本文的重点就是 Spring Framework,它是其它所有项目的底层支撑。
3 ) Spring Framework 的系统架构
Spring Framework 的架构经过多年演进,已非常稳定。其核心模块如下:
各模块职责简述:
| 模块 | 作用 |
|---|---|
| Core Container(核心容器) | 管理对象(Bean)的创建、初始化及生命周期,是整个框架的基础 |
| AOP | 面向切面编程,在不修改原代码的情况下增强功能;整合了 AspectJ |
| Data Access / Integration | 数据层技术,包含 JDBC、事务(Transaction)以及与 MyBatis 等框架的集成 |
| Web | 提供 Web 开发能力(后续 Spring MVC 课程会深入) |
| Test | 方便进行单元测试与集成测试 |
4 )学习路线
依据以上架构,我们推荐的掌握顺序是:
- 核心容器 → 掌握 IoC 和 DI 的概念与使用
- 数据访问与集成 → 整合 MyBatis
- AOP → 掌握面向切面编程
- 事务处理 → 基于 AOP 的声明式事务
- 测试 & Web 后续再聊
今天我们先扎进最核心的部分:IoC 与 DI
两个核心概念:IoC 与 DI
1 ) 传统开发中的耦合问题
看一段普通的业务层代码:
public class BookServiceImpl implements BookService {
private BookDao bookDao = new BookDaoImpl(); // 直接 new 具体实现
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
这种做法存在明显的 高耦合 问题:如果以后想替换 BookDaoImpl 为另一个实现,就必须修改源代码,然后重新编译、测试、部署,代价很高。根本原因就是我们自己在类中 主动创建了依赖对象。
2 ) IoC:控制反转
为了解决上述问题,我们提出一个思路:对象不要由使用方主动 new,而是交给一个“外部”来提供。这种将对象创建的控制权从程序内部转移到外部的思想,就是 IoC(Inverse of Control,控制反转)。
Spring 对 IoC 进行了落地实现:它提供一个 IoC 容器(又称 Spring 容器),充当那个“外部”。
容器负责创建、初始化对象,并将这些对象称为 Bean。
IoC / IoC 容器 / Bean 三者的关系:
- IoC 是一种思想
- IoC 容器是 Spring 提供的具体实现
- Bean 就是容器管理的对象
3 ) DI:依赖注入
仅仅管理 Bean 还不够。BookServiceImpl 在运行时仍然需要 BookDao 对象,否则会报 NullPointerException。IoC 容器既然已经管理了 BookServiceImpl 和 BookDao 两个 Bean,就可以 自动把后者注入到前者中。这种在容器中绑定 Bean 之间依赖关系的行为,称为 DI(Dependency Injection,依赖注入)。
IoC + DI 协同工作:容器不仅帮你创建对象,还会把对象需要的依赖自动注入,实现 充分解耦。
IoC 入门案例:让 Spring 管理对象
下面我们用一个简单的 BookDao 和 BookService 案例,演示 IoC 的具体使用。
1 ) 项目结构一览
spring01quickstart
├── pom.xml
└── src
├── main
│ ├── java/com/wb
│ │ ├── App.java
│ │ ├── App2.java
│ │ ├── dao
│ │ │ ├── BookDao.java
│ │ │ └── impl
│ │ │ └── BookDaoImpl.java
│ │ └── service
│ │ ├── BookService.java
│ │ └── impl
│ │ └── BookServiceImpl.java
│ └── resources
│ └── applicationContext.xml
└── test
2 ) 第一步:导入 Spring 坐标
在 pom.xml 中添加 spring-context 依赖:
<!-- pom.xml -->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
只有导入了 Spring 相关依赖,IDEA 等工具才会提供 Spring 配置文件的模板。
3 ) 第二步:创建 Spring 配置文件并声明 Bean
在 src/main/resources 下新建 applicationContext.xml,编写如下内容:
<?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">
<!-- 配置 Dao Bean -->
<bean id="bookDao" class="com.wb.dao.impl.BookDaoImpl"/>
<!-- 配置 Service Bean -->
<bean id="bookService" class="com.wb.service.impl.BookServiceImpl"/>
</beans>
<bean>标签:声明一个受 Spring 管理的 Beanid属性:给 Bean 起一个唯一标识,用于后续获取class属性:指定实现类的全限定名(不能是接口)
4 ) 第三步:获取 IoC 容器并取出 Bean
编写 App2.java 来测试:
package com.wb;
import com.wb.dao.BookDao;
import com.wb.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App2 {
public static void main(String[] args) {
// 1. 获取 IoC 容器:加载配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 2. 获取 Bean(根据 id 获取)
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
BookService bookService = (BookService) ctx.getBean("bookService");
bookService.save();
}
}
此时运行,你会发现 BookDao 的 save() 正常执行,但 BookService 会抛出 NullPointerException,因为 Service 里的 bookDao 还没有注入。
5 ) 运行结果
book dao save ...
Exception in thread "main" java.lang.NullPointerException
仅 IoC 还不够,必须配合 DI 才能让 Service 真正工作。
DI 入门案例:解耦依赖关系
1 ) 案例思路分析
要让 BookServiceImpl 能用上 BookDao 的对象,需要完成三件事:
- 删除 Service 实现类中
new BookDaoImpl()的硬编码; - 在 Service 实现类中 提供 setter 方法,让容器能把 Dao 对象传进来;
- 在配置文件中 描述 Service 与 Dao 的依赖关系。
2 ) 改造 Service 实现类
package com.wb.service.impl;
import com.wb.dao.BookDao;
import com.wb.service.BookService;
public class BookServiceImpl implements BookService {
// 不再 new,只声明接口
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
// 提供 setter 方法,供容器注入
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
}
3 ) 在配置中绑定依赖关系
修改 applicationContext.xml,在 Service 的 <bean> 标签内添加 <property> :
<bean id="bookDao" class="com.wb.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.wb.service.impl.BookServiceImpl">
<!-- 注入依赖:name 对应属性名,ref 引用容器中的另一个 Bean -->
<property name="bookDao" ref="bookDao"/>
</bean>
name:Service 中定义的属性名(bookDao)ref:指向已经配置的 Bean 的id(同样是bookDao,但含义不同)- Spring 容器会自动调用
setBookDao()方法,将对应的 Bean 传入。
4 ) 完整代码展示与运行
再次运行 App2 :
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookService bookService = (BookService) ctx.getBean("bookService");
bookService.save();
}
运行结果:
book service save ...
book dao save ...
到此,Service 与 Dao 实现了完全解耦,所有对象都由 IoC 容器管理,依赖关系由容器注入。
总结
通过本篇文章,我们完成了 Spring 中最基础、最核心的 IoC 与 DI 入门:
IoC(控制反转):将对象的创建权交给容器,而不是由程序自身 new。DI(依赖注入):容器自动为 Bean 注入它所需要的其他 Bean。- 入门实践:
- 导入
spring-context依赖; - 在
applicationContext.xml中声明 Bean; - 通过
ApplicationContext获取容器,再通过getBean()拿到对象; - 使用
<property>+setter方法实现依赖注入。
- 导入
掌握这两个概念之后,后续学习 AOP、事务、整合 MyBatis 等内容都会更加顺畅。
Spring 的世界刚刚打开,下一站我们将深入 Bean 配置与生命周期。欢迎持续关注!
1597

被折叠的 条评论
为什么被折叠?



