spring全家桶

一 .spring

1. 介绍

(1)spring是一个轻量级的,ioc/aop的开源的分层框架低入侵/低耦合

(2)根据配置文件创建及组装对象之间的依赖关系

(3)面向切面编程能帮我们无耦合的实现日志记录,性能统计,安全控制,管理数据库事务

(4)能与第三方数据库框架无缝集合,能与第三方web框架集合,能与javaee集合


spring加载Bean过程

2.IOC

控制反转,一种设计思想,将原本在程序中手动创建对象的控制权,交给spring框架来管理;当需要某个对象的时候只需要从spring容器中取出,不关心对象的创建过程

Spring 通过一个配置文件描述 Bean 及 Bean 之间的依赖关系,利用 Java 语言的反射功能实例化 Bean 并建立 Bean 之间的依赖关系。 Spring 的 IoC 容器在完成这些底层工作的基础上,还提供了 Bean 实例缓存、生命周期管理、 Bean 实例代理、事件发布、资源装载等高级服务

BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身

ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合我们都直接使用 ApplicationContext 而非底层的BeanFactory

Spring 配置文件中每一个节点元素在 Spring 容器里都通过一个 BeanDefinition 对象表示,它描述了Bean 的配置信息。而 BeanDefinitionRegistry 接口提供了向容器手工注册 BeanDefinition 对象的方法

(1) BeanFactory

    BeanFactory管理对象之间的关系

    BeanFactory定义了获取单个Bean的实例特征方法,一个应用中有多个BeanFactory;BeanFactory是Bean的容器,支持两种对象模型:

    单例:提供了具有特定名称的对象的共享,默认的最常用的

    原型:每次检索都会创建单独的对象,当每个用户需要创建自己的对象时,需要用到原型


  BeanFactory :接口位于类接口树的顶端,它最主要的方法就是 getBean(String beanName),该方法从容器中返回特定名称的Bean

  ConfigurableBeanFactory:是一个重要的接口,增强了 IoC 容器的可定制性,它定义了设置类装载器、属性编辑器、容器初始化后置处理器等方法

  SingletonBeanRegistry:定义了允许在运行期间向容器注册单实例 Bean 的方法

  AutowireCapableBeanFactory:定义了将容器中的 Bean 按某种规则(如按名字匹配、按类型匹配等)进行自动装配的方法

  ListableBeanFactory:该接口定义了访问容器中 Bean 基本信息的若干方法,如查看Bean 的个数、获取某一类型 Bean 的配置名、查看容器中是否包括某  一 Bean 等方法

HierarchicalBeanFactory:父子级联 IoC 容器的接口,子容器可以通过接口方法访问父容器; 通过 HierarchicalBeanFactory 接口, Spring 的 IoC 容器可以建立父子层级关联的容器体系,子容器可以访问父容器中的 Bean,但父容器不能访问子容器的 Bean

(2)ApplicationContext

      ApplicationContext 由 BeanFactory 派生而来,提供了更多面向实际应用的功能

      ApplicationContext 在初始化应用上下文时就实例化所有单实例的 Bean

    ClassPathXmlApplicationContext:默认从类路径加载配置文件

    FileSystemXmlApplicationContext:默认从文件系统中装载配置文件

(3)spring加载Bean过程


a、ResourceLoader从存储介质中加载Spring配置信息,并使用Resource表示这个配置文件的资源;

b、BeanDefinitionReader读取Resource所指向的配置文件资源,然后解析配置文件。配置文件中每一个解析成一个BeanDefinition对象,并保存到BeanDefinitionRegistry中;

c、容器扫描BeanDefinitionRegistry中的BeanDefinition,使用Java的反射机制自动识别出Bean工厂后处理后器(实现BeanFactoryPostProcessor接口)的Bean,然后调用这些Bean工厂后处理器对BeanDefinitionRegistry中的BeanDefinition进行加工处理

d、Spring容器从BeanDefinitionRegistry中取出加工后的BeanDefinition,并调用InstantiationStrategy着手进行Bean实例化的工作;

e、在实例化Bean时,Spring容器使用BeanWrapper对Bean进行封装,BeanWrapper提供了很多以Java反射机制操作Bean的方法,它将结合该Bean的BeanDefinition以及容器中属性编辑器,完成Bean属性的设置工作;

