Spring框架教程:Spring入门
尽管Spring框架常被认为过时,但它仍然是全球企业广泛使用的热门应用开发工具。Spring提供无与伦比的控制力、一流的安全性以及使用Spring Beans的省时依赖关系管理系统。
然而,由于 Spring 的选项众多且工具集复杂,因此它也出了名的难学。
今天,我们将通过一篇入门教程,帮助你开启 Spring 开发之旅,了解 Spring 的使用方法和意义。最后,我们甚至会指导你完成你的第一个 Spring 作品集项目。
今天我们将讨论以下内容:
用一半的时间学会春天
通过实践课程,快速掌握专业级弹簧技术。
Spring框架是什么?
Spring 是一个轻量级的开源应用程序开发框架,它使用 Java 企业版 (Java EE) 和企业 JavaBeans 模型 (EJB)。
Spring 通常被认为是“框架之框架”,因为它支持 Java 生态系统中的其他集成框架,例如 Struts、Hibernate 和 Tapestry。Spring 有许多针对特定用途的变体,例如 Spring MVC、Spring Boot 和 Spring Security。
Spring 框架以其依赖注入和控制反转 (IoC) 系统而闻名,使用户能够轻松创建大规模、松耦合的应用程序。Spring 框架尤其适用于金融和企业级应用程序,因为它速度快、安全性高,并且易于构建事务系统。Spring 开发人员的主要雇主包括花旗银行、eBay、Visa 和摩根大通。
总的来说,Spring Framework 允许您创建安全可靠的企业级应用程序,并能自动处理维护容器生命周期和管理依赖项等底层功能。
春季的优势
- 普通Java对象(POJO):Spring应用程序仅使用普通的Java对象,而不是服务器或企业级容器。这使得应用程序更加轻量级。
- 模块化IoC 和MVC架构允许您在应用程序中重用组件,而无需手动管理每个组件的依赖关系。
- 对 Java 生态系统的强大支持:Spring 创新性地利用了现有技术,例如 ORM 框架、JEE 和 JDK 定时器。
- 可扩展事务:Spring 为本地事务和全局事务提供了一致且可扩展的事务管理接口,其中包括缓存协议。
- 安全:易于实现具有身份验证和验证功能的安全模块。
- 灵活的配置方式:可以选择使用基于 Java 的注解或 XML 配置。
春季的缺点
- 复杂性:Spring框架注重控制和复杂性,而非易用性。因此,Spring比其他Web框架更难上手。虽然功能强大,但Spring最适合能够应对其陡峭学习曲线的经验丰富的开发人员。
- 并行机制:Spring 丰富的选项意味着同一个任务可以用多种方式完成。你需要对可用工具有深入的了解,才能选择理想的解决方案,避免跨团队沟通混乱。
- 文档不完善:Spring 的文档在许多方面缺乏清晰的指导,尤其是在网络安全技术方面。用户需要自行应对常见的攻击,例如跨站请求伪造 (CSF) 和脚本攻击。> Spring Boot 模块的出现解决了许多此类缺点,它具有很强的规范性,专为微服务架构而设计。> > 大多数现代 Spring 应用程序都基于 Boot 构建,但仍有许多老牌公司维护着一些较旧的 Spring 应用程序。
春季的特点
- 控制反转 (IoC):将依赖项的管理责任从对象转移到框架本身。如果没有 IoC,每个对象都必须自行处理依赖项实例。有了 IoC,对象只需列出它需要的依赖项,框架就会自动配置和管理。这通过整合依赖系统并减少单个类的工作负载,简化了应用程序开发过程。
- 面向切面编程:Spring AOP 允许您使用不同的类加载器来提高模块化程度并分离横切关注点。
- 依赖注入:Spring 用于自动管理 bean 依赖项的过程。Spring 会检查特定 bean 运行所需的 bean,并将它们作为依赖项注入。Spring 可以通过构造函数或 setter 方法执行依赖注入。
- 容器生命周期管理:自动创建、管理和配置应用程序对象。
- MVC 支持:支持 MVC Web 架构,该架构将功能分离到模型、视图和控制器层。
- 错误处理:包括具有异常层次结构的 JDBC 异常处理。
Spring架构和组件
让我们来分解 Spring Framework 应用程序的基本组成部分,以帮助您了解全局。
豆子
Spring Bean 是由 Spring 管理的类的实例。它们是 Spring 程序中最基本的组成部分。
传统上,对象会创建其依赖项的独立实例。Spring 管理对象的所有依赖项,并在注入所需依赖项后将对象实例化为 bean。注解@Component是定义 bean 最常用的方法。
@Component
public class Vehicle {
}
Bean 的生命周期和可见性取决于其作用域。作用域共有六种类型:单例、原型、请求、会话、应用程序和 WebSocket。单例和原型作用域可用于任何应用程序,而后四种作用域仅适用于 Web 应用程序。
Bean 的默认作用域是单例,即只会创建一个 Bean 实例并将其缓存在内存中。多次请求同一个 Bean 会返回对同一个 Bean 的共享引用。相比之下,原型作用域会在每次向应用程序上下文发出 Bean 请求时创建新的 Bean。
汽车线路
Spring 实现 bean 相互注入的方法。Spring 会识别选定 bean 的依赖关系,查找匹配项,然后填充依赖项。注解指示@AutowiredSpring 查找并向另一个 bean 注入协作 bean。如果存在多个相同类型的 bean,Spring 将抛出错误。
在以下场景中,Spring 检测到了两个类型为 Operator 的 bean:
@Component
class Arithmetic(){
@Autowired
private Operator operator;
//...
}
@Component
class Addition implements Operator {
}
@Component
class Subtraction implements Operator {
}
IoC容器
IoC容器是一个提供控制反转功能的框架。IoC容器管理Bean并创建所需的任何实例。
例如,假设我们有一个类Vehicle依赖于另一个类,Engine。
class Vehicle{
private Engine engine;
//...
}
使用 IoC,程序员只需指定依赖项,Spring 就会完成其余工作。IoC 容器会创建这两个类的实例,并将其作为依赖项注入Engine到 Spring 中。Vehicle
Spring 模块和 Spring 项目
模块是按预期功能分组的工具集合。开发人员可以指定除基本模块集之外,他们希望将哪些模块作为依赖项导入到任何给定的应用程序中。
模块按项目分组组织。每个项目包含专门针对特定平台或应用程序类型的模块。项目和模块系统有助于保持程序轻量级,因为您可以选择仅加载应用程序中使用的工具。
下面按层级分组展示了 Spring 项目基本架构的各个模块:
Spring Core Container 包含使用 Spring 所必需的四个模块:Beans、Core、Context 和 Spring Expression Language (SpEL)。这些模块负责 Spring 框架的基本功能,例如控制反转 (IoC)、依赖注入、国际化以及对运行时对象查询的支持。
Spring Data 访问/集成层提供与数据库交互和数据管理的支持。它包含 4 个主要部分:
- Java 数据库连接 (JDBC)模块允许数据层获取、存储数据或与其他系统交互,而无需编写繁琐的独立 JDBC 代码。
- 对象关系映射(ORM)模块,使你的 Spring Web 应用程序能够与 ORM 框架进行交互。
- Java消息服务(JMS) 模块允许 Spring 生成自己的消息并从其他系统接收消息。这对于响应式应用程序至关重要。
- 对象-XML 映射(OXM) 模块提供了一些有用的功能,使对象到 XML 文件的转换变得容易。
Web 层包含用于创建 Web 应用程序的 Web、Servlet、Portlet 和 Sockets 模块。
测试模块解决了单元测试这一横切关注点。Spring 测试框架支持使用 JUnit 和 TestNG 进行测试,还可以创建模拟对象来隔离测试代码。
AOP 模块提供面向切面编程 (AOP) 的功能,例如方法拦截、切入点、安全性和日志记录。Spring 拥有自己的 Spring AOP 模块,提供基本的面向切面编程功能。更高级的 AOP 功能可以通过与 AspectJ 集成来实现。AOP 的特点是业务逻辑中存在横切关注点。
除了这个基础项目之外,Spring 还包含了涵盖所有主要用例的项目。这些项目包含一些模块,这些模块对于基础项目来说过于小众,但却包含了对目标用途极其宝贵的 API 和功能。
例如,Spring Cloud 支持开发可动态配置和部署的云原生应用程序,并提供处理分布式系统中常见模式的功能。其他项目包括 Spring Boot、Spring Security、Spring DAO、Spring Context 等等。
继续学习Spring框架。
通过构建实际项目快速学习 Spring,这些项目会向您展示如何以及为何使用新技能。Educative 的文字课程易于浏览,并提供实时编码环境,帮助您按自己的节奏获得持久的学习效果。
开始使用 Spring
现在我们将带你亲自动手开发你的第一个 Spring 应用:一个简单的电影推荐系统。
使用 Spring 框架搭建一个新项目比较困难,因为你需要手动配置整个架构,包括使用哪些 Apache Maven 依赖项、使用 XML 还是 Java,以及安装像 Tomcat 这样的 Web 服务器。
相反,我们将使用 Spring Boot 项目来自动化大部分设置过程,并使用其内置的 Web 服务器。
如何启动你的项目
我们将使用 Spring Initializr,通过其简单的选择菜单快速创建一个 Spring Boot 项目。
首先,前往start.spring.io。你会看到一个类似下图的菜单界面,其中包含设置选项和元数据字段。
在这个项目中,我们将选择“Maven 项目”,选择 Java 作为编程语言,并选择最新版本的 Spring Boot。暂时避免使用“SNAPSHOT”版本,因为这些版本正处于 alpha 或 beta 测试阶段。在“项目元数据”下,分别输入io.datajek.springbasics“GroupID”和movie-recommmender-system“ArtifactID”。Group ID 和 Artifact ID 分别对应包名和类名。通常情况下,您需要在“依赖项”下添加模块依赖,但本项目仅需要默认的 Spring 工具。
输入所有信息后,点击“生成”按钮,创建一个包含架构设置的 zip 文件。将该文件夹解压缩到硬盘上的指定位置。该文件夹将包含一个pom.xml可导入Eclipse IDE 的文件。
稍等片刻,您将看到以下层级结构:
src/main/javaJava 代码将在此处编写src/main/resources应用程序属性写入的位置src/test/java测试将在此处编写。现在您可以右键单击MovieRecommenderSystemApplication.java并将其作为 Java 应用程序运行,以生成以下控制台输出。
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.4.RELEASE)
2021-05-03 22:46:15.549 INFO 78 --- [ main] .b.m.d.MovieRecommenderSystemApplication : Starting MovieRecommenderSystemApplication v0.0.1-SNAPSHOT on b041f076fcbd with PID 78 (/Code/movie-recommender-system/target/movie-recommender-system-0.0.1-SNAPSHOT.jar started by root in /Code/movie-recommender-system/target)
2021-05-03 22:46:15.563 INFO 78 --- [ main] .b.m.d.MovieRecommenderSystemApplication : No active profile set, falling back to default profiles: default
2021-05-03 22:46:16.458 INFO 78 --- [ main] .b.m.d.MovieRecommenderSystemApplication : Started MovieRecommenderSystemApplication in 1.41 seconds (JVM running for 1.855)
恭喜,您已经使用 Spring Boot 设置了您的第一个 Spring 应用程序!
添加依赖项
现在,我们将使用 Spring 的依赖系统实现一个简单的电影推荐器。该程序会接收一个电影标题作为输入,并返回三个同类型的电影标题。目前,我们将输出硬编码,以便您可以专注于学习程序的结构。
src/main/java首先,在名为 . 的类中创建一个新类RecommenderImplementation。
接下来,我们将添加该recommendMovies方法RecommenderImplementation。该recommendMovies方法将接受一个字符串类型的电影标题作为输入,并返回一个字符串数组,其中包含三个推荐电影。
请使用以下硬编码实现:
public String[] recommendMovies (String movie) {
//use content based filter to find similar movies
//return the results
return new String[] {"M1", "M2", "M3"};
}
RecommenderImplementation现在,在文件中创建该类的实例MovieRecommenderSystemApplication,然后recommendMovies通过RecommenderImplementation该类调用该方法。
public static void main(String[] args) {
RecommenderImplementation recommender = new
RecommenderImplementation();
String[] result = recommender.recommendMovies("Finding Dory");
System.out.println(result);
}
接下来,我们将实现基于内容的过滤来生成推荐。为了保持recommendMovies过滤逻辑的独立性,我们将创建一个名为 `<class_name>` 的新类,ContentBasedFilter并在其中添加一个名为 `<method_name>` 的方法getRecommendations。您可以在此方法中实现复杂的过滤,例如查看观看历史、用户匹配评分等相关数据。请记住这些思路,以便在完成本教程后继续扩展此项目。
目前,我们将硬编码getRecommendations,使其返回相同的三个电影。
public String[] getRecommendations(String movie) {
//logic of content based filter
return new String[] {"Happy Feet", "Ice Age", "Shark Tale"};
}
ContentBasedFilter现在我们可以在类中使用该类的方法了RecommenderImplementation。请将之前硬编码的实现替换recommendMovies为以下基于依赖关系的实现。
public String[] recommendMovies(String movie) {
ContentBasedFilter filter = new ContentBasedFilter();
String[] results = filter.getRecommendations("Finding Dory");
return results;
}
最后,我们将toString为该方法添加一个子方法main,使字符串数组能够作为输出易于阅读。
你的程序现在看起来会像这样:
package io.datajek.spring.basics.movierecommendersystem.lesson1;
import java.util.Arrays;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MovieRecommenderSystemApplication {
public static void main(String[] args) {
//SpringApplication.run(MovieRecommenderSystemApplication.class, args);
//create object of RecommenderImplementation class
RecommenderImplementation recommender = new RecommenderImplementation();
//call method to get recommendations
String[] result = recommender.recommendMovies("Finding Dory");
//display results
System.out.println(Arrays.toString(result));
}
}
package io.datajek.spring.basics.movierecommendersystem.lesson1;
public class RecommenderImplementation {
public String [] recommendMovies (String movie) {
//use content-based filter to find similar movies
ContentBasedFilter filter = new ContentBasedFilter();
String[] results = filter.getRecommendations("Finding Dory");
//return the results
//return new String[] {"M1", "M2", "M3"};
return results;
}
}
package io.datajek.spring.basics.movierecommendersystem.lesson1;
public class ContentBasedFilter {
public String[] getRecommendations(String movie) {
//implement logic of content-based filter
//return movie recommendations
return new String[] {"Happy Feet", "Ice Age", "Shark Tale"};
}
}
当前的实现方式耦合性很强,因为该类RecommenderImplementation依赖于其他组件才能ContentBasedFilter正常工作。现在,我们将解耦这些组件,以支持多种过滤类型,例如…… CollaborativeFilter。我们将使用一个抽象Filter接口,并根据所选的过滤类型提供不同的实现。
Spring 通过自动创建和管理每个组件的依赖实例,简化了这一过程。它会自动检测类之间的依赖关系,这意味着您可以专注于代码编写。
解耦后的项目将如下所示:
package io.datajek.spring.basics.movierecommendersystem.lesson2;
import java.util.Arrays;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MovieRecommenderSystemApplication {
public static void main(String[] args) {
//SpringApplication.run(MovieRecommenderSystemApplication.class, args);
//passing name of the filter as constructor argument
RecommenderImplementation recommender = new RecommenderImplementation(new ContentBasedFilter());
//call method to get recommendations
String[] result = recommender.recommendMovies("Finding Dory");
//display results
System.out.println(Arrays.toString(result));
}
}
package io.datajek.spring.basics.movierecommendersystem.lesson2;
public class CollaborativeFilter implements Filter{
public String[] getRecommendations(String movie) {
//logic of content based filter
return new String[] {"Finding Nemo", "Ice Age", "Toy Story"};
}
}
package io.datajek.spring.basics.movierecommendersystem.lesson2;
public class ContentBasedFilter implements Filter{
public String[] getRecommendations(String movie) {
//implement logic of content-based filter
//return movie recommendations
return new String[] {"Happy Feet", "Ice Age", "Shark Tale"};
}
}
package io.datajek.spring.basics.movierecommendersystem.lesson2;
public class RecommenderImplementation {
//use filter interface to select filter
private Filter filter;
public RecommenderImplementation(Filter filter) {
super();
this.filter = filter;
}
//use a filter to find recommendations
public String [] recommendMovies (String movie) {
//print the name of interface implementation being used
System.out.println("Name of the filter in use: " + filter + "\n");
String[] results = filter.getRecommendations("Finding Dory");
return results;
}
}
package io.datajek.spring.basics.movierecommendersystem.lesson2;
public interface Filter {
public String[] getRecommendations(String movie);
}
接下来要学习的Spring高级概念
恭喜你完成了第一个解耦的 Spring 应用!随着你不断学习更高级的 Spring 概念,不妨回到这个项目,实现更复杂的过滤器和功能。这将有助于你巩固所学知识,并在面试时为你提供一个可以作为作品集的项目。
以下是一些可以应用于本项目的新概念:
- 实现高级自动接线
- 利用 Bean 范围优化资源管理
- 使用 Spring Web MVC 框架将其转换为 Web 应用程序
- 使用 BeanFactory 设计模式创建自修复系统
- 使用 Hibernate 模板和 Java 持久化 API (JPA) 添加关系数据库支持
为了帮助您学习这些概念并将其应用到本项目中,Educative 编写了《Spring 5 和 Spring Boot 2 完全指南》。本课程将引导您了解 Spring 框架的所有高级特性,并演示如何在项目环境中使用它们。课程结束时,您将获得所有这些主题的实践经验,并掌握在面试中脱颖而出所需的 Spring 相关知识。