Java使得以模块化构建复杂应用系统成为可能,它为Applet而来,但为组件化而留。

Spring是一个开源的框架,最早由Rod Johnson创建。Spring是为了解决企业级应用开发的复杂性而创建的,但Spring又不仅仅局限于服务器端开发,任何Java应用都能在简单性、可测试性和松耦合性等方面从Spring中获益。

Spring可以做很多事情,但归根结底,支撑Spring的仅仅是少许的基本理念,所有的理念都可以追溯到Spring最根本的使命:简化Java开发。

为了降低Java开发的复杂性,Spring采取了一下4个关键策略:

  1. 基于POJO的轻量级和最小侵入性编程
  2. 通过依赖注入和面向接口实现松耦合
  3. 基于切面和惯例进行声明室编程
  4. 通过切面和模板减少样式代码

1、基于POJO的最小侵入式编程

在Java编程中,很多框架通过强迫应用继承它的类或实现它的接口从而让应用和框架绑死。典型的例子实现一个EJB2 的无状态回话Bean。

package com.test.session;

import javax.ejb.SessionBean;
import javax.ejb.SessionContext; public class HelloWorldBean implements SessionBean {
public void ejbActive(){}
public void ejbPassivate(){}
public void ejbRemove(){}
public void setSessionContext(SessionContext ctx){}
public String sayHello(){
return "Hello World";
}
public void ejbCreate(){}
}

SessionBean接口允许你实现若干个生命周期的回调方法以便参与到EJB的生命周期内。HelloWorldBean的大部分代码是为了EJB而编写的。这些重量级的框架都存在一个问题:强迫开发者编写大量的冗余代码、应用和框架绑定,并且难以测试代码。

Spring竭力避免因自身API而扰乱你的应用代码。Spring 不会强迫你实现Spring规范的接口或继承Spring规范的类。在Spring框架中,它的类没有任何痕迹表明你使用了Spring。最坏的场景是,一个类或许会使用Spring注解,但它依然是POJO。

采用Spring把HelloWorldBean重写,应该是这样子的。

package com.test.session;

public class HelloWorldBean {
public String sayHello() {
return "Hello World";
}
}

HelloWorldBean没有实现、继承或导入任何与Spring API相关的东西,HelloWorldBean只是一个普通的Java对象。

尽管形式简单,但是POJO一样可以拥有魔力。Spring赋予POJO魔力的方式之一就是通过依赖注入来装配它们。

2、依赖注入

依赖注入 可能让人望而生畏,事实证明依赖注入并不像它听上去复杂。在项目中应用依赖注入,你会发现代码更简单、更易理解和测试。

任何有实际意义的应用都是由两个或更多地类组成的,它们之间相互协作来完成特定的业务逻辑。通常,每个对象负责管理和自己协作的对象(它依赖的对象)引用,这就难免导致了高度耦合和难以测试。

例如knights类

package com.test.knights;

public class DamselRescuingKnight implements Knight {
private RescueDamselQuest quest; public DsmselRescuingKnight() {
quest = new RescueDamselQuest();
} public void embarkOnQuest() throws QuestException {
quest.embrak();
}
}
DamselRescuingKnight在构造函数中自行创建了RescueDamselQuest,这使得二者耦合在一起;更糟糕的是,为这个DamselRescuingKnight编写单元测试将出奇的困难。在这样的测试中,你必须保证当embarkOnQuest方法被调用时,embrak 方法也被调用,但是没有一个简明的方式能够实现这点。

耦合的两面性:一方面耦合的代码难以测试、复用和理解;另一方面,一定的耦合又是必须的,为了完成特定功能不同的类必须以适当的方式进行交互。

通过依赖注入,对象的依赖关系将由负责协调系统中各个对象的第三方组件在创建对象时设定。对象无需创建和管理它们的依赖关系——依赖关系会被自动注入到需要它们的对象中去。

package com.test.knights;

public class BraveKnight implements Knight {
private Quest quest; public BraveKnight(Quest quest) {
this.quest = quest;
} public void embarkOnQuest() throws QuestException {
quest.embrak();
}
}

此时的BraveKnight并没有自行创建Quest,而是在构造函数时把探险任务作为构造器参数传入,这是依赖注入的方式之一,即构造器注入。

更重要的是,它传入的类型是Quest,这可以是个接口,所以BraveKnight可以相应RescueDamselQuest、SlayDragonQuest...等任何Quest实现。

对依赖进行替换的最常用方法之一,就是测试的时候使用mock实现。你无法充分测试DamselRescuingKnight,因为它是紧耦合的,但可以轻松测试BraveKnight,只需要给它提供一个Quest的mock实现。

package com.test.knights;

import static org.mockito.Mockito.*;
import org.junit.Test; public class BraveKnightTest {
@Test
public volid knightShouldEmbrakOnQuest() throws QuestException {
Quest mockQuest = mock(Quest.class); BraveKnight knight = new BraveKnight(mockQuest);
knight.embarkOnQuest(); verify(mockQuest, time(1)).embrak();
}
}

通过现有的mock对象,你可以创建一个新的BraveKnight实例,通过构造器注入mock Quest。当调用embarkOnQuest()方法时,你可以要求Mockito框架验证Quest的mock实现的embrack 方法仅仅被调用了一次。

创建应用插件之间协作的行为通常称之为装配。Spring有多种装配Bean的方式,采用XML是最常用的方式。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id = "knight" class = "com.test.knight.BraveKnight">
<constructor-arg ref = "quest" />
</bean> <bean id = "quest" class = "com.test.knight.SlayDragonQuest" />
</beans>

现在已经声明了BraveKnight和Quest的关系,你只需要装在XML配置文件,并把应用启动起来。

