再论IoC和AOP驳yong9981对"谈谈...(20191225)"一文的评论

编程

谈谈我对 IoC 和 AOP 的理解 一文由 JFinal 作者波总对 IoC 与 AOP 的一句表述引起:

quote>

IOC 本质是为了实现 AOP

在文中我考察了 IoC, DI 和 AOP 三个概念及其关系, 并得出以下结论:

  1. IoC 的本质不是为了实现 AOP.
  2. 波总的 JFinal 已经实现了 IoC 原则. 因为应用写的代码总是被 JFinal 的代码调用, 这就是控制反转.
  3. DI 也不是为了实现 AOP

@yong9981 对此文给出了以下评论:

我不赞同 yong9981 在评论中的观点, 所以在本文中一一回应.

1. "其实不能算错, 相反,只有对IOC/AOP有深切理解的人才能说出这句话"

yong9981 这句话应该是针对波总的表述 "IoC 的本质是为了实现 AOP" 而言. 我在 谈谈 一文中已经清楚地给出了维基百科中对 IoC 和 AOP 这两个概念的描述, 并由此得到结论: "IoC 的本质不是为了实现 AOP". 如果 yong9981 认为波总的表述没有错误, 那就是我的结论有误. 逻辑上讲有两个可能:

  1. 维基百科对 IoC 和 AOP 的概念描述有错误
  2. 我在文中依据概念得出结论的过程不正确, 依据维基百科的概念描述应该得到 "IoC 的本质是为了实现 AOP" 这个表述

请 @yong9981 回答, 你认为我上面结论的错误应该属于哪种情况? 不管是哪种情况, 请给出你的依据. 直接下断言的方式我不接受.

2. "ACT则更奇葩,框架只提供 IOC 功能 ... 从架构上来说是错误的"

依据维基百科对 IoC 的定义, 凡是提供控制反转的 (应用代码被框架调用的) 都是 IoC 的应用. 因此我大致可以说基本上 Web 框架 (包括 Servlet 在内)都是符合 IoC 原则的.

基于以上分析, 我姑且揣摩 yong9981 想说的是 "ACT 则更奇葩, 框架只提供 DI 功能".

先来看看除 Act (截止到 1.8.x) 以外还有那些框架支持 DI, 但不提供 通用 AOP:

  • blade - Java
  • finatra - Scala
  • gin - Go
  • hexagon - Kotlin
  • jawn - Java
  • jooby - Java
  • martini - Go
  • minijax - Java
  • playframework - Scala
  • quarkus - Java

由此看来只支持 DI 而不提供 AOP 的框架也不仅仅是 Act 了.

再来看看百度百科对 奇葩 这个词的定义是:

原意是指奇特而美丽的花朵,常用来比喻不同寻常的优秀文艺作品或非常出众的人物。比喻某人(或某事物)不落世俗,个性十足。这个词更多带有调侃,指美好出众的事物不同。也多指向一些正常人行为和思维以外的,让人难以想象的行为。

我相信 yong9981 用 奇葩 来修饰 Act, 不会是引用其原意, 而是指 Act 仅支持 DI 不支持 AOP 的设计不正常. 上面我已经列出有更多的框架采用同样的设计, 所以这个词我不接受.

3. "把AOP和声明式事务当作DAO插件一起捆绑,这从架构上来说是错误的"

这里解释一下 yong9981 上面这个论断的上下文.

ActFramework 不支持通用的 AOP, 而是采用下面的方式替代了 AOP 的部分常见用途:

  1. 拦截器机制 - 解决应用在请求处理流程中的切面编程问题
  2. Metric 机制 - 解决应用收集性能数据的切面编程问题
  3. 对声明式事务的处理

    • Ebean - 交给 Ebean 的声明式事务处理机制 (通过 javaagent 机制修改应用字节码)
    • EclipseLink 和 Hibernate - 交给 act-jpa-common 的声明式事务机制处理 (通过 Act 的类增强机制修改应用字节码)

yong9981 认为 Act 在这方面的设计是错误的, 他的理由是:

因为事务本身是可以独立于DAO存在的

