十年前的Java企业应用开发世界

jopen 12年前

        在 2003 年用 Java 编程比现在要更痛苦一些。比如说,J2SE 1.5 还没有发布,也就是说一些现在大家认为理所当然的特性,比如泛型容器、static import、Annotation,都是不存在的;Integer 和 int 是不能自动转换的;枚举只是整数换了个写法没有任何类型安全机制……我还在 2003 年第 6 期《程序员》杂志发表了一篇文章,介绍 J2SE 1.5 的新特性。而在项目里,不管是浙江省财政厅的项目,还是杭州市工商局的项目,我们用的都还是 J2SE 1.3。

十年前的Java企业应用开发世界

        更大的挑战——或者说,乐趣——是框架乃至编程思想的不统一。几年以后,当 Java 企业应用开发彻底成熟,所有人都知道 SSH(Spring+Struts+Hibernate,后来 Struts 终于被 SpringMVC 取代),连培训学校也拿这几样东西来作为就业敲门砖。可是在 2003 年,Martin Fowler 那篇“Dependency Injection”还没发表,关于“什么是好的容器框架”还远远没有定论。且不提 Apache Avalon 这样的容器——照现在的眼光来看,Avalon 根本算不上一个合格的容器,但你必须意识到它是 Java 1.3 之前的作品,这样才能理解为什么它会存在并进入这个讨论——Spring 之外还有 Paul Hammant 和 Jon Tirsen 的 PicoContainer 在与之竞争成为事实标准。而当时还在 0.x 版本的 Spring(当年 10 月 Spring 才发布 1.0 版本),其功能也并不比单纯专注对象容器的 Pico 丰富。

        Web 框架的情况更加混乱。Struts 被使用最多同时也被诟病最多;Rickard Oberg 刚做出了 WebWork,大家还没充分意识到它的好处。更麻烦的是,其时整个 J2EE 社区并未——像今天这样——达成一个共识说“MVC 是好的”,于是其他种种构造 Web 应用的方式以及相应的框架层出不穷:有人相信 Web 开发也应该走“组件化”道路,于是有了面向组件的 Web 框架(例如 Tapestry );有人认为 Portal 才是未来 Web 的发展方向,于是有了形形色色的 Portlet 容器(例如 JetSpeed );甚至还有人尝试用“XML 文档 +XSLT 转换”的方式来实现 Web 应用。当年最火的全功能 Web 框架还是 Turbine ,到如今它给我们留下的也就只剩 Velocity 了——恰恰 Velocity 所代表的“view template engine”在当时还没有被广泛接受,更多人仍然习惯于在 JSP 里直接写上一大堆 Java 代码。当时有人笑称,每周都会有一个新的 Web 框架在 TSS 上发布——其时最具影响力的 J2EE 网上社区 TheServerSide.com 被简称“TSS”,由此可见那时的企业软件世界是有多爱三字母缩写词。InfoQ 的创始人 Floyd Marinescu 当时还在 TSS 做内容主管呢。

        持久化框架的情况也好不到哪儿去。Hibernate 倒是已经发布了 2.0 版本,不论功能还是性能都已接近成熟;可是 Hibernate 与 ADO 之间的争论正在如火如荼地展开着,究竟应该选一个刚开始热门的开源框架还是选一个“标准”也颇让人头疼;同时也别忘了另一边,很多程序员更愿意用简单的 SQL 来操作数据库,而不是在对象与关系数据的映射中绞尽脑汁;再加上 2003 年普遍的“XML 热病”,真的有很多人相信可以把企业应用中的数据持久化成 XML 从而抛弃关系型数据库——你也可以说这是 NoSQL 的早期萌芽,总之当时这些思想只是让事情变得更复杂而已。

        当你谈论 2003 年的 J2EE 世界时,千万别忘了这里还有 EJB。实际上,EJB 2 才是当时 J2EE 的正统——再提醒一下读者们,Spring 还在 0.x 的阶段,Rod Johnson 那本旗帜般的“without EJB”还没写出来呢。曾经有 IBM 的咨询师来跟我们讨论应用架构,听说我们完全没用 EJB 时都连连摇头。如果不是石一楹坚持不用 EJB,也许我会走上一条相当不同的技术路线。后来我一直对 EJB 不怎么上手(虽然还翻译过一本与 EJB 关系不少的书),倒是轻量级 J2EE 架构接受起来驾轻就熟,不得不说是种运气。

        仿佛是嫌事情还不够复杂,那时很多企业对开源软件抱持一种不信任的态度,所有框架都愿意自己开发,似乎只要“not invented here”的东西就不可靠——这样的企业现在也有,毕竟数量少多了。这里固然有心态的原因,同时技术上的原因也不应该忽视。J2SE 1.3 引入了动态代理(dynamic proxy)技术,以 Rickard Oberg 为代表的一帮天才开发者们立即敏锐地意识到:这是一件框架开发的利器——在与 JBoss Group 决裂之前,Oberg 是 JBoss 的首席架构师,可以说是他一手创造了 JBoss;同时他也是 AOP 和 Interception 的狂热爱好者,因为他早早地看到了这些元编程技巧在框架开发中的重要意义,而动态代理则正是让 Java 不依赖于外部的、非标准的代码生成技术(例如 AspectJ、CGLib 等)实现动态元编程的基础设施。其结果是,从 Java 1.3 开始,很多新的框架显著地变得更优雅、更少侵入性——Java 1.3 之前的“老”框架,例如 Avalon、Turbine,与这些后来者比起来就显得相形见绌。然而这种优雅同时也意味着更难理解其内部运作机制,有时对着一个漂亮的框架就仿佛在看 一场精彩的魔术,愉悦之余也难免有些心里犯嘀咕。正处在这场转变之中的企业和团队,希望自己动手开发框架从而获得更多安全感,也是情有可原。

        不过这种复杂、混乱与缺乏信心对于程序员来说倒未尝不是好事。短短的几个月时间里,我的项目主管带着我把 J2EE Web 应用的全套框架——对象容器、持久化、Web MVC——都实现了一遍。这个过程不仅让我的技术水平突飞猛涨,而且还让我交了不少朋友:因为我比较喜欢显摆,做出点东西就在网上谈论,一来二去就结识了 一些与我有着同样困惑的同行。在这些“以技术会友”的新朋友之中,最有趣的是一个叫 DreamHead 的家伙。这人每每写邮件长篇大论洋洋千言,博客也是一副正襟危坐的范儿。我们讨论的主要就是这些基础框架与架构,没想到类似的话题我竟然与他一直讨论了十 年。