前言
Spring是企业级J2EE一站式解决方案,提供了整个项目的表现层、业务层、持久层,而且,它的生态特别完善,可以和其他框架无缝对接,现在做Java的哪个项目里没有Spring的说出不去都不信。但往往我们开发者只重视项目是不是run起来了,而忽略了去了解Spring本身,所以很多开发者仅仅是停留在了使用的层次。博主也不例外,说出来怕你不信,博主最不喜欢的就是Spring了,用的很爽啊,但是就像我们打游戏,玩着很爽,让你自己做一款出来那不是玩呢?所以,这也是博主不喜欢Spring的原因,底层太复杂,想要明白其原理,很难!但今天我们不去做复杂的源码分析(就是想也没这能力啊),我们就来了解了解支撑Spring工作的一些基本的机制。
Spring的特征
轻量
做为一个支持底层的几乎是万能的框架来说,Spring哪里算轻量级的?但这只是表象的认知,从其引入的JAR包来说,spring–web-5.2.0.RELEASE.jar和spring–core-5.2.0.RELE ASE.jar的大小仅仅只有1M多,从资源利用上来说,它只需要少量的系统资源就可以运行。麻雀虽小,五脏俱全,Spring同时还是模块化的,可以根据需要引入不同的模块,而不需要一股脑的引入全部,从这一点来说,又非常的灵活多变,搞的博主都有点不好意思了,算是今天才真正了解了它的这一特点。
子曰:朝闻道,夕死可矣。但博主只想多多的朝闻道。
控制反转
Spring的控制反转指一个对象依赖的对象会在Spring容器初始化完成后主动将依赖的对象传递给他,而不需要这个对象自己去创建或者查找其依赖的对象,基于此,Spring实现了依赖对象之间的解耦,我们平时用的比较多的就是@Autowired注解。
面向容器
容器方面主要指Spring实现了对象的配置化生成和生命周期管理,通过XML文件或者注解的方式,应用可以配置每个Bean对象创建和销毁的时间,还有创建的先后顺序和依赖关系。Spring中的对象我们根据其使用,基本可以推断它是类似单例的工作模式,但如果你想自己重复创建,那也是被允许的,但具体怎么用还要由Bean对象的生命周期来决定,这是通过prototype 属性来定义的。
面向切面
Spring提供了面向切面编程的能力,博主首先想到的就是过滤器,因为在登录的流程中我们在登录成功后需要在请求头获取令牌。切面通过分离系统逻辑和业务逻辑来提高系统的内聚性,业务层只需要关注并实现和业务相关的代码,而不需要关注系统功能(例如系统日志、事务支持)和业务功能的复杂关系,Spring 通过面向切面技术将系统功能自动织人业务逻辑的关键点。就像是切开一条管道,接入了另一条管道一样,非常的形象。
框架集合
Spring管理对象的方式非常的灵活,对象可以被声明式的创建,例如通过 XML文件或注解的方式定义对象和对象之间的依赖关系,作为一个比较基础的框架,Spring可以允许事务管理、持久化等框架集成和提供Java Web服务的能力,我们现在的项目也是在其基础上进行了框架的集成,当然,我们现在更多的采用Spring Boot,但Spring Boot和Spring在本质上区别并不大,只是Spring Boot更加的智能化,集成度更加高,使用起来更加便利。
Spring的模块
此处必须有图:
这是一张比较经典的Spring模块图,里面详细列出了Spring模块化后的各个部分,好家伙,可以说一半以上的模块博主都没听过,但这并不妨碍它在我们开发的过程中所起到的举足轻重的作用。下面,我们就来分别认识一下这些模块都是什么,都做什么。
核心容器层
Spring-Beans
我们先来说说什么是Bean,Bean是计算机自动生成的类,是由Spring IoC容器实例化、组装和管理的对象。
Spring-Beans模块通过工厂模式实现对象的创建,再通过XML的方式实现了对象的声明式管理,将复杂的对象依赖关系从实际编码中解耦了出来,实现了前面所说的对象的声明式管理。在这个过程中,我们来猜一下,有没有反射机制?可以说,所有的以解耦为目的的框架也好,模块也好,恐怕都离不开反射。也就是说,Bean并不是由开发者创建管理的,而是程序运行时由Spring通过反射生成并统一管理的对象或者实例。这是博主说的,大家可以去求证,求打脸【贱兮兮】。
Spring-Core
一看见Core就知道这是Spring的核心模块,它包含了控制反转和依赖注入,关于这两个词我相信大家起码知道他们大概是啥意思。但这里博主还是要再说一遍。依赖注入是在一个Bean实例引入另一个Bean实例时,Spring会自动创建其所依赖的Bean实例,并注入到对应的Bean中。关于控制反转,博主在上面Spring的特征已经讲过,但过于抽象,我们可以理解成本来应该由开发者控制的Bean对象现在控制权交给了Spring容器,控制权反转了【摊手】。
Spring-Context
要了解Spring-Context,那你就要先去了解Spring-Beans和Spring-Core,如果把Spring-Context比作一栋高楼,那么Spring-Beans和Spring-Core就是高楼的地基,Spring-Context 继承自 Spring-Beans 模块,并且添加了国际化,事件传播,资源加裁和透明地创建上下文等功能。
Spring-Context还额外提供了一些J2EE的功能,比如 EJB、 JMX 和远程调用等,ApplicationContext接口还是Spring-Context 模块操作 Bean入口的产物。
Spring-Conext-Support还提供了将第三方库集成到Spring-Context的能力,比如缓存、邮件、模块、调度引擎等,不过这些都是更加偏底层和源码的部分,我们知道有这些就行,要是说掌握?那真是……一言难尽。
SpEL
SpEL提供了丰富的表达式和语言支持,更贴近于我们的实际变成。由于SpEL在JSP 2. 1表达式语言规范的基础上进行了扩展,支持set方法、get方法、属性赋值、方法调用、访问数组集合、索引 容、逻辑算术运算、命名变量、基于名称在Spring loC 容器检索对象,同时支持列表的投影选择和聚合等功能。额,像不像天书?像!所以,你只需要了解前半部分就行,后半部分请自动忽略,这辈子恐怕都用不上,换句话说,就是用上了,你也不知道是它,所以不要纠结,如果你精益求精,非要知道是啥,到时记得告诉博主【哈哈】。
数据访问层
如果没有深入的了解,大眼一扫,博主只认识JDBC和Transactions,所以其他到底是什么?我们下面来一一解答。
JDBC
JDBC全称Java Data Base Connectivity,是用来连接数据库的,JDBC提供了一个抽象层,Spring通过这个抽象层不同数据库的灵活切换,而且还不用担心不同数据库的语法是否兼容。
ORM
ORM全称Object Relational Mapping,是对象关系映射,它提供了对象关系映射的API,包括 JPA ( Java Persistence API )、 JDO( Java Data Obj ct) 和Hibernate等。基于该模块, ORM 框架能很容易地和Spring其他功能整合,一个比较典型的案例就是事务管理,这个其实挺抽象,到这里也差不多了,可以说用到了你也不知道是这玩意儿,是不是很尴尬?好奇怎么用的可以再深入了解。
OXM
全称Object XML Mapping,字面意思是对象XML映射,此模块实现了对 OXM的支持,比如 JAXB、Castor、XML Beans、JiBX、XStream。我只能说,我们实际编码中未必真的会接触,但是人家都帮我们做好了,突然不知道写这个有啥用,有几个人真正搞明白的?个人认为,对于这些模块,了解大的模块就行,比如这里是数据访问层,下面的知道个JDBC就行,其他的了解即可。
JMS
全称Java Message Service,这个博主知道,如果你还不知道,那你看下面这句话:包含消息的生产( Produce )和消费( Consume )功能。看着像MQ?是的,从Spring4.1 开始,Spring 集成了 Spring-Messaging模块,用于实现对消息队列的支持。
Transactions
Transactions就是事务管理,这个大家应该都比较熟悉,该模块基于接口实现了声明式事务管理,编程式事务下,应用程序需要调用beginTransaction()、commit()、rollbac()等方法来实现事务的管理,Spring声明式事务通过注解或者配置就可以实现事务的管理,具体的工作都由Spring自动完成,开发者不必再关心提交和回滚的问题。
Web应用层
我们平时说的Java指的是Java Web,就是Java应用程序,用来做Web交互和数据传输等的相关功能。具体就是由以下几个模块组成的。
Web
Web模块提供了面向web的基本功能,还提供了HTTP (Hyper Text Transfer Protocol ,超文本传输协议)客户端及 Spring 远程调用与Web 相关的部分,Web模块基于 Servlet 监听器初始化 IoC 容器
Web-MVC
Web-MVC 模块为 Web 应用提供了模型视图控制( Model View Controller , MVC)和REST API 服务的实现。Spring MVC 框架使数据模型和视图分离,数据模型负责数据的业务逻辑,视图负责数据的展示。同时,Web-MVC 可与 Spring 框架的其他模块方便地集成。
Web-Socket
Web-Socket 模块提供了对 WebSocket-Base 的支持,用于实现Web 应用程序中服务端和客户端实时双向通信,尤其在实时消息推送中应用广泛。
Web-Portlel
Web-Portlet 模块提供了基于 Portlet 环境的 MVC 实现,并提供了与 Spring Web-MVC 模块相关的功能。
总结
前面的都还好,这个Web层总有点生无可恋的赶脚,我们恐怕了解不了那么深,当然不排除一些大神很有天赋,一看就懂,总之博主觉得这些看看就行。
其他模块
剩下的模块共五大块,我们来分别看下都是什么。
AOP
AOP提供了面向切面编程的实现,允许应用程序通过定义方法拦截器和切人点来实现系统功能和业务功能之间的解耦,这个博主之前有写过,可自行查看使用方法。
Aspects
Aspects 模块提供了 Spring与Aspect的集成,是一个面向切面编程的模块。而AOP是Aspect Oriented Programming的简称,这就是A的由来。
Instrumentation
Instrumentation 模块在应用中提供了对 Instrumntation 支持和类加载器的实现。这个和没说一样啊,Instrumntation是动态编程的代名词,特别是在Java SE6中,其被赋予了更多的功能,具有了更强的动态控制、解释能力、也增加了动态添加 class path 的功能。
Instrumentation 的最大作用,就是类定义动态改变和操作。在 Java SE 5 及其后续版本当中,开发者可以在一个普通 Java 程序(带有 main 函数的 Java 类)运行时,通过 –javaagent 参数指定一个特定的 jar 文件(包含 Instrumentation 代理)来启动 Instrumentation 的代理程序。
推荐一篇Java探针的博客:Java探针技术:Instrumentation
我们现在使用的框架很多都是已经帮我们做过了,以至于我们根本不了解更底层的东西,所谓成也风云,败也风云,这样也不知道是幸?还是不幸 ?
Messaging
Messaging模块为 STOMP ( Simple Text Orientated Messaging Protocol ,简单文本定向消息协议)提供了支持,主要用于应用程序中 WebSocket 子协议的实现,同时,Messaging 模块可通过注解的方式来选择和处理来自 WebSocket 客户端的 STOMP 消息。
Test
Test模块用于对JUnit等岑氏框架的支持,以实现Spring代码的自动化测试功能。
Spring核心包
编号 | 包名 | 说明 |
1 |
Spring Core |
Spring 的核心工具包 |
2 |
Spring Beans |
Spring oC 的实现,通过 XML 配置文件或注解的方式实现 Spring Bean 的管理 |
3 |
Spring Context |
|
4 | ||
5 | ||
6 | ||
7 |
处理不同的项目依赖了不同版本的 Spring引起的版本冲突问 题 |
|
8 | ||
9 | ||
10 |
Spring JDBC |
|
11 |
Spring JMS |
|
12 | ||
13 |
Spring ORM |
Spring 整合第三方的 ORM 的实现,如 Hibemate、MyBatis、 JDO及Spring的JPA |
14 |
Spring OXM |
Spring Object/XML 映射的支符,可以让 Spring在Java 与XML之间方便地切换 |
15 |
Spring Test |
|
16 |
Spring TX |
|
17 |
Spring Web |
基于 Spring 构建Web 应用开发所需的核心类,包括自动载入 |
18 |
Spring WebMVC |
包含 Spring MVC 框架相关的所有类,例如国际化、标签、 Theme 、视图展现的 FreeMarker、JasperReports、Tiles Velocity、 XSLT 相关类。当然,如果你的应用使用了独立的 MVC 框架,则不需要使用这个 JAR 文件里的任何类 |
19 |
Spring WebMVC Portlet |
Spring常用注解
分类 | 注解 | 说明 |
Bean声明 |
@Cornponent |
|
@Controller |
||
Bean注入 | ||
@Resource |
||
配置类注解 | ||
@Bean |
||
用于对 Component 进行扫描配置 |
||
AOP 注解 |
||
@After |
||
@Around |
在方法执行之前和之后都执行 |
|
@PointCut |
声明一个切点 |
|
@Bean属性支持注解 |
设置 Spring 容器 Bean 实例的生命周期 取值有singleton、prototype、request、session、和 global session |
|
声明方法在构造函数执行完之后开始执行 |
||
声明方法在 Bean销毁之前执行 |
||
@Value |
||
异步操作注解 | ||
@Async |
异步执行该方法 |
|
定时任务注解 | ||
声明一个定时任务,包括 cron、fïxDelay、fixRate 等参数 |
||
开启功能支持注解 | ||
@EnableWebMVC |
开启对 WebMVC 的配置支持 |
|
开启对事务的支持 |
||
开启对缓存的支持 |
||
测试注解 |
@RunWith |
|
Spring MVC注解 |
@Controller |
声明该类为 Spring MVC 中的控制器 |
路径和参数 |
||
组合注解,相当于 @Controller和@ResponseBody 的组合 |
||
@InitBinder |
Spring IoC的原理
IoC作用
Spring 通过一个配置文件描述 Bean Bean 之间的依赖关系,利用 Java 的反射功能实例化 Bean 并建立Bean之间的依赖关系,Spring IoC 容器在完成这些底层操作的基础上,还提供了 Bean 实例缓存管理、 Bean 生命周期管理、 Bean 实例代理、事件发布和资源装载等高级服务。
Spring Bean作用域
Singleton (单例)
单例模式下,IoC容器只会存在一个共享的Bean实例,但在多线程下,它是不安全的,会发生竞争。配置如下:
<bean id="xxxxDao" class="com.xxxxxx.xxxxxximpl" scope="singleton"/>
Prototype (原型)
原型模式下,每次通过 Spring 容器获取 Prototype 定义的 Bean 时,容器都会重新创建一个新的Bean实例。和单例的区别是,单例的Bean是无状态的,原型的Bean有状态。配置如下:
<bean id="xxxxService" class="com.xxxxxx.xxxxxxService" scope="prototype"/>
Request (请求级别)
请求级别模式下,一个HTTP请求容器只返回该Bean的同一个实例,不同的HTTP请求,容器会创建新的Bean,Bean随着HTTP请求的结束而销毁。配置如下:
<bean id="xxxxRequest" class="com.xxxxxx.xxxxxxLogin" scope="request"/>
Session (会话级别)
Session 指在一次 HTTP Session 中容器会返回该 Bean 的同一个实例,而对不同的Session 请求则会创建新的 Bean 实例,不同的Bean实例不共享数据,请求结束,Bean实例销毁。配置如下:
<bean id="xxxxSession" class="com.xxxxxx.xxxxxxSession" scope="session"/>
Global Session (全局会话)
Global Session 指在一个全局的 HTTP Session容器会返问该 Bean 的同一个实例,且仅在使用 Portlet Context 时有效。配置如下:
<bean id="xxxxSession" class="com.xxxxxx.xxxxxxSession" scope="globalSession"/>
Spring Bean的生命周期
- 实例化一个bean;
- 按照 Spring 上下文对实例化的 Bean 进行配置;
- 如果这个 Bean 实现了 BeanNameAware 接口 ,则调用它实现的 setBeanName(String)方法,该方法传递的参数是 spring 配置文件中Bean的id值;
- 如果这个 Bean 实现了 BeanNameAware 接口 ,则调用它实现的 setBeanFactory(BeanFactory)方法,该方法传递的参数是Spring工厂本身;
- 如果这个 Bean 实现了 ApplicationContextAware 接口 ,则调用它实现的setApplicationContext(ApplicationContext) 方法,该方法传入的参数是Spring上下文;
- 如果该 Bean 关联了 BeanPostProcessor 接口, 会调用 postProcessBeforeInitialization(Object obj , String s) 方法,该方法在 Bean 初始化前调用,常用于定义初始化Bean 的前置工作,比如系统缓存的初始化;
- 如果Bean在Spring 配置文件中配置了 init–method 属性,则会自动调用其配置的初始化方法;
- 如果某个 Bean 关联了 BeanPostProcessor 接口,将会调用 postProcessAfterInitialization(Object obj, String s) 方法。至此, Bean 的初始化工作就完成了,应用程序就可以开始使用Bean实例了;
- 当 Bean 不再被需要时, 会在清理阶段被清理掉。如果 Bean 实现了DisposableBean 接口,则 Spring 会在退出前调用实现类的 destroy()方法;
- 如果某个 Bean的Spring 配置文件中配置了 destroy-method 属性,在 Bean 被销毁前会自动调用其配置的销毁方法。
Spring Bean的依赖注入
以上几种在开发中都比较常见,注入!博客认为更像是赋值,大家品一下。
Spring的自动装配
有自动装配就有手动装配,手动装配包括基于 XML的装配(构造方法、 set 方法等)。自动装配包括5种专配方式,均可以用来引导 Spring 容器自动完成依赖注入,具体如下:
- no: 关闭自动装配,通过显式设置 ref 属性来进行对象装配;
- byName: 通过参数名自动装配, Bean 的autowire 被设置为 byName后, Spring 容器试图匹配并装配与该 Bean 的属性具有相同名字 Bean;
- byType: 通过参数类自动装配, Bean的autowire 被设 byType 后,Spring 容器试图匹配并装配与该 Bean 的属性具有相同类型的 Bean;
- constructor:通过设置构造器参数的方式来装配对象,如果没有匹配到带参数构造器参数类型, Spring会抛出异常;
- autodetect: 首先尝试使用constructor 来自动装配 ,如果无法完自动装配 ,则使用byType方式进行装配。
Spring AOP的原理
关于AOP的介绍和代码案例都在这里了:Java开发 – AOP初体验
Spring MVC原理
Spring MVC中的MVC即模型-视图-控制器,该框架围绕 DispatcherServlet 设计,把请求分发给各个处理器,并支持可配置的处理器映射和视图渲染等功能。其详细流程如下:
- 客户端发起HTTP 请求:客户端将请求提交到 DispatcherServlet;
- 寻找处理器:DispatcherServlet,控制器查询一个或多 HandlerMapping,找到处理该请求的 Controller;
- 调用处理器:DispatcherServlet将请求提交到 Controller;
- 调用业务处理逻辑并返回结果:Controller调用业务处理逻辑后,返回ModelAndView
- 处理视图映射并返回模型:DispatcherServlet 查询一个或多个ViewResoler视图解析器,找到 ModelAndView 指定的视图;
- HTTP响应:视图负责将结果在客户端浏览器上渲染和展示。
Spring Boot
相较于Spring,Spring Boot是一个全新的项目,目的是为了简化Spring的初始搭建以及开发过程,使得开发人员不需要再定义样板化的配置。通过这种方式,Spring Boot成为了快速开发的代名词。其有如下特点:
独立运行Spring项目
Spring Boot可以以jar包的方式独立运行,通过命令“ java–jar xx.jar”,创建独立的Spring应用程序,并且基于其Maven或Gradle插件,可以创建可执行的JARs和WARs。
内嵌Servlet容器
Spring Boot 使用嵌入式的 Servlet 容器(例如 Tomcat、Jetty 或者 Undertow 等),应用无需打成 WAR 包 。
简化Maven配置
Spring Boot 提供了一系列的“starter”项目对象模型(POMS)来简化 Maven 配置,如: spring–boot–starter–redis、spring–boot–starter–data–mongodb 和 spring-boot-starter–data–elasticsearch等。
自动配置Spring
Spring Boot 提供了大量的默认自动配置来简化项目的开发,开发人员也通过配置文件修改默认配置,这种尽可能自动配置Spring容器的方式,可以说是开发者的福音。
自带应用监控
无代码生成和XML配置
创建好的Spring Boot项没有额外代码生成,也没有XLM相关的配置,你甚至在项目中找不到XML文件。
事务
MyBatis
MyBatis的缓存分为一级缓存和二级缓存,在默认情况下,一级缓存是开启的,而且不能被关闭的。
- 一级缓存指SqlSession级别的缓存,当在同一个 SqlSession 中执行相同的 SQL语句查询时将查询结果集缓存,第二次以后的查询不会从数据库中查询,而是直接从缓存中获取,一级缓存最多能缓存1024条SQL语句;
- 二级缓存指跨SqlSession的缓存,即Mapper级别的缓存。在Mapper级别的缓内,不痛的SqlSess ion缓存可共享。
一级缓存原理
客户端发出一个SQL查询语句时,MyBatis执行SQL查询并将查询到的数据存储到SqlSession一级缓存中,当第二次相同的SQL语句来查询时,将直接从SqlSession一级缓存中取出值返回。一级缓存使用的数据结构是Map,其key为Mapperld+Offset+Limit+SQL+所有的入参。
这里要注意,当出现Commit操作,即增删改操作时,MyBatis认为数据发生了变了,会将一级缓存中的数据全部清空。下次有SQL查询时将继续缓存,即使之前有缓存过,但在commit后也会被全部清空。
二级缓存原理
二级缓存是Mapper级别的,Mapper以命名空间为单位创建缓存数据结构,数据结构也是Map类型,其key为Mapperld+Offset+Limit+SQL+所有的入参,和一级缓存规则是一样的。MyBatis二级缓存是通过CacheExecutol实现的,CacheExecutor是Executor的代理对象。MyBatis接收到用户的查询请求时,首先会根据Map的Key在CacheExecutor中查询数据是否存在,不存在则前往数据库中查询。
开启 级缓存需要做以下配置
说实话,还真没用过,缓存我们一般都会利用Redis,有更大的内存和更高的并发,实在没有使用这个的必要。
Spring生态
Spring是一个开放的平台,在其上可以集成其他组件的功能,Spring的生态做的也还是不错的,我们常用的有Spring Data、Spring Security、Spring AMQP等,详细可查看下面的链接:
结语
这里只是粗浅的介绍了Spring中有哪些东西,能把这些东西搞懂也算是差不多了吧。哈哈,其实“差不多”这个词挺害人的,但能掌握多少,掌握到什么程度,就是大家自己的事情了,内容不少,大家可以有针对性的去看去学,像里面有些东西博主都是一笔带过,不是说不重要,只是没有想象中那么重要,要是有时间,可以深入研究,那今天就到这里吧,博主也需要拐回去好好再看几遍。
原文地址:https://blog.csdn.net/CodingFire/article/details/131487620
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_46654.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!