1-初识Spring框架

1-初识Spring框架
JavaT一 Spring 介绍
1.1 概述
-
Spring 框架的核心技术
Spring 是由 Rod Johnson 组织和开发的一个分层的 Java SE/EE 一站式(full-stack)轻量级开源框架。它最为核心的理念是 IoC(控制反转)和 AOP(面向切面编程),其中,IoC 是 Spring 的基础,它支撑着 Spring 对 JavaBean 的管理功能;AOP 是 Spring 的重要特性,AOP 是通过预编译方式和运行期间动态代理实现程序功能,也就是说可以在不修改源代码的情况下,给程序统一添加功能。
-
在表现层、业务逻辑层和持久层的作用
-
在表现层它提供了 Spring MVC 框架,并且 Spring 还可以与 Struts 框架整合。
-
在业务逻辑层可以管理事务、记录日志等。
-
在持久层可以整合 MyBatis、Hibernate、JdbcTemplate 等技术。
1.2 Spring 框架的优点
Spring 作为 Java EE 的一个全方位应用程序框架,为开发企业级应用提供了一个健壮、高效的解决方案。它不仅可以应用于 Java 应用的开发,也可以应用于服务器端开发。Spring 之所以得到如此广泛应用,是因为 Spring 框架具有以下几个优点。
-
非侵入式设计
Spring 是一种非侵入式(non-invasive)框架,所谓非侵入式是指 Spring 框架的 API 不会在业务逻辑上出现,也就是说业务逻辑应该是纯净的,不能出现与业务逻辑无关的代码。由于业务逻辑中没有 Spring 的 API,所以业务逻辑代码也可以从 Spring 框架快速地移植到其他框架。
-
降低耦合性
Spring 就是一个大工厂,可以将所有对象的创建和依赖关系的维护工作都交给 Spring 容器管理,大大降低了组件之间的耦合性。
-
支持 AOP 编程
Spring 提供了对 AOP 的支持,AOP 可以将一些通用的任务进行集中处理,如安全、事务和日志等,以减少通过传统 OOP 方法带来的代码冗余和繁杂。
-
支持声明式事务
在 Spring 中,可以直接通过 Spring 配置文件管理数据库事务,省去了手动编程的繁琐,提高了开发效率。
-
方便程序的测试
Spring 提供了对 Junit 的支持,开发人员可以通过 Junit 进行单元测试。
-
方便集成框架
Spring 提供了一个广阔的基础平台,其内部提供了对各种框架的直接支持,如 Struts、Hibernate、MyBatis、Quartz 等,这些优秀框架可以与 Spring 无缝集成。
-
降低 Java EE API 的使用难度
Spring 对 Java EE 开发中的一些 API(如 JDBC、JavaMail 等)都进行了封装,大大降低了这些 API 的使用难度。
1.3 Spring 5 的体系结构
-
体系结构图
-
组成模块
Spring 5 框架主要有七大模块,每个大模块由多个或 1 个小模块组成,如 Spring 的核心容器模块(Core Container)是由 Beans 模块、Core 模块、Context 模块和 SpEL 模块组成。下面结合 String 5 的体系结构图对 Spring 体系结构中的主要模块进行简单介绍。
-
核心容器模块在 Spring 的功能体系中起着支撑性作用,是其他模块的基石。核心容器层主要由 Beans 模块、Core 模块、Contex 模块和 SpEL 模块组成。
- Beans 模块。它提供了 BeanFactory 类,是工厂模式的经典实现,Beans 模块的主要作用是创建和管理 Bean 对象。
- Core 模块。它提供了 Spring 框架的基本组成部分,包括 IoC 和 DI 功能。
- Context 模块。它构建于 Beans 模块和 Core 模块的基础之上,它可以通过 ApplicationContext 接口提供上下文信息。
- SpEL 模块。它是 Spring 3.0 后新增的模块,提供了对 SpEL 表达式语言(Spring Expression Language)的支持,SpEL 表达式语言是一个在程序运行时支持操作对象图的表达式语言。
-
数据访问及集成模块用于访问和操作数据库中的数据,它主要包含 JDBC 模块、ORM 模块、OXM 模块、JMS 模块和 Transactions 模块。
- JDBC 模块。它提供了一个 JDBC 的抽象层,消除了冗长的 JDBC 编码并能够解析数据库供应商特有的错误代码。
- ORM 模块。它为主流的对象关系映射 API 提供了集成层,用于集成主流的对象关系映射框架。
- OXM 模块。它提供了对 XML 映射的抽象层的支持,如 JAXB、Castor 等。
- JMS 模块。它主要用于传递消息,包含消息的生产和消费。自 4.1 版本后,JMS 模块支持与 Spring-message 模块的集成。
- Transactions 模块。它的主要功能是事务管理。
-
Web 模块的实现基于 APPlicationContext 基础之上,它提供了 Web 应用的各种工具类,包括了 Web 模块、Servlet 模块、WebSocket 模块和 Portlet 模块。
-
Web 模块。它提供了针对 Web 开发的集成特性,如大部分文件上传功能等。此外,Web 模块还包含一个 HTTP 客户端和 Spring 远程处理支持的 Web 相关部分。
-
Servlet 模块。它提供了 Spring 的模型、视图、控制器以及 Web 应用程序的 REST Web 服务实现。
-
WebSocket 模块。它是 Spring 4.0 以后新增的模块,它提供了 WebSocket 和 SockJS 的实现,以及对 STOMP 的支持。
-
Portlet 模块。它类似 Servlet 模块的功能,提供了 Portlet 环境下的 MVC 实现。
-
Spring 框架的其他模块还有 AOP 模块、Aspects 模块、Instrumentation 模块以及 Test 模块。
- AOP 模块。它提供了对面向切面编程的支持,程序可以定义方法拦截器和切入点,将代码按照功能进行分离,以降低程序的耦合性。
- Aspects 模块。它提供了与 AspectJ 集成的支持。
- Instrumentation 模块。它提供了对类工具的支持,并且实现了类加载器,该模块可以在特定的应用服务器中使用。
- Messaging 模块。它是 Spring 4.0 以后新增的模块,它提供了对消息传递体系结构和协议的支持。
- Test 模块。它提供了对程序单元测试和集成测试的支持。
-
1.4 Spring 5 的新特性
-
更新 JDK 基线
因为 Spring 5 代码库运行于 JDK 8 之上,所以 Spring 5 对 JDK 的最低要求是 JDK 8,这可以促进 Spring 的使用者积极运用 Java 8 新特性。
-
修订核心框架
- 基于 JDK 8 的反射增强,通过 Spring 5 提供的方法可以更加高效的对类或类的参数进行访问。
- 核心的 Spring 接口提供了基于 JDK 8 的默认方法构建的选择性声明。
- 用@Nullable 和@NotNull 注解来表明可为空的参数以及返回值,可以在编译时处理空值而不是在运行时抛出 NullPointerExceptions 异常。
-
更新核心容器
Spring 5 支持候选组件索引作为类路径扫描的替代方案。从索引读取实体类,会使加载组件索引开销更低,因此,Spring 程序的启动时间将会缩减。
-
支持响应式编程
响应式编程是另外一种编程风格,它专注于构建对事件做出响应的应用程序。Spring 5 包含响应流和 Reactor(ReactiveStream 的 Java 实现),响应流和 Reactor 支撑了 Spring 自身的功能及相关 API。
-
支持函数式 Web 框架
Spring 5 提供了一个函数式 Web 框架。该框架使用函数式编程风格来定义端点,它引入了两个基本组件: HandlerFunction 和 RouterFunction。HandlerFunction 表示处理接收到的请求并生成响应函数;RouterFunction 替代了@RequestMapping 注解,用于将接收到的请求转发到处理函数。
-
支持 Kotlin
Spring 5 提供了对 Kotlin 语言的支持。Kotlin 是一种支持函数式编程风格的面向对象语言,它运行在 JVM 之上,可以让代码更具有表现力、简洁性和可读性。有了对 Kotlin 的支持,开发人员可以进行深度的函数式 Spring 编程,这拓宽了 Spring 的应用领域。
-
提升测试功能
Spring 5 完全支持 Junit 5 Jupiter,因此可以使用 Junit 5 编写测试代码。除此之外,Spring 5 还提供了在 Spring TestContext Framework 中进行并行测试的扩展。针对响应式编程模型,Spring 5 引入了支持 Spring webFlux 的 WebTestClient 集成测试。
二 入门程序
2.1 创建工程
使用 idea 创建一个空的 Maven 工程,在 pom.xml 写入以下内容后更新 Maven
1 |
|
2.2 入门程序
2.2.1 HelloSpring.java
SpringLearn/src/main/java/site/icefox/javaeelearn/learn1/target2/HelloSpring.java
1 | package site.icefox.javaeelearn.learn1.target2; |
2.2.2 TestHelloSpring.java
SpringLearn/src/main/java/site/icefox/javaeelearn/learn1/target2/TestHelloSpring.java
1 | package site.icefox.javaeelearn.learn1.target2; |
2.2.3 applicationContext.xml
SpringLearn/src/main/resources/learn1/target2/applicationContext.xml
1 |
|
2.2.4 测试
现在。你可以在TestHelloSpring.java
文件的行号前面看到一个绿色小三角,点击它尝试运行。
你应该可以看到类似如下的输出
1 | 2024-09-25 18:34:14 327 [main] INFO site.icefox.javaeelearn.learn1.target2.TestHelloSpring - 我是一条日志信息 |
三 控制反转与依赖注入
3.1 控制反转的概念
3.1.1 传统面向对象程序设计原则
控制反转(Inversion of Control,缩写为 IoC)是面向对象编程中的一个设计原则,用来降低程序代码之间的耦合度。在传统面向对象编程中,获取对象的方式是用 new 关键字主动创建一个对象,也就是说应用程序掌握着对象的控制权。
3.1.2 IoC 设计原则
IoC 控制反转机制指的是对象由 Ioc 容器统一管理,当程序需要使用对象时,可以直接从 IoC 容器中获取。这样对象的控制权就从应用程序转移到了 IoC 容器。IoC 设计原则如图,它是借助于 IoC 容器实现具有依赖关系对象之间的解耦,各个对象类封装之后,通过 IoC 容器来关联这些对象类。
3.2 依赖注入的概念
依赖注入(Dependency Inject,缩写 DI)就是由 IoC 容器在运行期间动态地将某种依赖资源注入对象之中。例如,将对象 B 注入(赋值)给对象 A 的成员变量。依赖注入的基本思想是:明确地定义组件接口,独立开发各个组件,然后根据组件的依赖关系组装运行
依赖注入(DI)和控制反转(IoC)是从不同角度来描述了同一件事情。依赖注入是从应用程序的角度描述,即应用程序依赖 IoC 容器创建并注入它所需要的外部资源;而控制反转是从 IoC 容器的角度描述,即 IoC 容器控制应用程序,由 IoC 容器反向地向应用程序注入应用程序所需要的外部资源。这里所说的外部资源可以是外部实例对象,也可以是外部文件对象等
3.3 依赖注入的类型
依赖注入的作用就是在使用 Spring 框架创建对象时,动态的将其所依赖的对象注入到 Bean 组件中。依赖注入通常有两种实现方式,一种是构造方法注入,另一种是属性 setter 方法注入。
3.3.1 解释
-
构造方法注入
是指 Spring 容器调用构造方法注入被依赖的实例,构造方法可以是有参的或者是无参的。Spring 在读取配置信息后,会通过反射方式调用实例的构造方法,如果是有参构造方法,可以在构造方法中传入所需的参数值,最后创建类对象。
-
setter 属性注入
属性 setter 方法注入是 Spring 最主流的注入方法,这种注入方法简单、直观,它是在被注入的类中声明一个 setter 方法,通过 setter 方法的参数注入对应的值。
3.3.2 相关代码
-
SpringLearn/src/main/java/site/icefox/javaeelearn/learn1/target33/Entity/User1.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17package site.icefox.javaeelearn.learn1.target33.Entity;
public class User1 {
private int id;
private String name;
private String password;
public User1(int id, String name, String password) {
this.id = id;
this.name = name;
this.password = password;
}
public String toString() {
return "id=" + id + ",name=" + name + ",password=" + password;
}
} -
SpringLearn/src/main/java/site/icefox/javaeelearn/learn1/target33/Entity/User2.java
1
2
3
4
5
6
7
8
9
10
11package site.icefox.javaeelearn.learn1.target33.Entity;
import lombok.Data;
public class User2 {
private int id;
private String name;
private String password;
} -
SpringLearn/src/main/java/site/icefox/javaeelearn/learn1/target33/TestUser1.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16package site.icefox.javaeelearn.learn1.target33;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import site.icefox.javaeelearn.learn1.target33.Entity.User1;
public class TestUser1 {
public static void main(String[] args)throws Exception{
//加载applicationContext.xml配置
ApplicationContext applicationContext=new
ClassPathXmlApplicationContext("learn1/target33/applicationContext-User.xml");
//获取配置中的User1实例
User1 user1=applicationContext.getBean("user1", User1.class);
System.out.println(user1);
}
} -
SpringLearn/src/main/java/site/icefox/javaeelearn/learn1/target33/TestUser2.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17package site.icefox.javaeelearn.learn1.target33;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import site.icefox.javaeelearn.learn1.target33.Entity.User2;
public class TestUser2 {
public static void main(String[] args) throws Exception {
//加载applicationContext.xml配置
ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("learn1/target33/applicationContext-User2.xml");
//获取配置中的User2实例
User2 user2 = applicationContext.getBean("user2", User2.class);
System.out.println(user2);
}
} -
SpringLearn/src/main/resources/learn1/target33/applicationContext-User.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
<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 id="user1" class="site.icefox.javaeelearn.learn1.target33.Entity.User1">
<constructor-arg name="id" value="1">
</constructor-arg>
<constructor-arg name="name" value="张三">
</constructor-arg>
<constructor-arg name="password" value="123"></constructor-arg>
</bean>
</beans> -
SpringLearn/src/main/resources/learn1/target33/applicationContext-User2.xml
1
2
3
4
5
6
7
8
9
10
11
12
<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 id="user2" class="site.icefox.javaeelearn.learn1.target33.Entity.User2">
<property name="id" value="2"></property>
<property name="name" value="李四"></property>
<property name="password" value="456">
</property>
</bean>
</beans>
3.3.3 测试结果
分别执行TestUser1.main()
和TestUser2.nain()
,应该可以获得如下结果:
-
构造方法注入
1 | site.icefox.javaeelearn.learn1.target33.TestUser1 |
-
setter 方法注入
1 | 2024-09-26 10:36:27 536 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@248e319b |
四 依赖注入的应用
4.1 相关代码
4.1.1 SpringLearn/src/main/java/site/icefox/javaeelearn/learn1/target34/dao/UserDao.java
1 | package site.icefox.javaeelearn.learn1.target34.dao; |
4.1.2 SpringLearn/src/main/java/site/icefox/javaeelearn/learn1/target34/dao/impl/UserDaoImpl.java
1 | package site.icefox.javaeelearn.learn1.target34.dao.impl; |
4.1.3 SpringLearn/src/main/java/site/icefox/javaeelearn/learn1/target34/service/UserService.java
1 | package site.icefox.javaeelearn.learn1.target34.service; |
4.1.4 SpringLearn/src/main/java/site/icefox/javaeelearn/learn1/target34/service/impl/UserServiceImpl.java
1 | package site.icefox.javaeelearn.learn1.target34.service.impl; |
4.1.5 SpringLearn/src/main/java/site/icefox/javaeelearn/learn1/target34/TestSpring.java
1 | package site.icefox.javaeelearn.learn1.target34; |
4.1.6 SpringLearn/src/main/resources/learn1/target34/applicationContext.xml
1 |
|
4.2 测试结果
输出理应如下:
1 | 2024-09-26 10:47:58 430 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@248e319b |
五 小结
本章主要讲解了 Spring 框架的基础知识,首先介绍了 Spring 框架基础知识,包括了 Spring 概述、Spring 框架的优点、Spring 框架的体系结构、Spring 5 的新特性和 Spring 下载及目录结构;然后编写了 Spring 的入门程序;最后讲解了控制反转与依赖注入,包括控制反转的概念、依赖注入的概念、依赖注入的类型和依赖注入的应用。