如何使用弹簧的分层架构仍然遵循面向对象的结构?
我学习了spring及其分层结构(控制器,服务和dao)
@Controller("userController") @service("userService") @Transactional( propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = true) @Repository("userDAO")
现在我很困惑如何利用这些分层结构来利用优秀的OOPS实践 ( 如此 )来制作一个大项目(现实世界有更复杂的业务逻辑,然后通常提供示例应用程序)。 我还想使用这些spring事务和框架提供的其他function。 有些人可以帮我解决这个问题,或者参考开源项目来澄清我的疑问。
简而言之
分层体系结构将简化代码的可维护性和一致性,当它变得庞大而复杂时。
要记住的事实是在执行之前要进行适当的软件设计。
- 封装 – 特定于域模型的业务逻辑应该在其中。
- 抽象 – 在抽象中编写公共业务逻辑的同时,根据服务分组隔离接口。
- inheritance – 在绘制域对象时使用
- 多态性 – 当您想要更改子模型的业务逻辑时,还有inheritance。
详细地
下面我正在努力为这次讨论提供一个ERP应用程序示例。 希望ERP是一个足以查看业务逻辑复杂性的大项目 。
以下描述适用于任何需要在Spring(或任何其他框架)中理解和使用分层项目结构的开发人员。
但请注意,这些不是要遵循的规则,而是要使用的最佳实践。 🙂
1.数据访问层 – 模型/域对象
这包含实际表到类的映射。
在ERP示例中,您可以获得模型:
CustomerOrder
,CustomerOrderLine
这还包含子域对象的en-capsuled逻辑和self的域逻辑。 例如,
CustomerOrderLine
是CustomerOrderLine
的子项。 没有父母,孩子就不能存在。 因此,父母将完全控制在其中构建孩子。 即业务逻辑封装。 。 即:Add CustomerOrderLine
,RemoveCustomerOrderLine
等。当谈到自域逻辑,ApproveCustomerOrder
,RejectCustomerOrder
等。
2.数据访问层 – 存储库
除了使用SELECT, INSERT, UPDATE and DELETE SQLs
包含对数据库的简单CRUD。 您可以在Spring中使用存储库模式以及Spring Data JPA
。
注意:除非您的逻辑是高度数据密集的,否则不要在此层中编写任何复杂的逻辑
在这种情况下,您可能必须编写一个或多个函数来执行复杂的查询语句。 (最好是JPQL
)
在ERP示例中,这是您为
GetCustomerOrders
,GetCustomerOrderByCustomer
,GetCustomerOrderLines
,GetOrderByStatus
编写逻辑的地方简单来说,该层定义了应用程序如何与外部实体(如数据库)进行通信。
3.服务层
在这里, 您应该放置涉及多个未连接(非子 – 父)域模型的复杂业务逻辑 。 这些将在Web控制器和Rest API控制器中重用。
因此,为了保持一致性并实现安全性 ,我宁愿所有在域模型中编写的业务逻辑都包含在这一层。
在ERP例子中,这是您编写逻辑或包装在域模型中编写的逻辑的地方。 例如
CreateCustomerOrder
,ListCustomerOrder
,ApproveCustomerOrderLine
,ApproveCustomerOrderLine
,……
如果这些逻辑应该与其他模型逻辑一起执行,那么也应该在服务层内的序列中调用它们。 例如。
其他复杂业务逻辑的例子
如果要为供应商创建
Purchase Order
,则在下达Customer Order
时。
然后,这可以通过创建一个名为SupplyChainService
的服务来完成,该服务使用Spring AOP绑定到CustomerOrderService.ReleaseCustomerOrder
。
4.控制器
控制器可以分为两类,即:Web控制器和REST控制器。 在该层中不应该实现业务逻辑,因为在Web和API级别中调用可能需要相同的逻辑。
在ERP系统中,您可以在此处为客户订单表单编写控制器,以输入数据并保存以创建新的客户订单。
这将是您还将创建一个API控制器(如REST)以通过移动应用程序或Windows客户端创建客户订单的位置。
感谢SO社区向我展示了我在这个答案中没有涉及OOP原则的领域
Spring应用程序设计和OOD不是互斥的。
典型的Spring(MVC)应用程序具有以下结构:
- 一个或多个
@Controller
类。 这些是您的应用程序的入口点。 它们不应包含任何业务逻辑。 尽管名称我将它们标识为MVC中的V ( 模型 – 视图 – 控制器 ) - 一个或多个
@Service
类。 这是您开发业务逻辑(BL)的地方。 将BL放在这里的好处之一是它可以被多个控制器重用(例如@Controller
和@RestController
)。 他们是MVC中的C。 - 一个或多个
@Repository
类,您可以在其中实现持久层(数据库,内存中,等等……)。 此外,您可以实现一组描述域对象的@Component
类。 这些是MVC中的M. - 您无法在MVC模式中映射的其他类,如
@ControllerAdvice
Configuration,@ControllerAdvice
和其他Spring配置/管理类。
在设计每个对象时,您可以遵循您喜欢的任何OOD方法。
在你提到的OOD示例中,我会像这样设计我的应用程序:
- 每个actor的一个视图(
@Controller
) - 每个用例一个
@Service
- 每个域类有一个
@Repository
和一个@Component
编辑:你可以在这里找到我为大学写的一个示例项目。 它通过附加层(在@Controller和@Service之间)实现了我在后三点中解释的内容,因为需要最小化对C层的依赖性。 这些概念仍然适用。
您正在尝试理解可以一起互操作的两个不同概念。
分层架构
层架构是业界的架构风格之一。 在这里我们有单独的层来做特定的逻辑。 示例我们有表示层,业务层和数据服务层。 这称为应用程序的水平切片。 还有其他架构风格,如面向服务/基于组件的体系结构,其中应用程序是垂直切片的。
假设您有自动预订流程。 通常,如果你采用分层架构设计(水平切片),那么我们有不同的层来完成所需的工作。 但是当涉及垂直切片时,我们将应用程序的不同实体识别为预订,客户管理,基金管理。 我们将实现这些组件,并相互通信以构建我们的预订应用程序。 这里需要记住的是内部组件可以使用相同的分层架构。
OOPS概念
OOPS概念可帮助您以面向对象的方式设计应用程序。 一旦确定了体系结构样式,就必须以可扩展的方式实现应用程序,并且可以轻松维护。 所以,他们有不同的实施方法。 OOPS就在他们身上。 它提出了一些设计原则,可帮助您以更好的方式实现应用程序
见SOLID
我想,你在这里问一个错误的问题。 分层体系结构本质上不是面向对象的,因此,虽然使用(某些)面向对象的实践是可能的,甚至是可取的,但它本身不应该是目标。 它类似于询问我如何使用最佳的卡车驾驶练习来骑自行车。
为什么我说分层架构不是面向对象的? 嗯,正如我们所知,区分面向对象设计有三个原则:封装,inheritance和多态。
虽然最后两个可能存在也可能不存在,但根据您的设计选择,分层架构几乎与封装相反 :根据这种方法的本质,您明确地将数据(“DTO”)与逻辑分开(“服务”)。
不要误解我,这种方法不是面向对象的事实并不意味着它有任何问题。 反之亦然,“面向对象”并不是“好”的同义词,它是程序员工具箱中的众多工具之一,并且与任何工具一样,更适合解决某些问题而不是其他工具。
分层架构是一种很好的设计模式,可以成功地用于解决许多现实工程问题。 它有自己的一套可以并且应该使用的最佳实践,虽然这个集合可能与OOP的对应部分有一些交叉点,但这两者肯定不相同。