十、Spring / Spring MVC
90. 为什么要应用 spring?
1. 简介
- 目标:解决企业应用开发的复杂性
- 性能:应用根本的 JavaBean 代替 EJB,并提供了更多的企业应用性能
- 范畴:任何 Java 利用
简略来说,Spring 是一个轻量级的管制反转 (IoC) 和面向切面 (AOP) 的容器框架。
2. 轻量
从大小与开销两方面而言 Spring 都是轻量的。残缺的 Spring 框架能够在一个大小只有 1MB 多的 JAR 文件里公布。并且 Spring 所需的解决开销也是微不足道的。此外,Spring 是非侵入式的:典型地,Spring 利用中的对象不依赖于 Spring 的特定类。
3. 管制反转
Spring 通过一种称作管制反转(IoC)的技术促成了松耦合。当利用了 IoC,一个对象依赖的其它对象会通过被动的形式传递进来,而不是这个对象本人创立或者查找依赖对象。你能够认为 IoC 与 JNDI 相同——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象申请就被动将依赖传递给它。
4. 面向切面
Spring 提供了面向切面编程的丰盛反对,容许通过拆散利用的业务逻辑与零碎级服务(例如审计(auditing)和事务(transaction)治理)进行内聚性的开发。利用对象只实现它们应该做的——实现业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的零碎级关注点,例如日志或事务反对。
5. 容器
Spring 蕴含并治理利用对象的配置和生命周期,在这个意义上它是一种容器,你能够配置你的每个 bean 如何被创立——基于一个可配置原型(prototype),你的 bean 能够创立一个独自的实例或者每次须要时都生成一个新的实例——以及它们是如何互相关联的。然而,Spring 不应该被混同于传统的重量级的 EJB 容器,它们常常是宏大与轻便的,难以使用。
6. 框架
Spring 能够将简略的组件配置、组合成为简单的利用。在 Spring 中,利用对象被申明式地组合,典型地是在一个 XML 文件里。Spring 也提供了很多根底性能(事务管理、长久化框架集成等等),将应用逻辑的开发留给了你。
所有 Spring 的这些特色使你可能编写更洁净、更可治理、并且更易于测试的代码。它们也为 Spring 中的各种模块提供了根底反对。
91. 解释一下什么是 aop?
AOP(Aspect-Oriented Programming,面向方面编程),能够说是 OOP(Object-Oriented Programing,面向对象编程)的补充和欠缺。OOP 引入封装、继承和多态性等概念来建设一种对象层次结构,用以模仿公共行为的一个汇合。当咱们须要为扩散的对象引入公共行为的时候,OOP 则显得无能为力。也就是说,OOP 容许你定义从上到下的关系,但并不适宜定义从左到右的关系。例如日志性能。日志代码往往程度地分布在所有对象档次中,而与它所分布到的对象的外围性能毫无关系。对于其余类型的代码,如安全性、异样解决和通明的持续性也是如此。这种分布在各处的无关的代码被称为横切(cross-cutting)代码,在 OOP 设计中,它导致了大量代码的反复,而不利于各个模块的重用。
而 AOP 技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象外部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简略地说,就是将那些与业务无关,却为业务模块所独特调用的逻辑或责任封装起来,便于缩小零碎的反复代码,升高模块间的耦合度,并有利于将来的可操作性和可维护性。AOP 代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的办法,就好像一把利刃,将这些空心圆柱体剖开,以取得其外部的音讯。而剖开的切面,也就是所谓的“方面”了。而后它又以巧夺天功的妙手将这些剖开的切面还原,不留痕迹。
应用“横切”技术,AOP 把软件系统分为两个局部:外围关注点和横切关注点。业务解决的次要流程是外围关注点,与之关系不大的局部是横切关注点。横切关注点的一个特点是,他们常常产生在外围关注点的多处,而各处都根本类似。比方权限认证、日志、事务处理。Aop 的作用在于拆散零碎中的各种关注点,将外围关注点和横切关注点拆散开来。正如 Avanade 公司的高级计划构架师 Adam Magee 所说,AOP 的核心思想就是“将应用程序中的商业逻辑同对其提供反对的通用服务进行拆散。”
92. 解释一下什么是 ioc?
IOC 是 Inversion of Control 的缩写,少数书籍翻译成“管制反转”。
1996 年,Michael Mattson 在一篇无关探讨面向对象框架的文章中,首先提出了 IOC 这个概念。对于面向对象设计及编程的根本思维,后面咱们曾经讲了很多了,不再赘述,简略来说就是把简单零碎分解成相互合作的对象,这些对象类通过封装当前,外部实现对外部是通明的,从而升高了解决问题的复杂度,而且能够灵便地被重用和扩大。
IOC 实践提出的观点大体是这样的:借助于“第三方”实现具备依赖关系的对象之间的解耦。如下图:
图 IOC 解耦过程
大家看到了吧,因为引进了两头地位的“第三方”,也就是 IOC 容器,使得 A、B、C、D 这 4 个对象没有了耦合关系,齿轮之间的传动全副依附“第三方”了,全副对象的控制权全副上缴给“第三方”IOC 容器,所以,IOC 容器成了整个零碎的要害外围,它起到了一种相似“粘合剂”的作用,把零碎中的所有对象粘合在一起发挥作用,如果没有这个“粘合剂”,对象与对象之间会彼此失去分割,这就是有人把 IOC 容器比喻成“粘合剂”的由来。
咱们再来做个试验:把上图两头的 IOC 容器拿掉,而后再来看看这套零碎:
图 拿掉 IOC 容器后的零碎
咱们当初看到的画面,就是咱们要实现整个零碎所须要实现的全部内容。这时候,A、B、C、D 这 4 个对象之间曾经没有了耦合关系,彼此毫无分割,这样的话,当你在实现 A 的时候,基本无须再去思考 B、C 和 D 了,对象之间的依赖关系曾经升高到了最低水平。所以,如果真能实现 IOC 容器,对于零碎开发而言,这将是一件如许美妙的事件,参加开发的每一成员只有实现本人的类就能够了,跟他人没有任何关系!
咱们再来看看,管制反转 (IOC) 到底为什么要起这么个名字?咱们来比照一下:
软件系统在没有引入 IOC 容器之前,如图 1 所示,对象 A 依赖于对象 B,那么对象 A 在初始化或者运行到某一点的时候,本人必须被动去创建对象 B 或者应用曾经创立的对象 B。无论是创立还是应用对象 B,控制权都在本人手上。
软件系统在引入 IOC 容器之后,这种情景就齐全扭转了,如图 3 所示,因为 IOC 容器的退出,对象 A 与对象 B 之间失去了间接分割,所以,当对象 A 运行到须要对象 B 的时候,IOC 容器会被动创立一个对象 B 注入到对象 A 须要的中央。
通过前后的比照,咱们不难看出来:对象 A 取得依赖对象 B 的过程, 由被动行为变为了被动行为,控制权颠倒过去了,这就是“管制反转”这个名称的由来。
93. spring 有哪些次要模块?
Spring 框架至今已集成了 20 多个模块。这些模块次要被分如下图所示的外围容器、数据拜访 / 集成,、Web、AOP(面向切面编程)、工具、音讯和测试模块。
更多信息:howtodoinjava.com/java-spring-framework-tutorials/
94. spring 罕用的注入形式有哪些?
Spring 通过 DI(依赖注入)实现 IOC(管制反转),罕用的注入形式次要有三种:
- 构造方法注入
- setter 注入
- 基于注解的注入
95. spring 中的 bean 是线程平安的吗?
Spring 容器中的 Bean 是否线程平安,容器自身并没有提供 Bean 的线程安全策略,因而能够说 spring 容器中的 Bean 自身不具备线程平安的个性,然而具体还是要联合具体 scope 的 Bean 去钻研。
96. spring 反对几种 bean 的作用域?
当通过 spring 容器创立一个 Bean 实例时,不仅能够实现 Bean 实例的实例化,还能够为 Bean 指定特定的作用域。Spring 反对如下 5 种作用域:
- singleton:单例模式,在整个 Spring IoC 容器中,应用 singleton 定义的 Bean 将只有一个实例
- prototype:原型模式,每次通过容器的 getBean 办法获取 prototype 定义的 Bean 时,都将产生一个新的 Bean 实例
- request:对于每次 HTTP 申请,应用 request 定义的 Bean 都将产生一个新实例,即每次 HTTP 申请将会产生不同的 Bean 实例。只有在 Web 利用中应用 Spring 时,该作用域才无效
- session:对于每次 HTTP Session,应用 session 定义的 Bean 豆浆产生一个新实例。同样只有在 Web 利用中应用 Spring 时,该作用域才无效
- globalsession:每个全局的 HTTP Session,应用 session 定义的 Bean 都将产生一个新实例。典型状况下,仅在应用 portlet context 的时候无效。同样只有在 Web 利用中应用 Spring 时,该作用域才无效
其中比拟罕用的是 singleton 和 prototype 两种作用域。对于 singleton 作用域的 Bean,每次申请该 Bean 都将取得雷同的实例。容器负责跟踪 Bean 实例的状态,负责保护 Bean 实例的生命周期行为;如果一个 Bean 被设置成 prototype 作用域,程序每次申请该 id 的 Bean,Spring 都会新建一个 Bean 实例,而后返回给程序。在这种状况下,Spring 容器仅仅应用 new 关键字创立 Bean 实例,一旦创立胜利,容器不在跟踪实例,也不会保护 Bean 实例的状态。
如果不指定 Bean 的作用域,Spring 默认应用 singleton 作用域。Java 在创立 Java 实例时,须要进行内存申请;销毁实例时,须要实现垃圾回收,这些工作都会导致系统开销的减少。因而,prototype 作用域 Bean 的创立、销毁代价比拟大。而 singleton 作用域的 Bean 实例一旦创立胜利,能够重复使用。因而,除非必要,否则尽量避免将 Bean 被设置成 prototype 作用域。
97. spring 主动拆卸 bean 有哪些形式?
Spring 容器负责创立应用程序中的 bean 同时通过 ID 来协调这些对象之间的关系。作为开发人员,咱们须要通知 Spring 要创立哪些 bean 并且如何将其拆卸到一起。
spring 中 bean 拆卸有两种形式:
- 隐式的 bean 发现机制和主动拆卸
- 在 java 代码或者 XML 中进行显示配置
当然这些形式也能够配合应用。
98. spring 事务实现形式有哪些?
- 编程式事务管理对基于 POJO 的利用来说是惟一抉择。咱们须要在代码中调用 beginTransaction()、commit()、rollback()等事务管理相干的办法,这就是编程式事务管理。
- 基于 TransactionProxyFactoryBean 的申明式事务管理
- 基于 @Transactional 的申明式事务管理
- 基于 Aspectj AOP 配置事务
99. 说一下 spring 的事务隔离?
事务隔离级别指的是一个事务对数据的批改与另一个并行的事务的隔离水平,当多个事务同时拜访雷同数据时,如果没有采取必要的隔离机制,就可能产生以下问题:
- 脏读:一个事务读到另一个事务未提交的更新数据。
- 幻读:例如第一个事务对一个表中的数据进行了批改,比方这种批改波及到表中的“全副数据行”。同时,第二个事务也批改这个表中的数据,这种批改是向表中插入“一行新数据”。那么,当前就会产生操作第一个事务的用户发现表中还存在没有批改的数据行,就好象产生了幻觉一样。
- 不可反复读:比方说在同一个事务中先后执行两条截然不同的 select 语句,期间在此次事务中没有执行过任何 DDL 语句,但先后失去的后果不统一,这就是不可反复读。
100. 说一下 spring mvc 运行流程?
Spring MVC 运行流程图:
Spring 运行流程形容:
- 用户向服务器发送申请,申请被 Spring 前端管制 Servelt DispatcherServlet 捕捉;
2. DispatcherServlet 对申请 URL 进行解析,失去申请资源标识符(URI)。而后依据该 URI,调用 HandlerMapping 取得该 Handler 配置的所有相干的对象(包含 Handler 对象以及 Handler 对象对应的拦截器),最初以 HandlerExecutionChain 对象的模式返回;
3. DispatcherServlet 依据取得的 Handler,抉择一个适合的 HandlerAdapter;(附注:如果胜利取得 HandlerAdapter 后,此时将开始执行拦截器的 preHandler(…)办法)
- 提取 Request 中的模型数据,填充 Handler 入参,开始执行 Handler(Controller)。在填充 Handler 的入参过程中,依据你的配置,Spring 将帮你做一些额定的工作:
- HttpMessageConveter:将申请音讯(如 Json、xml 等数据)转换成一个对象,将对象转换为指定的响应信息
- 数据转换:对申请音讯进行数据转换。如 String 转换成 Integer、Double 等
- 数据根式化:对申请音讯进行数据格式化。如将字符串转换成格式化数字或格式化日期等
- 数据验证:验证数据的有效性(长度、格局等),验证后果存储到 BindingResult 或 Error 中
- Handler 执行实现后,向 DispatcherServlet 返回一个 ModelAndView 对象;
- 依据返回的 ModelAndView,抉择一个适宜的 ViewResolver(必须是曾经注册到 Spring 容器中的 ViewResolver)返回给 DispatcherServlet;
7. ViewResolver 联合 Model 和 View,来渲染视图;
- 将渲染后果返回给客户端。
101. spring mvc 有哪些组件?
Spring MVC 的外围组件:
- DispatcherServlet:地方控制器,把申请给转发到具体的管制类
- Controller:具体解决申请的控制器
- HandlerMapping:映射处理器,负责映射中央处理器转发给 controller 时的映射策略
- ModelAndView:服务层返回的数据和视图层的封装类
- ViewResolver:视图解析器,解析具体的视图
- Interceptors:拦截器,负责拦挡咱们定义的申请而后做解决工作
102. @RequestMapping 的作用是什么?
RequestMapping 是一个用来解决申请地址映射的注解,可用于类或办法上。用于类上,示意类中的所有响应申请的办法都是以该地址作为父门路。
RequestMapping 注解有六个属性,上面咱们把她分成三类进行阐明。
value,method:
- value:指定申请的理论地址,指定的地址能够是 URI Template 模式(前面将会阐明);
- method:指定申请的 method 类型,GET、POST、PUT、DELETE 等;
consumes,produces
- consumes:指定解决申请的提交内容类型(Content-Type),例如 application/json, text/html;
- produces:指定返回的内容类型,仅当 request 申请头中的 (Accept) 类型中蕴含该指定类型才返回;
params,headers
- params:指定 request 中必须蕴含某些参数值是,才让该办法解决。
- headers:指定 request 中必须蕴含某些指定的 header 值,能力让该办法解决申请。
103. @Autowired 的作用是什么?