Springの奇妙冒险——第一卷:Spring和IoC的初体验
Spring的奇妙冒险——第一卷:Spring和IoC的初体验
本卷预告
- 什么是Spring
- 控制反转(IoC)有什么作用?
- 搭建Spring-IoC框架
什么是framework(框架)
框架就是一些类和接口的集合,通过这些类和接口协调来完成一系列的程序实现。JAVA框架可以分为三层:表示层,业务层和物理层。框架又叫做开发中的半成品,它不能提供整个WEB应用程序的所有东西,但是有了框架,我们就可以集中精力进行业务逻辑的开发而不用去关心它的技术实现以及一些辅助的业务逻辑。大家熟知的Structs和Spring就是表示层和业务层框架的强力代表。
架构发展历程
随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进:
这部分借鉴dubbo的背景介绍,这是原文地址:http://dubbo.apache.org/en-us/docs/user/preface/background.html,不过现在这篇介绍应该是找不到了。
单一应用架构
当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。
此时我们使用的架构便是:Servlet+JSP+JavaBean。
垂直应用架构(前后端分离)
当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,提升效率的方法之一是将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(也就是我们熟悉的MVC)是关键。
分布式服务架构
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。
流动计算架构
当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA面向服务架构)是关键。
什么是Spring
先贴几个spring的网站地址在下方方便学习:
- 中文文档:https://github.com/DocsHome/spring-docs/blob/master/SUMMARY.md
- 官网地址:https://spring.io/projects/spring-framework#overview
- Spring仓库,压缩包文件下载地址:https://repo.spring.io/list/libs-snapshot-local/org/springframework/spring/
- 源码地址:https://github.com/spring-projects/spring-framework
Spring是一个轻量级Java开发框架,最早由Rod Johson创建,目的是为了解决企业级应用开发的业务逻辑和其他各层的耦合问题。它是一个分层的JavaSE/JavaEE full-stack(一站式)轻量级开源框架,为开发Java应用程序提供了全面的基础架构支持。Spring负责基础架构,因此Java开发者可以专注于应用程序的开发。
Spring最根本的使命是解决企业级应用开发的复杂性,即简化Java开发。Spring可以做很多事情,它为企业级开发提供了丰富的功能,但是这些功能的底层都依赖它的两个核心特性:依赖注入(dependency injection,DI)和面向切面编程(aspect-oriented programming,AOP)。
总结:
-
Spring是一个轻量级Java开发的开源框架;
-
Spring为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题
-
Spring是一个
IOC(控制反转)
和AOP(面向切面)
的容器(包含并管理应用对象的生命周期)
框架。(如果有问题问Spring是一个什么的容器框架,只有一个空时回答IOC控制反转,因为AOP面向切面是基于IOC控制反转实现的)
DI(依赖注入)和IOC(控制反转)
Spring的两个核心特性是DI依赖注入和AOP面向切面编程,Spring是一个IOC控制反转和AOP面向切面的容器框架。那么,DI和IOC是什么关系呢?
从上面这句话我们可以知道,IOC和DI是从不同的角度去描述同一件事,IOC是从容器的角度描述的,而DI是从应用程序的角度来描述的,所以,IOC是依赖倒置原则的设计思想,而DI是具体的实现方式。
看完这段可能有点晕,结合下面的IOC介绍或许就可以清晰一些了。
IOC(Inversion of Control控制反转)
IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies (that is, the other objets they work with) only through constructor arguments, arguments to a factory method, or properties that are set om the object instance after it is constructed or returned from a fundamentally the inverse(hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes or a mechanism such as the Service Locator pattern.
上面是从官方文档中抄写的对于IoC的介绍,大意是说IoC与依赖注入DI同理。这是一个通过依赖,注入对象的过程。也就是说它们所使用的对象,是通过构造函数参数、工厂方法的参数或工厂方法的构造函数或返回值的对象实例设置的属性,然后容器在创建bean的时候注入这些需要的依赖。这个过程相对于普通创建对象是反向的(所以称作控制反转)。bean本身通过直接构造类来控制依赖关系的实例化或位置或提供诸如服务定位器模式之类的机制。
我自己的理解是:如果一个类A的功能实现需要借助于类B,那么就称类B是类A的依赖,如果在类A的内部去实例化类B,那么两者之间会出现较高的耦合,一旦类B出现了问题,类A也需要进行改造,如果这样的情况较多,每个类之间都有很多依赖,那么就会出现牵一发而动全身的情况,程序也就会极难维护,并且很容易出现问题。要解决这个问题,就要把A类对B类的控制权抽离出来,交给一个第三方去做,把控制权反转给第三方,就称作控制反转(IOC Inversion Of Control),控制反转是一种思想,是能够解决问题的一种可能的结果,而依赖注入(Dependency Injection)就是其最典型的实现方法。
这里体现了IoC的两个原则:
- 接口分离原则(ISP):模块间通过抽象接口隔离开
- 依赖倒置原则(DIP):下层依赖上层,IoC是DIP的设计原理
说白了,IoC就是引入DI实现对象由Spring创建、管理和装配。
所以他们的关系记住一句话:依赖注入(DI)实现了控制反转(IoC)
IoC容器
随着依赖注入(DI)的频繁使用,要实现控制反转(IOC),会有很多重复代码,甚至随着技术的发展,有更多新的实现方法和方案,那么有人就把这些实现IOC的代码打包成组件或框架,来避免人们重复造轮子。
IoC的优点
- 解决变更所带来的加大异常风险和导致系统维护性差的问题(解决办法:解耦合)
- 集中管理,因为类都是由Spring统一创建、管理和装配
- 功能可复用(减少对象的创建和内存消耗) ,值得一提的是Spring默认创建的bean都是单例的
- 使得程序的整个体系结构可维护性、灵活性、扩展性变高
Spring的模块划分图
- Test:Spring的单元测试模块
- Core Container:核心容器模块
- AOP+Aspects:面向切面编程模块
- Instrumentation:提供了class instrumentation支持和类加载器的实现来在特定的应用服务器上所以,几乎不用
- Messaging:包括一系列的用来映射消息到方法的注解,几乎不用
Spring的优点
- Spring通过DI依赖注入和AOP面向切面编程以及消除样板式代码来简化企业级Java的开发;
- Spring框架之外还存在一个构建在核心代码框架之上的庞大生态圈,他将Spring扩展到不同的领域,如web服务、NoSQL等等;
- 低侵入式设计(侵入式:必须继承接口或实现类),代码的污染极低;
- 独立于各种应用服务器,基于Spring框架的应用,可以真正实现一次写入多处运行的承诺;
- Spring的IOC(控制反转)容器降低了业务对象替换的复杂性,提高了组件之间的解耦;
- Spring的AOP(面向切面编程)支持允许将一些通用任务如安全、事务、日志等进行集中式处理,从而提供更好的复用;
- Spring的ORM和DAO提供了与第三方持久层框架的良好整合,并简化了底层的数据库访问;
- Spring的高度开放性,并不强制应用完全依赖于Spring,开发者可以选用Spring框架的部分或全部,例如流行的SSM框架;
- 任何一个语言或框架想要立于不败之地,那么很重要的就是它的生态。
顺便说一下,Spring是不重复造轮子的,现在的官方文档推荐直接使用基于 Spring Boot 来编写应用程序,由此开始使用Spring框架,后续Spring Cloud等基本也都是以Spring Boot为基础做的开发。但是我们还是先从Spring的基础开始了解,再定一个小目标,开始Spring Boot的奇妙冒险。
Spring项目构建
我们先使用jar包的方式构建一个Spring项目,我们直接创建一个java项目就行了:
-
导入jar包:访问Spring仓库https://repo.spring.io/list/libs-snapshotlocal/org/springframework/spring/ 下载任意版本的spring 只需要下载dist.zip这个就行,这里面包含了docs和schema
-
通过Spring的模块划分图可以看出,如果要构建一个基本的Spring项目,只需要导入核心包即可。
注意:Spring5.0报Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LgFactory
错误,导入jar包:spring-jcl-5.2.7.BUILD-SNAPSHOT.jar
解决。 -
创建几个类用于测试,比如我创建com.temp.User.java,里面有属性,有无参、有参构造函数、有setter和getter方法,重写了toString方法等等
-
准备配置文件如“spring.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://w ww.springframework.org/schema/beans/spring‐beans.xsd"> <bean class="com.temp.User" id="user"></bean> </beans>
-
然后准备一个测试类
public class IocTest { @Test public void test01(){ ApplicationContext ioc=new ClassPathXmlApplicationContext("spring.xm l"); User bean = ioc.getBean(User.class); System.out.println(bean); } }
如果运行成功没有报错,说明一个Spring项目构建成功。
下卷预告
下卷主要为大家介绍Spring配置文件的详细使用以及使用xml配置文件的方式搭建一个Spring项目。