Spring核心---简化java开发

为了降低JAVA开发的复杂性,Spring采取了一下4中关键策略
  • 基于POJO的轻量级和最小侵入性编程
  • 通过依赖注入和面向接口实现松耦合
  • 基于切面和惯例进行声明式编程
  • 通过切面和模板减少样板式代码
激发POJO的潜能

Spring竭力避免因自身的API而弄乱你的应用代码。Spring不会强迫你实现Spring规范的接口或继承Spring规范的类,相反,在基于Spring构建的应用中,它的类通常没有任何合计表明你使用了Spring。最坏的场景是,一个类或许会使用Spring注解,但它依旧是POJO。

package com.lv.demo1;

public class HelloWorldBean {
    public String sayHello(){
        return "hello world";
    }
}

可以看到,这是一个简单普通的JAVA类—POJO。没有任何地方表明它是一个Spring组件。Spring的非侵入编程模型意味着这个类在Spring应用和非Spring应用中都可以发挥同样的作用

依赖注入

任何一个有实际意义的应用(肯定要比Hello World示例更复杂)都会由两个或者更多的类组成,这些类相互之间协作来完成特定的业务逻辑。按照传统的做法,每个对象负责管理与自己相互协作的对象(即它所依赖的对象)的引用,这将会导致高度耦合和难易测试的代码。
这里写图片描述
可以看到,DamselRescuingKnight在它的构造函数中创建了RescueDamselQuest。这使得DmaselRescuingKnight紧密地和RescueDamselQuest耦合到了一起

耦合具有两面性(two-headed beast)。一方面
,紧密耦合的代码难以测试,难以复用,难以理解,并且典型出现“打地鼠”式的bug特性(修复一个bug,将会出现一个或者更多新的bug)。另一方面,一定程度的耦合又是必须的—完全没有耦合的代码什么也做不了。耦合是必须的,但应当被小心谨慎的管理

这里写图片描述
我们可以看到,不同于之前的DamselRescuingKnight,BraveKnight没有自行创建探险任务,而是在构造的时候吧探险任务作为构造器参数传入。这是依赖注入的方式之一。即构造器注入(constructor injection).

这里的要点是BraveKnight没有与任何特定的Quest实现发生耦合。对它来说,被挑战的探险任务只要实现了Quest接口,那么具体是那种类型觉得探险就无关紧要了。这就是DI所带来的最大效益—松耦合。如果一个对象只通过接口(而不是具体实现或初始化过程)来表明依赖关系,那么这种依赖就能够在对象本身毫不知情的情况下,用不同的具体实现进行替换。

对依赖进行替换的最常用的一个方法就是在测试的饿时候使用mock实现。我们无法充分地测试DamselRescuingKnight,因为它是紧耦合的,但是可以轻松的测试BraveKnight,只需给它一个Quest的mock实现即可(mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。
这里写图片描述
这里写图片描述
你可以使用mock框架Mockito去创建一个Quest接口的mock实现。通过这个mock对象,就可以创建一个新的BreaveKnight实例,并通过构造器注入这个mock Quest。当调用embarkOnQuest()方法时,你可以要求Mockito框架验证Quest的mock实现的embark()方法仅仅被调用了一次

将Quest注入到Knight中

创建应用组件之间协作的行为通常称为装配(wiring)。Spring有多种装配的方式,采用XML是很常见的一种装配方式

这里写图片描述
在这里,BraveKnight和SlayDragonQuest被声明为Spring中的bean。就BraveKnight bean 来讲,它在构造时传入了对SlayDrangonQuest的引用,将其作为构造器的参数,同时,SlayDragonQuest bean的声明使用了Spring表达式语言,将System.ou传入到了SlayDragonQuest的构造器。

观察它如何工作的

Spring通过上下文(Application Context)装载bean的定义并把它们组装起来。Spring应用上下文全权负责对象的创建和组装。Spring自带了多种应用上下文的实现,它们之间的主要区别仅仅在于如何加载配置

这里写图片描述
这里写图片描述

这里的main()方法基于knights.xml文件创建了Spring上下文。随后它调用该应用的上下文获取一个ID为knight的bean。得到Knight对象的引用后,只需简单调用embarkOnQuest()方法就可以执行所赋予的探险任务了。注意这个类完全不知道我们的英雄骑士接受哪种探险任务,而且完全没有意识到这是由BraveKnight来执行的。只有Knight.xml文件知道哪个骑士执行哪种探险任务。

应用切面

DI能够让相互协作的软件组件保持松散耦合,而面向切面编程(AOP)允许你把遍布应用各处的功能分离出来形成可重用的组件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值