f、利用容器中注册的Bean后处理器(实现BeanPostProcessor接口的Bean)对已经完成属性设置工作的Bean进行后续加工,直接装配出一个准备就绪的Bean。

单例Bean缓存池:Spring 在 DefaultSingletonBeanRegistry 类中提供了一个用于缓存单实例 Bean 的缓存器,它是一个用 HashMap 实现的缓存器,单实例的 Bean 以 beanName 为键保存在这个HashMap 中

3.AOP


(1)概念

      面向切面编程,把核心业务功能和切面功能分开,减少系统的重复代码,降低模块间的耦合度,利于后续的扩展性和可维护性

(2)  aop中的一些概念:

    切入点(pointcut):在哪些类,哪些方法上切入(where)

    连接点(join point):执行过程中明确的点

    通知(advice):在方法执行的什么时候(when 方法前/后/前后)做什么事情(what增强的功能)

      切面(aspect):切入点+通知,在什么时机 什么地方  做什么事

      织入(weaving):把切面加入到对象,并创建出代理对象的过程


一个简单的aop应用

(3)aop实现过程

  配置文件中声明自动发现注解,spring默认启动时会注册注解解析器(AspectJAutoProxyBeanDefinitionParser),在注解解析器解析(parse)的过程中,会注册一个实现了BeanPostProcessor的后处理器(AspectJAwareAdvisorAutoProxyCreator),这个后处理器在目标对象实例化后进行拦截处理,拦截的流程是,先搜索所有已经注册的BeanDefiniton,从中找到标记了注解(@Aspect)的切面组成拦截器链,选择那些可以应用到目标对象的拦截器(过滤),如果拦截器链不为空,则为目标对象生成代理(JdkDynamicAopProxy或CglibAopProxy),当调用目标对象的指定拦截方法时,就会默认调用对应代理类的代理方法(invoke),这样就完成了AOP的整个流程

(4)代理

JDK动态代理:目标类实现了接口,默认采用JDK动态代理实现aop,可通过配置文件强行使用cglib代理实现aop,关键方法invoke

cglib代理:目标类没有实现接口,用CGLIB代理实现asop

CGLIB原理:动态生成一个要代理类的子类,子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。它比使用java反射的JDK动态代理要快。

CGLIB底层:使用字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。

CGLIB缺点:对于final方法,无法进行代理。

(5)应用场景

事务拦截器,日志拦截器性能拦截器还有权限拦截

4. 事务隔离级别

(1) 脏读:脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据

(2)不可重复读:是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两 次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的

(3) 幻读: 是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。 同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象 发生了幻觉一样

(4) 五个不同的事务隔离级别

ISOLATION_DEFAULT : 是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应

ISOLATION_READ_UNCOMMITTED :这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读

ISOLATION_READ_COMMITTED :保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读

ISOLATION_REPEATABLE_READ :这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读

ISOLATION_SERIALIZABLE :这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读

5.事务传播行为

PROPAGATION_REQUIRED :如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务

PROPAGATION_SUPPORTS :如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行

PROPAGATION_MANDATORY :如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。

PROPAGATION_REQUIRES_NEW :总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。

PROPAGATION_NOT_SUPPORTED :总是非事务地执行,并挂起任何存在的事务

PROPAGATION_NEVER :总是非事务地执行,如果存在一个活动事务,则抛出异常

PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行

二.spring mvc

1.spring mvc使用

核心类是DispatcherServlet,统一调度,降低组件之间的耦合性,提高每个组件的扩展性,它是一个Servlet,顶层是实现的Servlet接口

需要在web.xml中配置DispatcherServlet。并且需要配置spring监听器ContextLoaderListener

2.springmvc请求流程


(1)客户端(浏览器)发送请求,直接请求到DispatcherServlet。

(2)DispatcherServlet根据请求信息调用HandlerMapping,解析请求对应的Handler。

(3)解析到对应的Handler后,开始由HandlerAdapter适配器处理。

(4)HandlerAdapter会根据Handler来调用真正的处理器开处理请求,并处理相应的业务逻辑。

(5)处理器处理完业务后,会返回一个ModelAndView对象,Model是返回的数据对象,View是个逻辑上的View。

