Spring 框架的结构
Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架
下图是Spring官方给出的Spring框架的结构图
从图中我们可以看到Spring的四大部分:核心容器(container)、AOP模块、Web模块、Data模块。
- 首先看核心容器,从核心俩字我们可以看出,这是Spring最重要的部分。主要的功能是实现了控制反转(IOC)与依赖注入(DI)、Bean配置、加载以及生命周期的管理。
- AOP模块:负责Spring的所有AOP(面向切面)的功能。
- Web模块:扩展了Spring的Web功能。使其符合MVC的设计规范,最重要的是提供了Spring MVC的容器。
- Data模块:提供了一些数据相关的组件:包括JDBC、orm(对象关系映射)、事务操作、oxm(对象xml映射)、Jms(Java消息服务)。
各个模块介绍
- spring core:提供了框架的基本组成部分,包括控制反转(Inversion of Control,IOC)和依赖注入(Dependency Injection,DI)功能。
- spring beans:提供了BeanFactory,是工厂模式的一个经典实现,Spring将管理对象称为Bean。
- spring context:构建于 core 封装包基础上的 context 封装包,提供了一种框架式的对象访问方法。
- spring jdbc:提供了一个JDBC的抽象层,消除了烦琐的JDBC编码和数据库厂商特有的错误代码解析, 用于简化JDBC。
- spring aop:提供了面向切面的编程实现,让你可以自定义拦截器、切点等。
- spring Web:提供了针对 Web 开发的集成特性,例如文件上传,利用 servlet listeners 进行 ioc 容器初始化和针对 Web 的 ApplicationContext。
- spring test:主要为测试提供支持的,支持使用JUnit或TestNG对Spring组件进行单元测试和集成测试。
我们可以看到Spring给我们提供的模块相当的丰富,无论是持久层、业务层还是控制层都有所涉及。
- Spring几乎包揽除了业务逻辑之外的的所有工作,包括日志管理、事务管理、Bean管理、安全管理等。
- Spring致力于全套的Java问题的解决方案,在所有的Java可以涉足的领域,Spring都会提供相应的支持。(即使没有支持,也会让我们去整合)
- 与第三方框架的整合。在我的理解中Spring框架就像一个插线板,而第三方框架就相当于插头,可以轻易地与它组合在一起。需要的时候就插上去,不需要的时候就拔掉,相当的方便。
既然Spring如此的方便,那么它又是如何做到的呢?
很简单,通过两点:
- 控制反转(IOC)
- 面向切面编程(AOP)
为了降低Java开发的复杂性,Spring采取了以下4种关键策略
- 基于POJO的轻量级和最小侵入性编程;
- 通过依赖注入和面向接口实现松耦合;
- 基于切面和惯例进行声明式编程;
- 通过切面和模板减少样板式代码。
Spring 框架中都用到了哪些设计模式?
- 工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;
- 单例模式:Bean默认为单例模式。
- 代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
- 模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
- 观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现–ApplicationListener。
使用 Spring 有哪些方式?
- 作为一个成熟的 Spring Web 应用程序。
- 作为第三方 Web 框架,使用 Spring Frameworks 中间层。
- 作为企业级 Java Bean,它可以包装现有的 POJO(Plain Old Java Objects)。
- 用于远程使用。
控制反转(IOC)/依赖注入(DI)
既然说到控制反转,那么我们不禁要问什么控制被反转了?
答案是:我们对对象的控制权被反转了。我们将对象的控制交给了Spring的容器。
那么问题又来了,什么是Spring的容器?
简单的说,Spring容器就是一个超级大工厂,负责创建、管理所有的Java对象,这些Java对象被称为Bean。Spring容器管理着容器中Bean之间的依赖关系,Spring使用一种被称为“依赖注入”的方式来管理Bean之间的依赖关系。
什么又是依赖注入呢?
依赖注入(DI)就是控制反转的一种实现形式,Spring容器也是通过这种形式管理Bean的。
Spring容器如何做到替你管理这些bean的呢?
工厂模式。
Spring框架费了九牛二虎之力创建一个Spring容器去帮我们管理这些Bean又有什么好处呢?
其实和工厂模式的好处差不多:
- 解除硬编码耦合,利于项目升级和维护;
- 简化了对象的管理,使我们更加专注于业务操作;
聊完了控制反转我们再来看看Spring框架的另一项关键技术AOP。
面向切面编程(AOP)
什么是面向切面编程?
面向切面编程:在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。
这句话读完估计跟没读没什么区别,还是没懂。下面我们来看一张图:
从图中我们可以看出:我们每写一个业务功能,都需要判断权限、记录日志、提交事务、这些逻辑是不是都是重复的呀,这相当于什么呢?相当于我们前面说的脏活累活,这都不是我们的重点,我们的重点是业务逻辑,就是说我们需要把整体框架搭好,实际编写的时候只需要将我们的业务代码切入到框架之中,就行了。
原理:代理模式。
为什么需要AOP?
AOP专门用于处理系统中分布于各个模块或者不同方法中的交叉关注点的问题。比如:在程序中,我们常常需要处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等,AOP是一种非常常用的解决方案。
面向切面编程对我们来说有什么好处?
- 减少重复;
- 专注业务;
注意:面向切面编程只是面向对象编程的一种补充。
优点
- Bean的统一管理,降低了对象之间的耦合
- 对主流的框架提供了很好的集成支持
- 提供众多组件,事务管理,JDBC等
- 具有高度可开放性,开发者可以自由选择Spring部分或全部
- 主要使用工厂模式和代理模式。
- 低侵入,代码污染极低。(我们不会因为用了spring而影响我们的正常的业务逻辑)
- AOP的很好支持,方便面向切面编程(AspectJ)。
Spring MVC
聊完了Spring,我们来看看Spring在web方面的应用Spring MVC。
MVC
首先我们来看什么是mvc?
大家知道在jsp里面也是可以写java代码的,但是如果我们这样做就会有一个问题,就是代码全部都杂糅在一起,无论是阅读还是修改都将变得十分的困难。
MVC是模型(model)-视图(view)-控制器(controller)的缩写,他将我们的程序分为个三部分,页面、控制层、模型层。这样使我们的程序的逻辑更清晰,更容易维护。
它以将我们的业务逻辑、数据与界面显示分离,将众多的业务逻辑聚集到一个部件里面,在需要改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑,提高编码效率。
Spring MVC
Spring MVC 是MVC结构在Spring框架中的一种表现形式。下面我们来看一下Spring MVC的结构:
由图可知,Spring MVC的具体流程如下:
- 首先用户发送请求————>前端控制器(DispatcherServlet),前端控制器根据请求信息(如URL)来决定选择哪一个页面控制器进行处理并把请求委托给它,即以前的控制器的控制逻辑部分;
- 页面控制器接收到请求后,进行功能处理,首先需要收集和绑定请求参数到一个对象,并进行验证。然后将命令对象委托给业务对象进行处理;处理完毕后返回一个ModelAndView(模型数据和逻辑视图名);
- 前端控制器收回控制权,然后根据返回的逻辑视图名,选择相应的视图进行渲染(ViewResolver),并把模型数据传入以便视图渲染。
- 前端控制器再次收回控制权,将响应返回给用户;
大家可以把这想象成自己去医院看病的流程,前端控制器(DispatcherServlet)在这里就相当于一个医院前台的作用,我们看病时首先需要先到前台挂号,然后根据病情被分配到不同的科室,看完病之后还要再到前台去付钱拿药。
Spring和Spring MVC容器之间的关系
我们理解了Spring和Spring MVC,这里我们讨论一下Spring容器和Spring MVC容器之间的关系?
首先要说明的是:一个项目中,容器不一定只有一个。
Spring容器用于管理Spring中的Bean,而Spring MVC容器用于管理Spring MVC中的Bean。Spring是父容器,Spring MVC是其子容器。
并且在Spring MVC子容器中注册的Bean可以引用Spring父容器中注册的Bean,但在Spring容器中注册的Bean却不能引用Spring MVC容器中注册的Bean。
这句话听起来有点绕,我们可以看一下下面这张图,大家可以吧spring容器中的bean理解为全局变量,吧spring MVC容器中的bean理解为局部变量。在方法体中可以访问局部变量和全局变量,但是在方法外,就只能访问全局变量,是不能访问局部变量的。
这里我们要区分一下哪些bean是需要被SpringMVC管理的,最主要就是控制器(Controller),因为它需要与前端控制器交互。其他的可以都交给spring的容器管理。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。