我不是很明白上面这条理由. 其中的 "事务" 是指一个运行时的事务实例, 还是只框架的事务处理机制? "DAO" 是指一个运行时的 Dao 实例, 还是数据库访问组件? 如果都是指实例和正在讨论的问题不相干, 我姑且认定 yong9981 说的是"事务处理机制和数据库访问组件无关", 并基于这个理解来讨论.

对上面的理由 yong9981 继续列出了一个作证:

例如spring事务模块可以捆绑在任意支持AOP联盟标准上的DAO工具上使用的,但前提是框架要支持AOP联盟标准。

先向 yong9981 提两个问题:

  1. 什么是 "支持AOP联盟标准上的DAO工具" ?
  2. 请列举出几个 "支持AOP联盟标准上的DAO工具" 出来

就 Java 生态, 我所知道的比较著名的数据库访问组件有:

  • BeetlSQL
  • EbeanORM
  • Eclipselink
  • Hibernate
  • JDBC
  • JooQ
  • MyBatis
  • Spring JDBC Template
  • Spring Data JPA
  • Jdbi
  • fluent-jdbc

请问 yong9981 上面列出的 Java 数据库访问组件哪个是支持 AOP Alliance 的? 请列出你引用的链接. 如果你给不出反例, 我可以得出以下结论:

j1. 没有支持 AOP 联盟标准上的 DAO 工具

既然 yong9981 使用 Spring 作为作证, 下面我们就看看 Spring 中 AOP 到底是如何参与声明式事务处理的

3.1 Spring 中对声明式事务的处理

Spring Transaction Management 文中这个插图描述了 Spring 对声明式事务的处理机制:

从图中, 我们可以看到 AOP 的参与到 TransactionAdvisor 为止, 而具体某个数据库访问机制如果需要支持 Spring 的事务处理过程, 需要讲自己适配到 Spring 的事务管理机制中 - 不是适配到 AOP alliance

拿 MyBatis 为例. 在 MyBatis Spring 插件 - 事务 文档中第一句话就是:

One of the primary reasons for using MyBatis-Spring is that it allows MyBatis to participate in Spring transactions

在 MyBatis Spring Github 项目 我们可以看到 MyBatis Spring 集成进 Spring 事务处理的代码:

  • SpringManagedTransaction.java
  • SpringManagedTransactionFactory

到此我们可以得出下面的结论:

j2. "spring事务模块可以捆绑在任意支持AOP联盟标准上的DAO工具上使用的" 这个断言是错误的

4. "我说这个框架有问题... 只基于一个原则,... 能不能拿出来单独使用 ..."

yong9981 评论中的最后一段论述如下:

我说这个框架有问题,那个框架有问题,往往只基于一个原则,就是它这个功能能不能拿出来单独使用,能不能被其它软件替换掉, 基于这个原则,可以很简单地判断出以下问题:

  • ACT和JFinal不支持AOP联盟标准是一个缺陷
  • SpringBoot、SpringCloud的IOC/AOP内核不能被其它软件替换掉是一个问题,它导致Spring绑死在Spring内核上,不是说springioc内核不好,相反它非常好,依赖也少,查一查MAVEN就知道了。但它的问题是太大了,源码难看,又动不动更新扰民。
  • ACT和jFinal的MVC模块不能单独使用,这是一个架构问题,造成资源浪费,比方说,我想使用以下三个优秀功能的组合是做不到的:

    spring-ioc内核+ACT的MVC+JFinal的事务

依据 hotframeworks 给出的统计, 2019 最常用的 Java web 框架有:

  • Spring
  • JSF
  • GWT
  • Play!
  • Struts
  • Vaadin
  • Grails

请问 yong9981: 这些框架的组件都能互换吗? 是不是这些框架都有问题? 如果每个框架都有问题, 是不是你的问题有问题?

我认为:

  1. 在一定程度上, 框架组件的解耦 (相互替换) 可以采用遵循一些标准来达到, 比如 JSR 330 依赖注入, JSR 303 数据校验, JAX-RS (RESTful Service API) 等等
  2. 框架拥有选择自己生态结构的权利. 一个框架可以选择一个全封闭的生态, 也可以选择一个相对开放的生态. 没有理由因为框架做出的这种选择认为该框架有问题甚至有缺陷.

以上是 再论IoC和AOP驳yong9981对"谈谈...(20191225)"一文的评论 的全部内容, 来源链接: utcz.com/z/512061.html

回到顶部