近年来,在 JAVA 社区中风起轻量级框架的热潮,“让 J2EE 开发变得简单”,几乎每个月就会有新的轻量级容器出现,这些轻量级容器能够较好地帮助开发者快速地将不同的组件组成一个应用程序,在这些轻量级容器的背后都有一个共同的装配模式,那就是“反向控制”,也就是 IOC ,英文全称是“ Inversion of Control ”。
Spring 的核心是个轻量级 (LightWeight) 的容器 (Container) ,它是实现 IOC(Inversion of Control) 容器和非侵入性 (No intrusive) 的框架, Spring 最重要的核心概念是 IOC ,在 Spring 中,“依赖关系的转移”、“依赖于抽象而非实践”是重要的观念,从对象的角度来看,可以避免对象之间的耦合;从容器的角度来看,可以避免应用程序因依赖于容器的功能,而从容器脱离。
Spring 另一个重要核心概念为 Dependency Injection ,中文常翻译为“依赖注入”,简称 DI 。使用 Spring ,不必自己在程序代码中维护对象的依赖关系,只需在配置文件中加以设置, Spring 容器会自动根据配置,将依赖注入指定的对象。
控制反转
Spring 的核心概念是 IOC , IOC 的抽象概念是“依赖关系的转移”。转移是相对于过去不良的应用程序设计来说的,像“高层模块不应该依赖于底层模块,而模块都必须依赖于抽象”是 IOC 的一种表现,“实现必须依赖抽象,而不是抽象依赖于实现”是 IOC 的另一种表现,“应用程序不应该依赖于容器,而是容器服务于应用程序”也是 IOC 容器的一种表现。
IOC 的 Control 是控制的意思,其实背后的意义也是一种依赖关系的转移。如果 A 依赖于 B ,其意义即 B 拥有控制权。如果转移这种关系 ( 依赖关系的反转即控制关系的反转 ) ,将控制权由实现的一方转移到抽象的一方,让抽象方拥有控制权,可以获得组件的可重用性。 IOC 在容器中扮演的角色,可以用好莱坞的一句名言来表示:“ Don’t call me , I’ll call you ”。以程序的术语来说,就是“不要向容器要求所需要的 ( 对象 ) 资源,容器会自动将这些对象给你”。
IOC 的要求是容器不应该 ( 或尽量不要 ) 侵入应用程序,也就是不应该出现与容器相依的 API 。应用程序本身可以依赖于抽象的接口,容器可以通过这些抽象接口将所需的资源注入至应用程序中。应用程序不向容器主动要求资源,故而不会依赖于容器特定的 API ,应用程序本身不会意识到正被容器使用,故而可以随时从容器系统中脱离,转移至其他的容器或框架而不需要作任何的修改。
依赖注入
依赖注入的意义是:“保留抽象接口,让组件 (Component) 依赖于抽象接口,当组件要与其他实际的对象发生依赖关系时,由抽象接口来注入依赖的实际对象。”
依赖注入通常有三种方式: Interface injection 、 Setter injection 、 Constructor injection 。
接口注入 (Interface injection)
因为接口注入需要特定的接口,这样使程序具备侵入性,所以 Spring 抛弃了这种注入方式。
设值注入 (Setter injection)
set 注入就是在程序中给每个变量都增加一个 set 方法,用来设置该属性的值。
构造子注入 (Constuctor injection)
构造子注入就是在需要注入的类中定义一个构造方法,应在构造方法中定义需要注入的实例元素,通过类的构造器来完成协助该类工作的其他实例的初始化。
Spring 的核心是个 IOC 容器,可以管理对象的生命周期,并可以通过 Setter 或构造函数的方式,编写配置文件 ( 一个 XML 文件或是通过注解 ) ,让 Spring 在执行时期根据配置文件的设定,建立对象之间的依赖关系。这不仅减少了大量的程序编写,降低了对象之间的耦合程度,通过 Spring 这类成熟的框架,还可以大幅提升应用程序的可靠性。