Spring的价值及学习内容

Spring的根本使命是 简化Java开发,方法是引导开发者使用POJO来设计实现系统。

Spring还有样式代码的封装和复用,我认为这个不是亮点。因此,略去不表,不喜勿喷。

关于POJO的理解

POJO是一个简称,全称为plain old java object。中文翻译是简单老式的java对象。

我认为Java类具备下面两个条件时,那么这个类可以被称为POJO。

  • Java类没有任何基类或Java类的继承链只有JDK标准类。
  • Java类依赖或者间接依赖的只有接口或者JDK标准类。

如下SlayDragonQuest就是POJO类。

/**
 * Quest.java
 */
public interface Quest {
    void embark();
}

/**
 * SlayDragonQuest.java
 */
public class SlayDragonQuest implements Quest{

    private final PrintStream mStream;

    public SlayDragonQuest(PrintStream stream) {
        this.mStream = stream;
    }

    public void embark() {
        mStream.println("embarking on quest to slay the dragon");
    }
}

POJO具备的好处是什么呢?

  • 易复用。

作为一个Androider,其实很容易举例子。界面相关的代码很难复用到其他系统里。界面类必须是Activity或者Fragment的子类。Activity和Fragment是AOSP定义实现的类。其他系统如果没有这两个类及对应生命周期的实现,那么就无法直接使用Android界面类代码。 可以看上面示例代码。Quest和SlayDragonQuest是POJO。他们既可以使用在Spring环境中,也可以使用在其他环境中。这种灵活性降低了复用难度。

  • 可测试/易测试

POJO类不会涉及到第三方类,易于构造/虚拟POJO类的运行环境。因此,POJO就具备可测性,测试难度也比较低。例如,上例中POJO的测试代码如下。

public class SlayDragonQuestTest {
    public static void main(String[] args) throws Exception{
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(1024);
        PrintStream stream = new PrintStream(outputStream);
        SlayDragonQuest quest = new SlayDragonQuest(stream);
        quest.embark();
        stream.close();
        try {
            String log = outputStream.toString("UTF-8");
            System.out.println(log);
            System.out.println(log.equals("embarking on quest to slay the dragon\n")?"success!":"failed!");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

    }
}

POJO对象对继承链及引用类型都有限制。Spring在简化继承链、简化引用类型两个方面都有设计和实现。

Spring使用切面思想降低继承使用率

使用第三方类作基类的一个场景是:第三方类将通用的功能都实现了,子类只要继承了第三方类,那么子类可以直接具备这些功能。这个场景可以用切面手法来替代。举一个实际的例子。

古时候骑士会作很多冒险活动。吟游诗人会用诗歌记载骑士的冒险活动。诗歌越传越广,骑士也就广味认知。

有两种方式实现这个需求。

//非POJO的方式。

//具备通用功能的类
public class LogRecord {
    public void logBeforeQuest() {
        ...
    }

    public void logAfterQuest() {
        ...
    }

    public void quest() {
        logBeforeQuest();
        actQuest();
        logAfterQuest();
    }

    public void actQuest() {
        //子类改写
    }
}

public class Quest extends LogRecord {
    public void actQuest() {
        System.out.println("quest");
    }
}

上例中Quest不再是POJO。复用/测试这个类必须考虑LogRecord的实现。

//POJO的方式

//具备通用功能的类
public class LogRecord {
    public void logBeforeQuest() {
        ...
    }

    public void logAfterQuest() {
        ...
    }
}

public class Quest extends LogRecord {
    public void quest() {
        System.out.println("quest");
    }
}

<aop:config>
    <aop:aspect ref="logRecord">
        <aop:pointcut id="watchpoint" expression="execution(* *.quest(..))"/>
        <aop:before pointcut-ref="watchpoint" method="logBeforeQuest" />
        <aop:after pointcut-ref="watchpoint" method="logAfterQuest" />
    </aop:aspect>
</aop:config>

上例中Quest仍然是POJO类。对Quest的复用及测试都比非POJO形式简单。

Spring使用控制反转思想引导开发者面向接口开发

对象的创建及销毁不是由使用者执行的而是由其他人来执行的,这个现象就是控制反转。如下例。

public interface MediaPlayer {
    void play();
}

public class MediaPlayerImpl implements MediaPlayer {
    public void play() {
        //...
    }
}

//控制反转
public class CDPlayerTestIoC {
    @Autowired
    private MediaPlayer player;

    public void play() {
        //player在使用前不需要创建
        player.play();
    }
}

//非控制反转
public class CDPlayerTestNonIoC {
    private MediaPlayer player;

    public void play() {
        player = new MediaPlayerImpl();//player在使用前必须创建
        player.play();
    }
}

显而易见,CDPlayerTestIoC复用/测试的难度小于CDPlayerTestNonIoC。

  • 只有普通类(非接口、非抽象类)才可以实例化,接口不能实例化。因此,在非控制反转场景下,CDPlayerTestNonIoC必须依赖MediaPlayerImpl。CDPlayerTestNonIoC不是POJO。
  • CDPlayerTestIoC不需要考虑player创建的问题。因此,可以不考虑具体实现,而是针对接口设计编程。CDPlayerTestIoC是POJO。

不能说IoC与面向接口是强相关。但是IoC存在的前提下,可以降低面向接口编程的难度。真实使用Spring的项目,面向接口设计开发是常态。

Spring学习重点

  • 切面的使用方法
  • 控制反转的使用方法
  • 与切面及控制反转相关的概念理解
  • 一个使用Spring的J2SE应用案例。
  • 一个使用Spring的Web应用案例。
  • 一个使用Spring的后台应用案例。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值