Spring通过应用上下文(Application Context)装载Bean的定义并将它们组装起来。

package com.test.knights;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ClassPathXmlApplicationContext; public class KnightMain {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("knights.xml");
Knight knight = (Knight) context.getBean("knight");
knight.embarkOnQuest();
}
}

注意Knight这个类型完全没有意识到它所要执行的quest(例如com.test.knight.SlayDragonQuest),只有knights.xml文件知道具体的组装配置。

Spring之旅的更多相关文章

  1. 我的Spring之旅(二):为请求加入參数

    1.前言 在上一篇我的Spring之旅(一)中,我们仅仅是利用不带參数的请求返回一个网页或一段json,在实际的B/S.C/S网络交互中,请求中须要自己定义的參数.本篇将简单地为之前的请求加入參数. ...

  2. Spring之旅第六篇-事务管理

    一.什么是事务 什么是事务(Transaction)?事务是数据库中的概念,是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit). 有个非常经典的转账问题:A向B转款1000元,A转出成 ...

  3. Spring之旅(2)

    Spring简化Java的下一个理念:基于切面的声明式编程 3.应用切面 依赖注入的目的是让相互协作的组件保持松散耦合:而AOP编程允许你把遍布应用各处的功能分离出来形成可重用的组件. AOP面向切面 ...

  4. Spring学习笔记—Spring之旅

    1.Spring简介     Spring是一个开源框架,最早由Rod Johnson创建,并在<Expert One-on-One:J2EE Design and Development> ...

  5. SpringInAction读书笔记--第1章Spring之旅

    1.简化Java开发 Spring是一个开源框架,它的根本使命在于简化java开发.为了降低java开发的复杂性,Spring采取了以下4种关键策略: 基于POJO的轻量级和最小侵入性编程      ...

  6. Spring之旅第五篇-AOP详解

    一.什么是AOP? Aspect oritention programming(面向切面编程),AOP是一种思想,高度概括的话是“横向重复,纵向抽取”,如何理解呢?举个例子:访问页面时需要权限认证,如 ...

  7. Spring之旅第四篇-注解配置详解

    一.引言 最近因为找工作,导致很长时间没有更新,找工作的时候你会明白浪费的时间后面都是要还的,现在的每一点努力,将来也会给你回报的,但行好事,莫问前程!努力总不会有错的. 上一篇Spring的配置博客 ...

  8. Spring之旅第三篇-Spring配置详解

    上一篇学习了IOC的概念并初步分析了实现原理,这篇主要学习Spring的配置,话不多说,让我们开始! 一.Bean元素配置 1.1 基本配置 看一个最基本的bean配置 <bean name=& ...

  9. Spring之旅第二篇-Spring IOC概念及原理分析

    一.IOC概念 上一篇已经了解了spring的相关概念,并且创建了一个Spring项目.spring中有最重要的两个概念:IOC和AOP,我们先从IOC入手. IOC全称Inversion of Co ...

随机推荐

  1. ABP入门系列(1)——学习Abp框架之实操演练

    作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...

  2. 【探索】无形验证码 —— PoW 算力验证

    先来思考一个问题:如何写一个能消耗对方时间的程序? 消耗时间还不简单,休眠一下就可以了: Sleep(1000) 这确实消耗了时间,但并没有消耗 CPU.如果对方开了变速齿轮,这瞬间就能完成. 不过要 ...

  3. 采用MiniProfiler监控EF与.NET MVC项目(Entity Framework 延伸系列1)

    前言 Entity Framework 延伸系列目录 今天来说说EF与MVC项目的性能检测和监控 首先,先介绍一下今天我们使用的工具吧. MiniProfiler~ 这个东西的介绍如下: MVC Mi ...

  4. python爬取github数据

    爬虫流程 在上周写完用scrapy爬去知乎用户信息的爬虫之后,github上star个数一下就在公司小组内部排的上名次了,我还信誓旦旦的跟上级吹牛皮说如果再写一个,都不好意思和你再提star了,怕你们 ...

  5. tomcat开发远程调试端口以及利用eclipse进行远程调试

    一.tomcat开发远程调试端口 方法1 WIN系统 在catalina.bat里:  SET CATALINA_OPTS=-server -Xdebug -Xnoagent -Djava.compi ...

  6. 【项目管理】GitHub使用操作指南

    GitHub使用操作指南 作者:白宁超 2016年10月5日18:51:03> 摘要:GitHub的是版本控制和协作代码托管平台,它可以让你和其他人的项目从任何地方合作.相对于CVS和SVN的联 ...

  7. 漫谈C#编程语言在游戏领域的应用

    0x00 前言 随着微软越来越开放,C#也变得越来越吸引人们的眼球.而在游戏行业中,C#也开始慢慢地获得了关注.这不, 网易绝代双娇手游团队已经全面使用.Net Core支持前后端统一C#开发,跨平台 ...

  8. C#创建、安装、卸载、调试Windows Service(Windows 服务)的简单教程

    前言:Microsoft Windows 服务能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序.这些服务可以在计算机启动时自动启动,可以暂停和重新启动而且不显示任何用户界面.这 ...

  9. Collection集合

    一些关于集合内部算法可以查阅这篇文章<容器类总结>. (Abstract+) Collection 子类:List,Queue,Set 增: add(E):boolean addAll(C ...

  10. ADFS3.0与SharePoint2013安装配置(原创)

    现在越来越多的企业使用ADFS作为单点登录,我希望今天的内容能帮助大家了解如何配置ADFS和SharePoint 2013.安装配置SharePoint2013这块就不做具体描述了,今天主要讲一下怎么 ...