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模块化后的各个部分,好家伙,可以说一半以上的模块博主都没听过,但这并不妨碍它在我们开发的过程中所起到的举足轻重的作用。下面,我们就来分别认识一下这些模块都是什么,都做什么。
我们先来说说什么是Bean,Bean是计算机自动生成的类,是由Spring IoC容器实例化、组装和管理的对象。
Spring-Beans模块通过工厂模式实现对象的创建,再通过XML的方式实现了对象的声明式管理,将复杂的对象依赖关系从实际编码中解耦了出来,实现了前面所说的对象的声明式管理。在这个过程中,我们来猜一下,有没有反射机制?可以说,所有的以解耦为目的的框架也好,模块也好,恐怕都离不开反射。也就是说,Bean并不是由开发者创建管理的,而是程序运行时由Spring通过反射生成并统一管理的对象或者实例。这是博主说的,大家可以去求证,求打脸【贱兮兮】。
一看见Core就知道这是Spring的核心模块,它包含了控制反转和依赖注入,关于这两个词我相信大家起码知道他们大概是啥意思。但这里博主还是要再说一遍。依赖注入是在一个Bean实例引入另一个Bean实例时,Spring会自动创建其所依赖的Bean实例,并注入到对应的Bean中。关于控制反转,博主在上面Spring的特征已经讲过,但过于抽象,我们可以理解成本来应该由开发者控制的Bean对象现在控制权交给了Spring容器,控制权反转了【摊手】。
要了解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在JSP 2. 1表达式语言规范的基础上进行了扩展,支持set方法、get方法、属性赋值、方法调用、访问数组集合、索引 容、逻辑算术运算、命名变量、基于名称在Spring loC 容器检索对象,同时支持列表的投影选择和聚合等功能。额,像不像天书?像!所以,你只需要了解前半部分就行,后半部分请自动忽略,这辈子恐怕都用不上,换句话说,就是用上了,你也不知道是它,所以不要纠结,如果你精益求精,非要知道是啥,到时记得告诉博主【哈哈】。
如果没有深入的了解,大眼一扫,博主只认识JDBC和Transactions,所以其他到底是什么?我们下面来一一解答。
JDBC全称Java Data Base Connectivity,是用来连接数据库的,JDBC提供了一个抽象层,Spring通过这个抽象层不同数据库的灵活切换,而且还不用担心不同数据库的语法是否兼容。
ORM全称Object Relational Mapping,是对象关系映射,它提供了对象关系映射的API,包括 JPA ( Java Persistence API )、 JDO( Java Data Obj ct) 和Hibernate等。基于该模块, ORM 框架能很容易地和Spring其他功能整合,一个比较典型的案例就是事务管理,这个其实挺抽象,到这里也差不多了,可以说用到了你也不知道是这玩意儿,是不是很尴尬?好奇怎么用的可以再深入了解。
全称Object XML Mapping,字面意思是对象XML映射,此模块实现了对 OXM的支持,比如 JAXB、Castor、XML Beans、JiBX、XStream。我只能说,我们实际编码中未必真的会接触,但是人家都帮我们做好了,突然不知道写这个有啥用,有几个人真正搞明白的?个人认为,对于这些模块,了解大的模块就行,比如这里是数据访问层,下面的知道个JDBC就行,其他的了解即可。
全称Java Message Service,这个博主知道,如果你还不知道,那你看下面这句话:包含消息的生产( Produce )和消费( Consume )功能。看着像MQ?是的,从Spring4.1 开始,Spring 集成了 Spring-Messaging模块,用于实现对消息队列的支持。
Transactions就是事务管理,这个大家应该都比较熟悉,该模块基于接口实现了声明式事务管理,编程式事务下,应用程序需要调用beginTransaction()、commit()、rollbac()等方法来实现事务的管理,Spring声明式事务通过注解或者配置就可以实现事务的管理,具体的工作都由Spring自动完成,开发者不必再关心提交和回滚的问题。
我们平时说的Java指的是Java Web,就是Java应用程序,用来做Web交互和数据传输等的相关功能。具体就是由以下几个模块组成的。
Web模块提供了面向web的基本功能,还提供了HTTP (Hyper Text Transfer Protocol ,超文本传输协议)客户端及 Spring 远程调用与Web 相关的部分,Web模块基于 Servlet 监听器初始化 IoC 容器
Web-MVC 模块为 Web 应用提供了模型视图控制( Model View Controller , MVC)和REST API 服务的实现。Spring MVC 框架使数据模型和视图分离,数据模型负责数据的业务逻辑,视图负责数据的展示。同时,Web-MVC 可与 Spring 框架的其他模块方便地集成。
Web-Socket 模块提供了对 WebSocket-Base 的支持,用于实现Web 应用程序中服务端和客户端实时双向通信,尤其在实时消息推送中应用广泛。
Web-Portlet 模块提供了基于 Portlet 环境的 MVC 实现,并提供了与 Spring Web-MVC 模块相关的功能。
前面的都还好,这个Web层总有点生无可恋的赶脚,我们恐怕了解不了那么深,当然不排除一些大神很有天赋,一看就懂,总之博主觉得这些看看就行。
剩下的模块共五大块,我们来分别看下都是什么。
AOP提供了面向切面编程的实现,允许应用程序通过定义方法拦截器和切人点来实现系统功能和业务功能之间的解耦,这个博主之前有写过,可自行查看使用方法。
Java开发 - AOP初体验
Aspects 模块提供了 Spring与Aspect的集成,是一个面向切面编程的模块。而AOP是Aspect Oriented Programming的简称,这就是A的由来。
Instrumentation 模块在应用中提供了对 Instrumntation 支持和类加载器的实现。这个和没说一样啊,Instrumntation是动态编程的代名词,特别是在Java SE6中,其被赋予了更多的功能,具有了更强的动态控制、解释能力、也增加了动态添加 class path 的功能。
Instrumentation 的最大作用,就是类定义动态改变和操作。在 Java SE 5 及其后续版本当中,开发者可以在一个普通 Java 程序(带有 main 函数的 Java 类)运行时,通过 –javaagent 参数指定一个特定的 jar 文件(包含 Instrumentation 代理)来启动 Instrumentation 的代理程序。
推荐一篇Java探针的博客:Java探针技术:Instrumentation
我们现在使用的框架很多都是已经帮我们做过了,以至于我们根本不了解更底层的东西,所谓成也风云,败也风云,这样也不知道是幸?还是不幸 ?
Messaging模块为 STOMP ( Simple Text Orientated Messaging Protocol ,简单文本定向消息协议)提供了支持,主要用于应用程序中 WebSocket 子协议的实现,同时,Messaging 模块可通过注解的方式来选择和处理来自 WebSocket 客户端的 STOMP 消息。
Test模块用于对JUnit等岑氏框架的支持,以实现Spring代码的自动化测试功能。
编号 | 包名 | 说明 |
1 | Spring Core | Spring 的核心工具包 |
2 | Spring Beans | Spring oC 的实现,通过 XML 配置文件或注解的方式实现 Spring Bean 的管理 |
3 | Spring Context | Spring 上下文环境,用于 Bean 关系的管理和维护等 |
4 | Spring Aspects | Spring对Aspect框架的整合和支持 |
5 | Spring Context Support | Spring Context 的扩展支持,用于 MVC 方面功能的支持 |
6 | Spring Expression Language | Spring 表达式语言 |
7 | Spring Framework Bom | 处理不同的项目依赖了不同版本的 Spring引起的版本冲突问 题 |
8 | Spring lnstrument | Spring 针对服务器的代理接口 |
9 | Spring lnstrument Tomcat | Spring 针对 Tomcat 的集成 |
10 | Spring JDBC | Spring 针对 JDBC 的封装 |
11 | Spring JMS | Spring 为简化JMS API 的使用而做的封装 |
12 | Spring Messaging | Spring 集成 Messaging API 和消息协议 |
13 | Spring ORM | Spring 整合第三方的 ORM 的实现,如 Hibemate、MyBatis、 JDO及Spring的JPA |
14 | Spring OXM | Spring Object/XML 映射的支符,可以让 Spring在Java 与XML之间方便地切换 |
15 | Spring Test | Spring 对Junit 等测试框架的支持 |
16 | Spring TX | Spring 为JDBC、Hibemate、JDO、JPA 等提供的一致的声明 式事务管理和编程式事务管理 |
17 | Spring Web | 基于 Spring 构建Web 应用开发所需的核心类,包括自动载入 WebApplicationContcxt、Struts与JSF集成、文件上传、 Filter 类和其他辅助工具类 |
18 | Spring WebMVC | 包含 Spring MVC 框架相关的所有类,例如国际化、标签、 Theme 、视图展现的 FreeMarker、JasperReports、Tiles Velocity、 XSLT 相关类。当然,如果你的应用使用了独立的 MVC 框架,则不需要使用这个 JAR 文件里的任何类 |
19 | Spring WebMVC Portlet | 基于 Portlet 环境的 Spring MVC 的增强 |
分类 | 注解 | 说明 |
Bean声明 | @Cornponent | 定义基础层的通用组件,没有明确的角色 |
@Service | 定义业务逻辑层的服务组件 | |
@Repository | 在数据访问层定义数据资源服务 | |
@Controller | 在展现层使用,用于定义控制器 | |
Bean注入 | @Autowired | 服务依赖注入,一般用于注入 @Cornponent、@Service 定义的组件 |
@Resource | 服务依赖注入,一般用于注入@Repository 定义的组件 | |
配置类注解 | @Configuration | 声明该类为配置类,其中@Value 属性可以直接和配置文件属性映射 |
@Bean | 注解在方法上,卢明该方法的返回值为一个 Bean实例 | |
@ComponentScan | 用于对 Component 进行扫描配置 | |
AOP 注解 | @EnableAspectJAutoProxy | 开启 Spring对AspectJ代理的支持 |
@Aspect | 声明一个切面 ,使用 @After、@Before、@Around 定义通知 (Advice ),可直接将拦截规则(切点)作为参数 | |
@After | 在方法执行之后执行 | |
@Before | 在方法执行之前执行 | |
@Around | 在方法执行之前和之后都执行 | |
@PointCut | 声明一个切点 | |
@Bean属性支持注解 | @Scope | 设置 Spring 容器 Bean 实例的生命周期 取值有singleton、prototype、request、session、和 global session |
@PoslConstruct | 声明方法在构造函数执行完之后开始执行 | |
@PreDestroy | 声明方法在 Bean销毁之前执行 | |
@Value | 为属性注入值 | |
@PropertySource | 声明和加载配置文件 | |
异步操作注解 | @EnableAsync | 声明在类上,开启对异步任务的支持 |
@Async | 声明方法是一个异步任务, Spring 后台基于线程池 异步执行该方法 | |
定时任务注解 | @EnableScheduling | 声明在调度类上,开启对任务调度的支持 |
@Scheduled | 声明一个定时任务,包括 cron、fïxDelay、fixRate 等参数 | |
开启功能支持注解 | @EnableAspectJAutoProxy | 开启对 AspectJ自动代理的支持 |
@EnableAsync | 开启对异步方法的支持 | |
@EnableScheduling | 开启对计划任务的支持 | |
@EnableWebMVC | 开启对 WebMVC 的配置支持 | |
@EnableConfigurationProperties | 开启对@ConfígurationPropertes 注解配置 Bean支持 | |
@EnableJpaRepositories | 开启对 SpringDataJPARepository 的支持 | |
@EnableTransactionManagement | 开启对事务的支持 | |
@EnableCaching | 开启对缓存的支持 | |
测试注解 | @RunWith | 运行器, Spring 中通常用于对Junit支持 |
@ContextConfiguration | 用来加载配置 ApplicationContext ,其中 classes属性用来加载配置类 | |
Spring MVC注解 | @Controller | 声明该类为 Spring MVC 中的控制器 |
@RequestMapping | 用于声明映射 Web 请求的地址和参数,包括访问 路径和参数 | |
@ResponseBody | 支持将返回值放在 Response Body 体中返回,通常 用于返回 JSON 数据到前瑞 | |
@RequestBody | 允许 Request 的参数在 Request Body 体中 | |
@PathVariable | 用于接收基于路径的参数,通常作为 RESTful 接口的实现 | |
@RestController | 组合注解,相当于 @Controller和@ResponseBody 的组合 | |
@ExceptionHandler | 用于全局控制器的异常处理 | |
@InitBinder | WebDataBinder用来自动绑定前台请求的参数到模型中 |
Spring 通过一个配置文件描述 Bean Bean 之间的依赖关系,利用 Java 的反射功能实例化 Bean 并建立Bean之间的依赖关系,Spring IoC 容器在完成这些底层操作的基础上,还提供了 Bean 实例缓存管理、 Bean 生命周期管理、 Bean 实例代理、事件发布和资源装载等高级服务。
单例模式下,IoC容器只会存在一个共享的Bean实例,但在多线程下,它是不安全的,会发生竞争。配置如下:
原型模式下,每次通过 Spring 容器获取 Prototype 定义的 Bean 时,容器都会重新创建一个新的Bean实例。和单例的区别是,单例的Bean是无状态的,原型的Bean有状态。配置如下:
请求级别模式下,一个HTTP请求容器只返回该Bean的同一个实例,不同的HTTP请求,容器会创建新的Bean,Bean随着HTTP请求的结束而销毁。配置如下:
Session 指在一次 HTTP Session 中容器会返回该 Bean 的同一个实例,而对不同的Session 请求则会创建新的 Bean 实例,不同的Bean实例不共享数据,请求结束,Bean实例销毁。配置如下:
Global Session 指在一个全局的 HTTP Session容器会返问该 Bean 的同一个实例,且仅在使用 Portlet Context 时有效。配置如下:
以上几种在开发中都比较常见,注入!博客认为更像是赋值,大家品一下。
有自动装配就有手动装配,手动装配包括基于 XML的装配(构造方法、 set 方法等)。自动装配包括5种专配方式,均可以用来引导 Spring 容器自动完成依赖注入,具体如下:
关于AOP的介绍和代码案例都在这里了:Java开发 - AOP初体验
Spring MVC中的MVC即模型-视图-控制器,该框架围绕 DispatcherServlet 设计,把请求分发给各个处理器,并支持可配置的处理器映射和视图渲染等功能。其详细流程如下:
相较于Spring,Spring Boot是一个全新的项目,目的是为了简化Spring的初始搭建以及开发过程,使得开发人员不需要再定义样板化的配置。通过这种方式,Spring Boot成为了快速开发的代名词。其有如下特点:
Spring Boot可以以jar包的方式独立运行,通过命令“ java–jar xx.jar”,创建独立的Spring应用程序,并且基于其Maven或Gradle插件,可以创建可执行的JARs和WARs。
Spring Boot 使用嵌入式的 Servlet 容器(例如 Tomcat、Jetty 或者 Undertow 等),应用无需打成 WAR 包 。
Spring Boot 提供了一系列的“starter”项目对象模型(POMS)来简化 Maven 配置,如: spring-boot-starter-redis、spring-boot-starter-data-mongodb 和 spring-boot-starter-data-elasticsearch等。
Spring Boot 提供了大量的默认自动配置来简化项目的开发,开发人员也通过配置文件修改默认配置,这种尽可能自动配置Spring容器的方式,可以说是开发者的福音。
提供生产就绪功能,如指标、健康检查和外部配置等。
创建好的Spring Boot项没有额外代码生成,也没有XLM相关的配置,你甚至在项目中找不到XML文件。
关于事务和分布式事务,博主在下面这篇博客中讲解的很清楚了:
Java开发 - 分布式事务详解
MyBatis的缓存分为一级缓存和二级缓存,在默认情况下,一级缓存是开启的,而且不能被关闭的。
客户端发出一个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 Data、Spring Security、Spring AMQP等,详细可查看下面的链接:
Spring Framework
这里只是粗浅的介绍了Spring中有哪些东西,能把这些东西搞懂也算是差不多了吧。哈哈,其实“差不多”这个词挺害人的,但能掌握多少,掌握到什么程度,就是大家自己的事情了,内容不少,大家可以有针对性的去看去学,像里面有些东西博主都是一笔带过,不是说不重要,只是没有想象中那么重要,要是有时间,可以深入研究,那今天就到这里吧,博主也需要拐回去好好再看几遍。