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轉換為真實業務服務的請求地址的核心過濾器,不需要配置,系統初始化時加載,並作用在每個路由上。