(6)ViewResolver会根据逻辑View查找实际的View。

(7)DispaterServlet把返回的Model传给View。

(8)通过View返回给请求者(浏览器)

3.spring mvc三大组件

处理器映射器、处理器适配器、视图解析器

三.springboot

1.简介

让spring应用变得更轻量化:传统的spring项目需要构建项目,打包应用,部署到服务器来运行我们的业务服务。spring boot只需要一个java类,打包成jar包,通过java -jar xxx.jar命令就可以运行起来。


四.spring cloud

1.简介

(1)Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中涉及的配置管理、服务发现、断路器、智能路由、微代理、控制总线、全局锁、决策竞选、分布式会话和集群状态管理等操作提供了一种简单的开发方式

(2)Spring Cloud包含了多个子项目(针对分布式系统中涉及的多个不同开源产品),比如:Spring Cloud Config、Spring Cloud Netflix、Spring Cloud0 CloudFoundry、Spring Cloud AWS、Spring Cloud Security、Spring Cloud Commons、Spring Cloud Zookeeper、Spring Cloud CLI等项目

2.Spring Cloud Eureka

(1).实现服务治理

它主要提供的模块包括:服务发现(Eureka),断路器(Hystrix),智能路由(Zuul),客户端负载均衡(Ribbon)

(2). 服务注册实现步骤:

创建springboot工程在pom文件中添加依赖

通过@EnableEurekaServer注解启动一个服务注册中心

在配置文件中添加配置信息

lease-renewal-interval-in-seconds:服务提供者维护一个心跳,告诉注册中心,我还活着,防止该服务被剔除

(3).服务发现

服务间的调用通过服务名来实现。当服务调用方要调用服务提供方时,服务调用方不知道服务提供方的具体地址的,需要向注册中心咨询服务,来获取所有的服务清单;例如:现有服务B想要调用服务A,服务B就需要向注册中心发起请求获取服务A的实例清单,注册中心返回服务A的实例清单,然后服务B会从清单中以某种策略轮询访问清单中的的实例,实现负载均衡的效果访问方式可以通过 Ribbon。实际生产项目中,不会在每一次请求中都获取服务列表清单,这样做效率低下。实际场景中缓存和服务剔除等机制也会有一些不同的实现方式

(4).服务注册

当Client发起注册请求时,这个实例首先要做的事情是保存到内部Eureka中的数据结构(数据结构是双向map),同时,Eureka Server当中会维护一个最近改变的队列,这个Client会定期的向Server发起同步,目的是为了向Server定期发出“我还活着,不要把我剔除”的信息。通常默认发送的频率是30秒一次,Eureka Client会持续向Eureka Server发起同步,在Eureka Server的数据结构中找到该次续约对应的Eureka Client,同时把Eureka Client对应的时间进行更新,这种更新只是把对应的节点取出来,更新到对应的时间戳,同时,再把这个信息复制给相邻的Eureka Server节点

3.Spring Cloud Feign

(1).使用Feign实现服务之间的调用

(2).实现步骤

创建一个springboot工程,在pom文件中添加依赖

修改应用主类。通过@EnableFeignClients注解开启扫描Spring Cloud Feign客户端的功能

创建一个Feign的客户端接口定义,使用@FeignClient注解来指定这个接口所要调用的服务名称

注解:value: 目标服务名,一般都是 application.name; fallback : 服务降级策略;configuration:重写feign的配置


(3) 结论

feign是通过动态代理的技术将一个interface变为Web Service客户端,但是仅仅只用这个注解feign是不会生效的,必须要在启动类上加上EnableFeignClients,feign才会自动扫描feignClient。所以我们的入口应该是 EnableFeignClients

(4)spring中使用原生feign

提供feign接口: tokit-provider-elasticsearch-api

提供调用服务:test-feign:

在test-feign pom中添加feign依赖

添加json依赖:

在配置文件中添加:

使用注解 配置接口等待调用:

Feign.Builder 设置发送http请求的相关参数feign.Contract 默认提供springmvc的注解解析,支持@RequestMapping,@RequestBody,@RequestParam,@PathVariable

调用:

4.Spring Cloud  Hystrix

(1)请求熔断

