0x00 参考

本笔记直接参考或引自如下链接文章:

https://www.w3cschool.cn/wkspring/

http://c.biancheng.net/spring/

0x01 Spring简介

Spring是一个轻量级的Java Web开发框架,是分层的Java SE/EE full-stack轻量级开源框架,以IoC(Inverse of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)为内核,使用基本的JavaBean完成以前只可能由EJB完成的工作,取代了EJB臃肿和低效的开发模式。

Spring的优点如下:

  1. 方便解耦,简化开发:Spring就是一个大工厂,可以将所有对象的创建和依赖关系的维护交给Spring管理;
  2. 方便集成各种优秀框架:Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如Struts2、Hibernate、MyBatis等)的直接支持;
  3. 降低Java EE API的使用难度:Spring对Java EE开发中非常难用的一些API(JDBC、JavaMail、远程调用等)都提供了封装,使这些API应用的难度大大降低;
  4. 方便程序的测试:Spring支持JUnit4,可以通过注解方便地测试Spring程序;
  5. AOP编程的支持:Spring提供面向切面编程,可以方便地实现对程序进行权限拦截和运行监控等功能;
  6. 声明式事务的支持:只需要通过配置就可以完成对事务的管理,而无须手动编程;

0x02 Spring体系结构

Spring框架采用分层架构,根据不同的功能被划分成了多个模块,这些模块大体可分为Data Access/Integration、Web、AOP、Aspects、Messaging、Instrumentation、Core Container和Test,如图:

Core Container(核心容器)

Spring的核心容器是其他模块建立的基础,由Beans模块、Core核心模块、Context上下文模块和Expression Language表达式语言模块组成,具体介绍如下:

  • Core模块:提供了框架的基本组成部分,包括IoC和依赖注入功能;
  • Beans模块 :提供BeanFactory,是工厂模式的经典实现,Spring将管理对象称为Bean;
  • Context模块:是在Core和Beans模块的基础上建立起来的,以一种类似于JNDI注册的方式访问对象,是访问定义和配置任何对象的媒介。ApplicationContext接口是上下文模块的焦点;
  • SpEL模块:提供了强大的表达式语言,用于在运行时查询和操作对象图;

它们之间的完整依赖关系如下:

Data Access/Integration(数据访问/集成)

数据访问/集成层包括JDBC、ORM、OXM、JMS和Transactions模块(注:JDBC=Java Data Base Connectivity,ORM=Object Relational Mapping,OXM=Object XML Mapping,JMS=Java Message Service),它们的细节如下:

  • JDBC模块:提供了JDBC抽象层,大幅度减少了在开发过程中对数据库操作的编码;
  • ORM模块:提供了对流行的对象关系映射API的集成,包括JPA、JDO和Hibernate等。通过此模块可以让这些ORM框架和spring的其它功能整合,比如前面提及的事务管理;
  • OXM模块:提供了一个支持对象/XML映射的抽象层实现,如JAXB、Castor、XMLBeans、JiBX和XStream;
  • JMS模块:指Java消息服务,包含的功能为生产和消费的信息。从Spring 4.1开始,集成了spring-messaging模块;
  • Transactions事务模块:为实现特殊接口类及所有的POJO支持编程式和声明式事务管理(注:编程式事务需要自己写beginTransaction()、commit()、rollback()等事务管理方法,声明式事务是通过注解或配置由spring自动处理,编程式事务粒度更细);

Web模块

Spring的Web层包括Web、Servlet、Struts和Portlet组件,具体介绍如下:

  • Web模块:提供面向Web的基本功能和面向Web的应用上下文,比如多部分(multipart)文件上传功能、使用Servlet监听器初始化IoC容器等。它还包括HTTP客户端以及Spring远程调用中与web相关的部分;
  • Servlet模块:包括Spring模型—视图—控制器(MVC)实现Web应用程序;
  • MVC模块:为Web应用提供了模型视图控制(MVC)和REST Web服务的实现。Spring的MVC框架可以使领域模型代码和Web表单完全地分离,且可以与Spring框架的其它所有功能进行集成;
  • WebSocket模块:为WebSocket-based提供了支持,而且在Web应用程序中提供了客户端和服务器端之间通信的两种方式;
  • Struts模块:包含支持类内的Spring应用程序,集成了经典的Struts Web层;
  • Portlet模块:提供了在Portlet环境中使用MVC实现,类似Web-Servlet模块的功能,并反映了spring-webmvc模块的功能;

其他模块

