阅读全文大概需要 7 分钟
前言
大多数文章讲 ” 什么到 Spring?” 上来就是 控制反转(IoC)或依赖注入(DI)和面向切面编程(AOP),拿着官网文档直译 copy。对小白来说并不友好,看完可能还是一头雾水。下面是我利用业余时间整理的一些资料、书籍和自己的理解,致力于更容易理解方式讲 Spring。
[toc]
什么是 Spring ?
Spring 是一个开源框架,Spring 是于 2003 年兴起的一个 轻量级 的 Java 开发框架,由 Rod Johnson 在其著作 Expert One-On-One J2EE Development and Design 中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring 使用基本的 JavaBean 来完成以前只可能由 EJB 完成的事情。
然而,Spring 的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何 Java 应用都可以从 Spring 中受益。Spring 的核心是控制反转(IoC)和面向切面(AOP)。简单来说,Spring 是一个分层的 JavaSE/EE full-stack
(一站式) 轻量级
开源框架。
简单来说,它是一个容器框架,用来装 javabean(java 对象),中间层框架(万能胶)可以起一个连接作用,比如说把 Struts 和 hibernate 粘合在一起运用。简单来说,Spring 是一个轻量级的控制反转 (IoC) 和面向切面 (AOP) 的容器框架。
如果你现在还有点疑惑,通读全文,你一定有所收获
Spring 模块
以下内容都是基于 Spring 4 及以上的
Spring
官网图片
- Spring Core:Spring 核心模块,主要提供 ioC 依赖注入、
- Spring Context:向 Spring 框架提供上下文信息、
- Spring AOP:面向切面编程,为基于 Spring 的应用程序中的对象提供了事务管理服务、
- Spring JDBC:Java 数据库连接、
- Spring JMS:Java 消息服务、
- Spring ORM:用于支持 MyBatis、Hibernate 等 ORM 工具、
- Spring Web:为创建 Web 应用程序提供支持、
- Spring Test:提供了对 JUnit 和 TestNG 测试的支持、
- Spring Aspects:该模块为与 AspectJ 的集成提供支持。
- Spring Web:Spring 框架支持与 Struts 集成,为基于 web 的应用程序提供了上下文。
Spring 的优点
- 方便解耦,简化开发(高内聚低耦合)
Spring 就是一个大工厂(容器),可以将所有对象创建和依赖关系维护,交给 Spring 管理,spring 工厂是用于生成 bean
- AOP 编程的支持
Spring 提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能
- 声明式事务的支持
只需要通过配置就可以完成对事务的管理,而无需手动编程
- 方便程序的测试
Spring 对 Junit4 支持,可以通过注解方便的测试 Spring 程序
- 方便集成各种优秀框架
Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz 等)的直接支持
- 降低 JavaEE API 的使用难度
Spring 对 JavaEE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等),都提供了封装,使这些 API 应用难度大大降低
我对 Spring IoC 和 AOP 理解
Spring 中最重要的概念 IoC 和 AOP
IoC(Inversion of Control)控制反转
IoC
需要DI
(依赖注入)的支持为什么呢?因为没有 DI 的注入 Spring 创造出的对象都是空值是无法使用的, 所以说IoC
和DI
多数是同时出现人们眼前的。
IOC
是 Inversion of Control
的缩写,多数书籍翻译成“控制反转”。为了解决对象之间的耦合度过高的问题 ,软件专家 Michael Mattson 提出了 IOC 理论,用来实现对象之间的 解耦。
2004 年,Martin Fowler 探讨了同一个问题,既然 IOC 是控制反转,那么到底是“哪些方面的控制被反转了呢?”,经过详细地分析和论证后,他得出了答案:“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为了由 IOC 容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。他的这个答案,实际上给出了实现 IOC 的方法:注入。所谓依赖注入,就是由 IOC 容器在运行期间,动态地将某种依赖关系注入到对象之中。
依赖注入 (DI) 和控制反转 (IOC) 是从不同的角度的描述的同一件事情,就是指 通过引入 IOC 容器,利用依赖关系注入的方式,实现对象之间的解耦。
背景介绍完了,讲讲我的理解
IoC 就是 依赖倒置 原则的一种 设计思路 ,就 是将原本在程序中自己手动创建对象的控制权,交由 Spring 框架来管理 。Spring 框架负责控制对象的 生命周期 和对象之间的关系。IoC 在其他语言中也有应用,并非 Spirng 特有。ioc 容器实际上就是个 map(key,value),里面存的是各种对象(在 xml 里配置的 bean 节点 ||repository、service、controller、component)。
Spring IOC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件 / 注解即可,完全不用考虑对象是如何被创建出来的。 IOC 容器负责创建对象,将对象连接在一起,配置这些对象,并从创建中处理这些对象的整个生命周期,直到它们被完全销毁。
在实际项目中一个 Service 类如果有几百甚至上千个类作为它的底层,我们需要实例化这个 Service,你可能要每次都要搞清这个 Service 所有底层类的构造函数,这可能会把人逼疯。如果利用 IOC 的话,你只需要配置好,然后在需要的地方引用就行了,这大大增加了项目的可维护性且降低了开发难度。
推荐阅读:
https://www.zhihu.com/questio…
IoC 容器的初始化过程可以分为三步:
- Resource 定位(Bean 的定义文件定位)、
- 将 Resource 定位好的资源载入到 BeanDefinition、
- 将 BeanDefiniton 注册到容器中
IoC 源码:
https://javadoop.com/post/spr…
AOP(Aspect-OrientedProgramming)面向切面编程
什么是 AOP?
AOP(Aspect Oriented Programming 面向切面编程),在程序开发中主要用来解决一些系统层面上的问题,比如 日志收集,事务管理,权限,缓存,对象池管理 等。
AOP 可以说是 OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP 引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过 OOP 允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如 安全性、异常处理和透明的持续性 也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在 OOP 设计中,它导致了 大量代码的重复,而不利于各个模块的重用。
AOP 技术恰恰相反,它利用一种称为 ” 横切 ” 的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为 ”Aspect”,即切面。所谓 ” 切面 ”,简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度 ,并有 利于未来的可操作性和可维护性。
Spring AOP
Spring AOP 就是基于动态代理的,底层实现有俩种方式:一种是 JDK 动态代理(JDK Proxy),另一种是 CGLib(Code Generation Library(基于字节码操作)) 的方式。
如果要被代理的对象是个实现类,那么 Spring 会使用 JDK 动态代理来完成操作(Spirng 默认采用 JDK 动态代理实现机制);如果要被代理的对象不是个实现类那么,Spring 会强制使用 CGLib 来实现动态代理。
推荐阅读:https://www.jianshu.com/p/5b9…
当然,也可以使用 AspectJ,AspectJ 可以做 Spring AOP 干不了的事情,它是 AOP 编程的完全解决方案。
Spring AOP 和 AspectJ AOP 有什么区别?
Spring AOP 属于运行时增强;而 AspectJ 是编译时增强。Spring AOP 只能在运行时织入,AspectJ 运行时织入不可用,支持编译时、编译后和加载时织入。
AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单。
Spring 的 bean
bean 的作用域有哪些?
Spring bean 单例与线程安全问题
线程安全一直是代码编写的重地,我们大多时候在系统开发中不会使用多线程。单例 bean 存在线程安全问题,当多个线程操作同一个对象的时候,这个对象的非静态成员变量会存在线程安全问题。
解决方法:
- 在类中定义一个 ThreadLocal 成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的一种方式,这也是常用一种);
2. 在 Bean 对象中尽量避免定义可变的成员变量。
Spring bean 的生命周期
在传统的 Java 应用中,bean 的生命周期很简单,使用 Java 关键字 new 进行 Bean 的实例化,然后该 Bean 就能够使用了。一旦 bean 不再被使用,则由 Java 自动进行垃圾回收。
相比之下,Spring 管理 Bean 的生命周期就复杂多了,正确理解 Bean 的生命周期非常重要。一个 Bean 的构造过程:
谈谈对 Spring MVC 的理解
说到了 Spring,那一定提一下 Spring MVC,各种讲 SSM 的技术博客大家应该都见了很多。
在我初学时 Java,那时讲的是“Java Bean(Model) + JSP(View)+ Servlet(Controller)”这种开发模式,这是早期的 JavaWeb MVC。
Spring MVC 是一款很优秀的 MVC 框架。可以让我们的开发更简洁,而且它和 Spring 是无缝集成,是 Spring 的一个子模块,是我们上面提到 Spring 大家族中 Web 模块。
Spring MVC 框架主要由 DispatcherServlet、处理器映射、处理器 (控制器)、视图解析器、视图 组成。
Spring MVC 流程图很重要:
Spring 事务声明
事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性。
- 编程式事务,在代码中硬编码。(不推荐使用)
- 声明式事务,在配置文件中配置(推荐使用)
声明式事务 又分为两种:
- 基于 XML 的声明式事务
- 基于注解的声明式事务
比较重要的一点是
@Transactional(rollbackFor = Exception.class)注解
在 @Transactional
注解中如果不配置 rollbackFor
属性, 那么事物只会在遇到 RuntimeException
的时候才会回滚, 加上 rollbackFor=Exception.class
, 可以让事物在遇到非运行时异常时也回滚。
后记
scope 是范围的意思, 在绝地求生中 scope 意为瞄准镜, 如果你的队友是个老外你就和他说 i want this 4times scope 他就明白了。
下篇结合代码一块讲解
声明:参考来源互联网,有任何争议可以留言。站在前人的肩上,我们才能看的更远。
本教程纯手打,致力于最实用教程,希望多多转发支持,对我真的很重要。
欢迎来我公众号,希望可以结识你,更多原创 PDF,微信搜索:JavaPub,回复:【666】,也可以催更。有任何问题都可以来谈谈!