当hystrix Command请求后端服务器失败的次数达到一定数量(默认50%),断路由会切换到开路状态(open),这时所有的请求不会到后端服务,断路由保持在一段时间后(默认5s)自动切换到搬开路由状态,这时会判断下一次请求的返回情况,如果成功,断路由切回闭路状态,否则切换到open状态

(2)服务降级

fallback相当于降级操作,对于一个查询操作,可以实现一个fallback方法,当请求后端服务出现异常的时候,可以使用fallback方法返回的值,

(3)依赖隔离(采用舱壁模式,Docker就是舱壁模式的一种)

在Hystrix中, 主要通过线程池来实现资源隔离. 通常在使用的时候我们会根据调用的远程服务划分出多个线程池.比如说,一个服务调用两外两个服务,你如果调用两个服务都用一个线程池,那么如果一个服务卡在哪里,资源没被释放后面的请求又来了,导致后面的请求都卡在哪里等待,导致你依赖的A服务把你卡在哪里,耗尽了资源,也导致了你另外一个B服务也不可用了。这时如果依赖隔离,某一个服务调用A B两个服务,如果这时我有100个线程可用,我给A服务分配50个,给B服务分配50个,这样就算A服务挂了,我的B服务依然可以用

(4)请求缓存

比如一个请求过来请求我userId=1的数据,你后面的请求也过来请求同样的数据,这时我不会继续走原来的那条请求链路了,而是把第一次请求缓存过了,把第一次的请求结果返回给后面的请求

(5)请求合并

我依赖于某一个服务,我要调用N次,比如说查数据库的时候,我发了N条请求发了N条SQL然后拿到一堆结果,这时候我们可以把多个请求合并成一个请求,发送一个查询多条数据的SQL的请求,这样我们只需查询一次数据库,提升了效率

(6)实现

创建一个springboot工程,在pom文件中添加依赖


在应用主类中使用@EnableCircuitBreaker或@EnableHystrix注解开启Hystrix的使用

使用 基于feign 在接口中加上fallback的指定类就行了

5.Spring Cloud Gateway

(1)简介

Router(路由):网关的基本构建块。它由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配

predicate(断言):匹配来自 HTTP 请求的任何内容

filter(过滤器):使用它修改请求和响应


(2)实现

创建一个springboot工程,在pom文件中添加依赖


在配置文件中添加如下配置

网关配置图

当我们访问http://localhost:8090/java/helloWorld  ==> 转发到http://localhost:8090/helloWorld

(3) predicate


Predict决定了请求由哪一个路由处理

Predict作为断言,它决定了请求会被路由到哪个router 中。在断言之后,请求会被进入到filter过滤器的逻辑

每一种predicate都会对当前的客户端请求进行判断,是否满足当前的要求,如果满足则交给当前请求处理。如果有很多个Predicate,并且一个请求满足多个Predicate,则按照配置的顺序第一个生效

(4)filter

作用  :  在微服务的上一层加一个全局的权限控制、限流、日志输出的Api Gatewat服务,然后再将请求转发到具体的业务服务层。这个Api Gateway服务就是起到一个服务边界的作用,外接的请求访问系统,必须先通过网关层


没有网关


添加网关

生命周期  :客户端的请求先经过“pre”类型的filter,然后将请求转发到具体的业务服务,比如上图中的user-service,收到业务服务的响应之后,再经过“post”类型的filter处理,最后返回响应到客户端。

GatewayFilter

工厂同上一篇介绍的Predicate工厂类似,都是在配置文件application.yml中配置,遵循了约定大于配置的思想,只需要在配置文件配置GatewayFilter Factory的名称,而不需要写全部的类名 ,

一下是Spring Cloud Gateway 内置的过滤器工厂 每一个过滤器工厂在官方文档都给出了详细的使用案例,可以参考

自定义:  使用 如上网关使用图中使用到的 TokitApiAuth 过滤器  比喻TokitApiAuthGatewayFilterFactory ,只需要在配置文件中写TokitApiAuth就可以了

global filter 

全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器,它为请求业务以及路由的URI转换为真实业务服务的请求地址的核心过滤器,不需要配置,系统初始化时加载,并作用在每个路由上。

Spring Cloud Gateway 参考链接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341