Spring的其他模块还有 AOP、Aspects、Instrumentation 以及 Test 模块,具体介绍如下:

  • AOP模块:提供了面向切面编程实现,允许定义方法拦截器和切入点,将代码按照功能进行分离,以降低耦合性;
  • Aspects模块:提供与AspectJ的集成,是一个功能强大且成熟的面向切面编程(AOP)框架;
  • Instrumentation模块:提供了类工具的支持和类加载器的实现,可以在特定的应用服务器中使用;
  • Test模块:支持Spring组件使用JUnit或TestNG框架的测试;
  • Messaging模块:为STOMP提供了支持作为在应用程序中WebSocket子协议的使用。它也支持一个注解编程模型,它是为了选路和处理来自WebSocket客户端的STOMP信息;

0x03 Spring开发环境准备

使用Spring框架时,只需将Spring的四个基础包和commons-logging包复制到项目的lib目录并发布到类路径中即可。

Spring相关包下载地址:http://repo.spring.io/simple/libs-release-local/org/springframework/spring/

commons-logging包下载地址:http://commons.apache.org/proper/commons-logging/download_logging.cgi

本地环境用的:spring-framework-4.1.6.RELEASE-dist,commons-logging-1.2。

0x04 Spring目录结构和基础jar包

解压并打开我们下载的spring-framework-4.1.6.RELEASE-dist可看到Spring有如下目录:

名称 作用
docs 包含 Spring 的 API 文档和开发规范
libs 包含开发需要的 JAR 包和源码包
schema 包含开发所需要的 schema 文件,在这些文件中定义了 Spring 相关配置文件的约束

在libs目录中,包含了Spring框架提供的所有JAR文件,其中有四个JAR文件是Spring框架的基础包,分别对应Spring容器的四个模块,具体如下:

名称 作用
spring-core-4.1.6.RELEASE.jar 包含 Spring 框架基本的核心工具类,Spring 其他组件都要用到这个包中的类,是其他组件的基本核心。
spring-beans-4.1.6.RELEASE.jar 所有应用都要用到的,它包含访问配置文件、创建和管理 bean 以及进行 Inversion of Control(IoC)或者 Dependency Injection(DI)操作相关的所有类。
spring-context-4.1.6.RELEASE.jar Spring 提供在基础 IoC 功能上的扩展服务,此外还提供许多企业级服务的支持,如邮件服务、任务调度、JNDI 定位、EJB 集成、远程访问、缓存以及各种视图层框架的封装等
spring-expression-4.1.6.RELEASE.jar 定义了 Spring 的表达式语言。 需要注意的是,在使用 Spring 开发时,除了 Spring 自带的 JAR 包以外,还需要一个第三方 JAR 包 commons.logging 处理日志信息

0x05 第一个Spring程序——HelloWorld

在IDEA新建项目,右键项目目录->Open Module Settings->Project Settings->Libraries中添加Springframework的包和commons-logging的包。

接着在src目录下新建com.mi1k7ea包,在其中新建HelloWorld.java和MainApp.java文件。

HelloWorld.java,是一个Bean:

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.mi1k7ea;

public class HelloWorld {
private String message;

public void setMessage(String message){
this.message = message;
}

public void getMessage(){
System.out.println("Your Message : " + message);
}
}

MainApp.java,:

1
2
3
4
5
6
7
8
9
10
11
12
package com.mi1k7ea;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
}
}

关于主要程序有以下两个要点需要注意:

  • 第一个是我们使用框架的ClassPathXmlApplicationContext()函数来创建应用程序的上下文。这个API加载beans的配置文件并最终基于所提供的API,它处理创建并初始化所有的对象,即在配置文件中提到的beans;
  • 第二个是使用已创建的上下文的getBean()方法来获得所需的bean。这个方法使用bean的ID返回一个最终可以转换为实际对象的通用对象。一旦有了对象,你就可以使用这个对象调用任何类的方法;

另外,还需要在src目录下创建一个Bean的XML配置文件,作为粘合Bean的粘合剂即类。Spring的配置文件名称是可以自定义的,一般情况下是命名为applicationContext.xml(或bean.xml),这里我们定义为Beans.xml,其中beans标签中的各个属性是Spring的约束配置:

1
2
3
4
5
6
7
8
9
<?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-3.0.xsd">
<bean id="helloWorld" class="com.mi1k7ea.HelloWorld">
<property name="message" value="mi1k7ea"/>
</bean>
</beans>

Beans.xml用于给不同的Bean分配唯一的ID,并且控制不同值的对象的创建,而不会影响Spring的任何源文件。这里给com.mi1k7ea.HelloWorld这个Bean分配了值为helloWorld的id,在MainApp主程序中通过传入id参数调用getBean()即可成功获取到指定的Bean。

运行输出如下,可以看到,在程序执行时对象的创建并不是通过new一个类完成的,而是由Spring容器管理实现的,这就是后面讲到的Spring IoC容器思想的工作机制: