从EJB到Spring

Expert One-on-One J2EE Development without EJB是Java企业级应用开发的经典之作,可以从中看到Java企业级应用开发框架的发展历程、历史负债,从该领域顶级的架构师、Spring之父Rod Johnson的视角来看怎样解决这些问题,引出Spring的诞生以及其重要价值。

1. J2EE/EJB的问题

1.1 EJB之过

  • 规范中很多已经过时,例如代码生成机制,在J2SE1.3提出动态代理后已经没有必要。
  • webservic的发展使得RMI没有那么必要。
  • 实际开发中,EJB定义的一套体系结构是否具有普遍性值得怀疑。
  • 为了解决这些问题,EJB规范日益复杂,以至于很多开发者无法理解。
  • 开发效率低,通过IDE掩盖复杂性。
  • 测试驱动开发变得流行,EJB很难测试。
  • ……

根源以规范为驱动,成功的标准是从实践中发展出来的,而不是由哪个委员会创造出来的。

1.2 我们的目标

简单

作为架构师,应该尽量降低架构设计的复杂度,只为现实的,或者合理的可预见的需求提供支持,不要试图把所有问题都考虑进来,同时要重视架构设计质量,保证未来可以对其重构,以应对更加复杂的需求,架构伸缩性至关重要。

高产

EJB使用者需要花大量时间调用大量API以及处理复杂的部署问题,这些时间本该处理业务逻辑。

面向对象为本

OO的设计比具体的实现技术更重要,应该避免被具体实现技术绑架,违背OO原则。

业务需求之上

应用架构应该是由业务需求驱动,而不是开发者凭空想象的,例如:多数据库迁移、支持各种客户端等待。

重视经验过程

同时实例验证架构合理性,主要指标包括:性能、采用的难度、可维护性。很多广受推崇的架构实际上是由技术规范或厂商推动的,并没有在生产环境验证过。

重视可测试性

测试先行的开发模式日益流行,可测试性是敏捷项目的基本要素,应用架构需要便于开发者编写单元测试。

EJB违反了帕累托法则(80/20法则),架构的价值在于为常见的问题找到好的解决方案,而不是一心想要解决更复杂也更罕见的问题, 需要注意,拒绝使用EJB并不是拒绝EJB使用的基础设施解决方案。

2. 轻量级IOC容器

2.1 什么是容器

代码的运行框架,管理形形色色的业务对象,提供秩序和结构。
核心功能:

  • 生命周期管理
    控制对象的生命周期,把创建新对象的逻辑从使用者抽离,更多的包括回调机制,在激活对象或容器关闭时,通知被管理对象。
  • 查找服务
    容器应该提供某种途径,用于获取被管理对象的引用。也就是把“对业务对象细节的了解”从使用者抽离出来,容器的核心是一个工厂。
  • 配置管理
    提供统一的方法配置运行其中的对象,允许对象参数化。
  • 依赖决议
    不仅管理简单独立对的对象,还能管理对象间依赖关系。

附加功能:

  • 企业级服务,事务管理等
  • 线程管理
  • 对象池
  • 集群服务
  • 远程服务
  • ……

2.2 控制反转

好莱坞原则:不要打电话过来,我们会打给你。
依赖注入是当先最流行的IOC类型,消除所有依赖查找代码,让容器处理对象依赖关系。

依赖查找

容器提供回调接口和上下文环境给组件,组件必须使用容器提供的API查找资源和对象,用户主动行为。

依赖注入

组件不做定位查询,只提供普通方法让容器决定依赖关系。容器全权决定组件装配,根据注入的方式可以分为:属性注入和构造函数注入。
基本原则:
应用对象不应该负责查找资源或者其他依赖的的协作组件,配置对象的工作应该由IOC容器完成,”查找资源“的逻辑应该从应用代码中抽取出来,交由容器负责。
依赖注入的好处:

  • 查找定位操作与应用代码完全无关。
  • 不依赖容器的API。
  • 不需要特殊接口。

Spring的IOC容器
Spring提供了完善的IOC支持,一般情况下,是通过元数据进行配置,并不强求任何特定的元数据表现形式,可以实现BeanDefinitionReader接口,通常可以使用XML文件格式作为配置信息输入。
Spring也提供了回调方法,用于实现基于回调的、依赖查询式地操作,托管对象可以利用这些回调函数查找其他对象,执行额外的初始化方法,或者在容器关闭时释放资源。

