写点什么

Spring Web 应用的最大瑕疵

  • 2013-11-08
  • 本文字数:2065 字

    阅读完需:约 7 分钟

众所周知, 现在的 Spring 框架已经成为构建企业级 Java 应用事实上的标准了,众多的企业项目都构建在 Spring 项目及其子项目之上,特别是 Java Web 项目,很多都使用了 Spring 并且遵循着 Web、Service、Dao 这样的分层原则,下层向上层提供服务;不过 Petri Kainulainen 在其博客中却指出了众多 Spring Web 应用的最大瑕疵,请继续阅读看看文中所提到的问题是否也出现在你的项目当中。

使用 Spring 框架构建应用的开发者很乐于谈论依赖注入的好处。但遗憾的是,他们很多人并没有在其应用中很好地利用其优势,如单一职责原则关注分离原则。如果仔细看看基于 Spring 的 Web 应用,你会发现很多都是使用如下这些常见且错误的设计原则来实现的:

  • 领域模型对象只是用来存储应用的数据。换句话说,领域模型使用了贫血模型这种反模式。
  • 业务逻辑位于服务层中,管理域对象的数据。
  • 在服务层中,应用的每个实体对应一个服务类。

可问题是:如果这种做法很普遍,那为什么说是不对的呢?下面来阐述一下。

旧习难改

Spring Web 应用之所以看起来是这个样子原因在于这是人们长久以来的做法,旧习难改,特别是在高级开发者或是软件架构师强制开发人员这样做的时候。问题在于这些人非常擅于捍卫自己的观点。他们喜欢的一个论调就是应用应该遵循关注分离原则,因为它被划分成了几个层次,每个层次都有自己具体的职责。

一个典型的 Spring Web 应用会有如下几个层次:

  • Web 层:负责处理用户的输入并向用户返回正确的响应。Web 层只会与服务层通信。
  • 服务层:作为事务边界。它还负责授权并包含了应用的业务逻辑。服务层管理着领域对象模型并且与其他服务及存储层通信。
  • 存储 / 数据访问层:负责与所用的数据存储进行通信。

关注分离原则的定义是这样的:关注分离(Soc)是一种将计算机程序划分到不同部分的一种设计原则,这样每一部分都会有单独的关注点。虽然一个典型的 Spring Web 应用也在一定程度上遵循了这个原则,不过实际情况却是应用拥有一个整体的服务层,它包含了太多的职责了。更具体一些,服务层主要有两个问题:

首先,应用的业务逻辑来自于服务层。

这是个问题,因为业务逻辑散落在服务层。如果需要查看某个业务规则是如何实现的,我们需要先找到它才行,这可不是那么轻松的事情。此外,如果有多个服务类都需要相同的业务规则,那么开发人员很可能会将这个业务规则从一个服务复制到另一个服务中,这会导致维护的梦魇。

其次,每个领域模型类在服务层中都有一个服务类。

这违背了单一职责原则:单一职责原则表明每个类都应该只有一个职责,这个职责应该完全被这个类所封装。它的所有服务都应该与这个职责保持一致。

服务类存在大量的依赖和大量的循环依赖。一个典型的 Spring Web 应用的服务层没有包含只拥有一个职责的松耦合的服务,它更像是一个紧耦合的大量服务的集合。这使得它很难理解、维护与重用。看起来有点苛刻,不过服务层经常是 Spring Web 应用最容易出现问题的一环。幸好对我们来说还存在着希望。

推翻

目前的状况并不好,不过也不是完全没有希望的。下面我们来看看如何打破旧有的习惯。

首先,我们需要将应用的业务逻辑从服务层移动到领域模型类中。

为何要这么做呢,看看下面这个例子:

假设我是个服务类,你是个领域模型对象。如果我告诉你从房顶跳下来,那么你是否会拒绝呢?

将服务层的业务逻辑移动到领域模型类中有如下 3 个好处:

  • 根据合理的方式划分代码的职责。服务层会负责应用的逻辑,而领域模型类则负责业务逻辑。
  • 应用的业务逻辑只会位于一处。如果需要验证特定的业务规则是如何实现的,我们总是知道该去哪里寻找。
  • 服务层的源代码将会变得更加整洁,再不会包含任何复制粘贴的代码了。

其次,我们需要将特定于实体的服务划分为更小的服务,每个服务只有一个目标。

比如说,如果应用有一个服务类,它为与用户帐户相关的人与操作提供了 CRUD 操作,那么我们就应该将其划分到两个单独的服务类中:

  • 第 1 个服务提供人的 CRUD 操作。
  • 第 2 个服务提供与用户帐户相关的操作。

这么做有如下 3 个好处:

  • 每个服务类都有一套合理的职责。
  • 每个服务类的依赖会更少,这意味着他们不再是紧耦合的庞然大物了。他们是更加小巧且松耦合的组件。
  • 服务类更易于理解、维护与重用。

这两个简单的步骤可以帮助我们清理应用的架构,提升开发者的生产力和幸福度。现在,我们想知道如果所有这些都是必要的,那么该何时解决这些问题呢?

