Spring的根本使命:简化JAVA开发
几个概念:
POJO:Plain Old Java Object,普通的Java对象。指只有属性、get、set等方法,不包含复杂逻辑的Java类。
JavaBean:一种可重用组件,是指符合JavaBean规范的类。JavaBean规范主要有以下几条(仅从网络信息摘取过来,有待商榷)
类必须是具体的和公共的,并且具有无参数的构造器。
提供符合一致性设计模式的公共方法将内部域暴露成员属性,set和get方法获取
属性名称符合这种模式,其他Java 类可以通过自省机制(反射机制)发现和操作这些JavaBean 的属性。
EJB:Enterprice JavaBean,是指符合Java企业级应用规范的类
为了快速开发企业级应用,Java提出了EJB,但是太重量级,并不好用;Spring技术则提供了一种方案,仅基于POJO又能实现EJB或其它企业级规范JAVA对象才有的功能,使企业级开发变得更加轻量级,简单;另外Java也看到了Spring技术的优势和好处,也使用Spring技术的原理,改进了原来的EJB,使其更加简单好用;目前为止,Spring技术还是比EJB技术更加好用。
另外,Spring还在不断进步中,移动开发、社交API集成、NoSQL数据库,云计算以及大数据等领域,Spring都一直创新,用更加高效简单的方式来提供这些领域的解决方案
Spring中把应用组件(类)也称为Bean或者JavaBean,但是Spring指的是任何POJO,所以文章中所有Bean或JavaBean不一定符合JavaBean规范,可能只是一个POJO
Spring的几个关键策略
为了简化Java开发,Spring使用了以下几个关键策略
1、基于POJO的轻量级和最小侵入编程
通常一个类应用Spring技术,不需要引用Spring;即使是最坏的情况,也只需要用到Spring注解,不会有Spring的代码出现在一个类中。从而保证应用中的类仍是POJO
2、基于依赖注入和面向接口实现松耦合
DI:Dependency Injection 依赖注入
在传统编程中,难免会有以下这种编程情景(多个类交互)
public class DamselRescuingKnight implements Knight { private RescueDamselQuest quest; public DamselRescuingKnight() { this.quest = new RescueDamselQuest(); } public void embarkOnQuest() { quest.embark(); } }
DamselRescuingKnight中,通过new 创建了一个RescueDamselQuest实例,2个类形成了紧耦合。
其中的依赖关系是DamselRescuingKnight依赖RescueDamselQuest,而且限制了embarkOnQuest方法的实现
而且,无法对DamselRescuingKnight进行单元测试,因为embarkOnQuest方法需要调用RescueDamselQuest的embark方法,而仅在这个方法内,并没有这个方法的实现
耦合的两面性:必须的(复杂逻辑必然有多个类进行交互)、过于耦合将导致难以测试、复用、难以理解
依赖注入:将对象的依赖关系交给第三方来进行创建和管理
public class BraveKnight implements Knight { private Quest quest; public BraveKnight(Quest quest) { this.quest = quest; } public void embarkOnQuest() { quest.embark(); } }
上面使用了依赖注入的一种方式:构造器注入;而且传入的是一个Quest接口,对象和依赖对象的具体实现没有耦合关系,就形成了松耦合。
而且,此情况下,可以使用mock(一种测试方式,具体自行学习)实现单元测试。
Spring可以作为一个依赖注入容器,通过不同方式注入,也有相应的配置,装配策略,留到后面讲解。
3、基于切面和惯例进行声明式编程
AOP:Aspect Oriented Programming,面向切面编程
DI负责让互相协作的组件实现松耦合,而AOP则允许把遍布程序各处的功能分离出来形成可重用组件。
可以把切面想象成很多组件上的一个外壳,借助AOP,可以使用各种功能层包裹核心业务层,以声明的方式灵活应用到系统中,核心应用中与这些功能层没有耦合,保证了POJO的简单性
例如,你的代码中可能会出现以下情景
package sia.knights; public class BraveKnight implements Knight { private Quest quest; private Minstrel minstrel; public BraveKnight(Quest quest, Minstrel minstrel) { this.quest = quest; this.minstrel = minstrel; } public void embarkOnQuest() { minstrel.singBeforeQuest(); quest.embark(); minstrel.singAfterQuest(); } }
minstrel类可以看作一个日志功能,在某个其它类中,需要调用这个日志类来记录日志,导致这个功能代码与业务代码混淆在一起
而Spring提供的AOP方案,可以通过配置文件等方式,将这个日志类的相关代码从这个业务类中去除,从而实现解耦;具体方式后面介绍
4、通过切面和模板减少样板式代码
例如:以往使用JDBC进行操作数据库时,每次操作,都有很多连接数据库,断开连接等代码和业务代码交织在一齐
而Spring则提供了如jdbcTemplate等类,对这些样板式代码进行简化