2.3 轻量级级容器关键特征

  • 无侵入性,尽量不要对其中运行的应用对象提出特殊需求。
  • 启动快速。
  • 无需特殊部署步骤。
  • 轻巧,可以再体系结构的任何层面使用。
  • 能够管理任何力度的对象。

无侵入性是轻量级容器的最重要的优势之一,由于尽量避免了应用代码对容器的依赖,生产率、代码可复用度、可测试性也将大为改善。这个目标是通过控制反转(具体来说,应该是依赖注入)实现的。
IOC容器解决了组件装配问题,使得应用开发人员可以专心处理业务逻辑。这恰好是J2EE平台最初的许诺。
轻量级IOC容器在实现J2EE应用方面有着巨大的优势。IOC将会和AOP一起成为下一代J2EE框架的基础。

3.Spring诞生

Spring提供了统一的应用架构方式,以及大量的中间层功能模块,能够大大简化J2EE的开发。

3.1 来历和动机

核心目标:

  • 解决其他框架忽略的部分
    提供一种贯彻始终的解决方案,将各种专用框架整合成一个连贯的整体架构。还涉及到一些其他框架没有触及的方面,包括普遍适用的事务管理器、数据存储对象实现,各个领域都有最好的选择,但没有框架把它们整合到一个应用中去。因此,Spring是一个应用框架,而不是web框架、IoC框架、AOP框架、中间层框架。
  • 易于选择
    一个框架应该有清楚的层次划分,允许用户使用其中的单项功能,而不是把自己的整个世界观强加给用户。Spring中许多特性,比如JDBC抽象、Hibernate集成,可以作为一个单独的库使用,也可以作为整体方案的一部分。
  • 易于使用
    框架应该帮助开发人员合理使用J2EE的服务,同时避免造成对服务的依赖,减少不必要的复杂性。
  • 鼓励最佳实践
    遵循最佳实践,例如面向接口编程,但是不强加任何架构风格,把选择的权利留给开发者。
  • 非侵入性
    应用对象避免过度依赖框架接口,IoC和AOP是实现的关键技术。
  • 统一配置
    一个好的基础框架可以让应用配置灵活而且统一。从中间层到web控制器,所有配置需求都可以用统一的方式实现。
  • 易于测试
    不论是整个应用测试还是单元测试都应该简单方便。
  • 可扩展
    基于接口编程,同时很多组件使用策略模式,方便定制。

关键概念:

  • bean工厂
    容器能够配置、装配JavaBean和普通Java对象,开发者不需要定制Singleton和配置机制。Spring提供多个”即拿即用“的bean工厂实现,包括基于xml的实现。
  • 应用上下文
    应用上下文(Application Context)是对bean工厂的扩展,它在bean工厂基础上增加了对信息员和资源加载的支持,并提供了接入现有系统环境的能力,Spring提供多个”即拿即用“的应用上下文实现,包括一个独立的应用上下文,以及一个基于xml的web应用上下文。
  • AOP框架
    框架提供了AOP支持,可以对容器管理的任何对象进行方法拦截。
  • 自动代理
    Spring在AOP框架基础上提供了更高级别的抽象,可以通过源码级的元数据驱动。
  • 事务管理
    Spring提供了通用的事务管理基础设施,包括可插拔的事务策略和不同的事务边界划分方式。
  • DAO抽象
    Spring定义了一组通用的数据访问异常类型,在创建通用DAO接口时可以抛出统一的有意义的异常信息,而不依赖底层持久机制。
  • JDBC支持
    比起直接使用JDBC,使用Spring的JDBC封装可以大大提高生产率,并且可以避免连接泄露等问题。
  • 集成OR映射工具
    Spring集成了多种ORM工具,如hibernate、ibatis等,开发者可以自行选择,这些集成包可以让应用无需定制ThreadLocal会话和事务操作,也不用考虑底层使用哪种ORM工具。
  • web MVC框架
    Spring提供了一个相当干净的MVC实现,web控制器可以IoC容器中配置,不需要编写额外的编码,还提供了通用的DispatcherServlet和”即拿即用“的控制器类,请求与控制器之间的映射方式、视图的判断、本地化以及其他的重要服务都是可插拔的。
  • 远程调用支持
    Spring为远程服务的创建和调用提供了一个薄的抽象层。

Spring涵盖了从事务管理到MVC的众多领域,但是解决问题的方式是一以贯之的,各种组件都是采用同样的bean配置方式。

3.2 bean工厂

todo

3.3 应用上下文

todo

如果觉得我的文章对您有用,请在支付宝公益平台找个项目捐点钱。 @sxzhou Apr 2, 2020

奉献爱心