有时生命是黑白的

我经常听到有人说我们不应该过多的关注于“架构”,因为我们的应用很小并且很简单。虽然这个论调有一定的正确性,不过我们必须要记住一开始很小的项目最后会变得很大。如果不考虑这种情况,那么一旦发生状况,我们就会陷入到巨大的麻烦当中。在未知的水域中航行可不是个好做法,但我们必须要知道,泰坦尼克号在撞到冰山沉没时是在熟悉的航线中航行的。这种事情也会发生在我们的应用中。当事情变得无法控制时,我们必须要有勇气说不。

如果你打算改变,那么我推荐你阅读一下Olivier Gierke 所写的“ Whoops! Where did my architecture ”(或是观看他在 SpringOne2GX 上关于这个项目的演讲)。但请注意,习惯的力量还是很强大的。

2013-11-08 11:329716
用户头像

发布了 88 篇内容, 共 266.9 次阅读, 收获喜欢 8 次。

关注

评论

发布
暂无评论
发现更多内容

关于 K8s 的一些基础概念整理-补充

不在线第一只蜗牛

Docker Kubernetes

远程控制软件套路深?4款对比测评,只有贝锐向日葵最靠谱!

科技热闻

BeeWorks:为企业打造专网部署即时通讯解决方案

BeeWorks

即时通讯 IM 私有化部署 局域网视频软件

从历史数据到实时决策:AI如何提升大数据实时分析能力?

天津汇柏科技有限公司

大数据 AI 人工智能

快速使用Milvus MCP Server,0代码搭建智能搜索Agent

阿里云大数据AI技术

大数据 搜索 Milvus LLM MCP

2.5D封装为何成为AI芯片的“宠儿”?

E科讯

慈善组织购买堡垒机需要考虑哪些因素?买哪家好?

行云管家

信息安全 堡垒机 慈善组织

DeepSeek-V3 0324炸场升级:代码能力碾压GPT-4.5,测试开发效率革命开启!

测试人

2025年企业组网新趋势:SASE与SD-WAN发展解析

Ogcloud

SD-WAN 组网 企业组网 企业网络 SD-WAN服务商

MySQL 优化利器 SHOW PROFILE 的实现原理

不在线第一只蜗牛

MySQL 数据库

四款远控软件对比:哪一款功能最全?哪一款延迟最低?

科技热闻

RabbitMQ集群部署(三)——镜像集群模式部署及常见问题

天翼云开发者社区

RabbitMQ

“清华”天才们联合创立,这家具身智能领域创企完成2亿元天使轮融资!

机器人头条

科技 大模型 人形机器人 具身智能

数据无界、湖仓无界,Apache Doris 湖仓一体典型场景实战指南(下篇)

SelectDB

数据湖 Doris LakeHouse trino 湖仓一体

RabbitMQ集群部署(一)——单机模式部署

天翼云开发者社区

RabbitMQ

3FS系列(二):3FS元数据性能深度拆解:那些在技术文档中找不到的实现细节

九章云极DataCanvas

人工智能 DeepSeek 3FS

【新模型速递】PAI一键云上零门槛部署DeepSeek-V3-0324、Qwen2.5-VL-32B

阿里云大数据AI技术

人工智能 模型部署 Qwen PAI DeepSeek

Java 开发高手必备:AI 工具如何帮你快速生成 Spring Boot 配置?

飞算JavaAI开发助手

企业信创项目建设实践

日志易

#信创 实践经验

让 DeepSeek 更懂你的业务,基于向量数据库 VectorDB 搭建问答应用

Baidu AICLOUD

数据库 向量数据库

《深入理解 eBPF 与可观测性》正式上架,龙蜥多位资深专家倾力打造

OpenAnolis小助手

Linux 操作系统 龙蜥社区 eBPF 技术

HarmonyOS @Reusable 装饰器自学指南:高性能组件复用实战指南

李游Leo

@Reusable

云学堂更名绚星智慧科技:发布AI新战略 领航企业智能生产力时代

人称T客

淘宝商品详情 API 接口全解析:从接入到实战

tbapi

淘宝商品详情接口 淘宝API 淘宝商品数据采集

智能网络感知,打造极致流畅的鸿蒙版中国移动云盘图文体验

最新动态

镜舟科技荣膺“北京市用户满意企业”认证,以用户为中心驱动高质量发展

镜舟科技

数据 技术创新 LakeHouse StarRocks 镜舟科技

Flink + Doris 实时湖仓解决方案

Apache Flink

大数据 flink 实时计算 Doris

外贸人必看!三步用云手机轻松收集产品反馈

Ogcloud

云手机 海外云手机 舆情监控 舆情监测 海外舆情监控

RabbitMQ集群部署(二)——普通集群模式部署

天翼云开发者社区

RabbitMQ

秒杀系统开发指南:用 AI 工具生成高并发代码的 5 个要点

飞算JavaAI开发助手

Spring Boot 集成实战:AI 工具如何自动生成完整微服务模块

飞算JavaAI开发助手

Spring Web应用的最大瑕疵_架构_张龙_InfoQ精选文章