Spring的两个核心特性:依赖注入(dependency injection,DI)和面向切面编程(aspect-oriented programming,AOP)
一 简化Java开发
Spring的根本使命:简化Java开发
为了降低Java开发的复杂性,Spring采取了以下4种关键策略:
- 基于POJO的轻量级和最小侵入性编程;
- 通过依赖注入和面向接口实现松耦合;
- 基于切面和惯例进行声明式编程;
- 通过切面和模板减少样板式代码。
激发POJO的潜能
Spring不会强迫用户实现Spring规范的接口或继承Spring规范的类,相反,在基于Spring构建的应用中,它的类通常没有任何痕迹表明你使用了Spring。最坏的场景是,一个类或许会使用Spring注解,但它依旧是POJO。
Spring非侵入编程模型意味着这个类在Spring应用和非Spring应用中都可以发挥同样的作用
依赖注入
背景
任何一个有实际意义的应用都会由两个或者更多的类组成,这些类相互之间进行协作来完成特定的业务逻辑。按照传统的做法,每个对象负责管理与自己相互协作的对象(即它所依赖的对象)的引用,这将会导致高度耦合和难以测试的代码。如下所示:
public class DamselRescuingKnight implements Knight {
private RescueDamselQuest quest;
public DamselRescuingKnight() {
this.quest = new RescueDamselQuest();// 与RescueDamselQuest紧耦合
}
public void embarkOnQuest() {
quest.embark();
}
}
DamselRescuingKnight在它的构造函数中自行创建了Rescue DamselQuest。这使得DamselRescuingKnight紧密地和RescueDamselQuest耦合到了一起。并且Knight只能执行Rescue这一个任务。
同时由于骑士的embarkOnQuest()被调用时,探险的embark()也要被调用,所以 DamselRescuingKnight 无法进行单元测试。
耦合具有两面性。一方面,紧密耦合的代码难以测试、难以复用、难以理解,并且典型地表现出“打地鼠”式的bug特性(修复一个bug,将会出现一个或者更多新的bug)。另一方面,一定程度的耦合又是必须的——完全没有耦合的代码什么也做不了。为了完成有实际意义的功能,不同的类必须以适当的方式进行交互。总而言之,耦合是必须的,但应当被小心谨慎地管理。
依赖注入能做什么
通过DI,对象的依赖关系将由系统中负责协调各对象的第三方组件在创建对象的时候进行设定。对象无需自行创建或管理它们的依赖关系。如下图所示,依赖关系将被自动注入到需要它们的对象当中去,而不是让对象自己去获取依赖。
对上面的骑士进行修改:
public class BraveKnight implements Knight {
private Quest quest;
public BraveKnight(Quest quest) {
//Quest被注入进来
this.quest =