spring-cloud-square源码速读(spring-cloud-square-okhttp篇)

public Builder addInterceptor(Interceptor interceptor) {

if (interceptor == null) throw new IllegalArgumentException(“interceptor == null”);

interceptors.add(interceptor);

return this;

}

  • builder是为实例化OkHttpClient服务的,去看OkHttpClient的构造方法,发现interceptors被复制过来了:

在这里插入图片描述

  • 在使用OkHttpClient访问网络的时候,会执行下图红框中的getResponseWithInterceptorChain:

在这里插入图片描述

  • 然后就是经典的链式处理了,所有的interceptor都会被执行,下图展示了如何构造和启动链式处理:

在这里插入图片描述

  • 进入proceed内部,可见每次执行proceed方法,都会取出一个interceptor,调用其intercept方法:

在这里插入图片描述

  • 以spring-cloud-square框架的OkHttpLoadBalancerInterceptor为例,下图红框中的方法极为重要,这行代码执行后,会回到上一幅图中的proceed方法,继续处理下一个interceptor:

在这里插入图片描述

  • 至此可以小结了:OkHttpClient.Builder.addInterceptor方法的作用,是传入一个Interceptor实现类,在OkHttpClient执行网络请求的时候,该Interceptor的intercept方法会被执行,请记住这个小结,后面有大用处!

spring-cloud-square-okhttp

  • spring-cloud-square提供了三种具体的实现,第一种是spring-cloud-loadbalancer + spring-cloud-square-okhttp的组合,而spring-cloud-loadbalancer是另一个项目不在此文中展开,因此,咱们最先看的就是spring-cloud-square-okhttp的源码了

  • 打开项目如下图,我只能感慨两个字:就这?

在这里插入图片描述

  • 关于配置文件additional-spring-configuration-metadata.json,在spring文档中有提到,如下图红框,负责处理注解的处理器会将additional-spring-configuration-metadata.json的内容合并到元数据文件中去:

在这里插入图片描述

  • 看看additional-spring-configuration-metadata.json的内容,如下,定义了属性okhttp.loadbalancer.enabled的默认值为true:

{

“groups”: [

],

“properties”: [

{

“name”: “okhttp.loadbalancer.enabled”,

“type”: “java.lang.Boolean”,

“description”: “Allows disabling OkHttp Spring Cloud LoadBalancer support.”,

“defaultValue”: “true”

}

]

}

  • 如果您写过自定义starter库,那么您一定知道,整个spring-cloud-square-okhttp项目应该从spring.factories文件看起,这里面会确定那些配置类要被实例化:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\

org.springframework.cloud.square.okhttp.loadbalancer.OkHttpLoadBalancerAutoConfiguration

  • 可见配置类OkHttpLoadBalancerAutoConfiguration会被实例化,咱们去看看OkHttpLoadBalancerAutoConfiguration.java,如下图,经过一长串分析得到一个结论:OkHttpBuilderBeanPostProcessor被实例化了

在这里插入图片描述

  • 再看OkHttpBuilderBeanPostProcessor.java,如下图,重点关注红框中的三个关键点:

在这里插入图片描述

  • 回忆《spring-cloud-square开发实战(三种类型全覆盖)》中的代码,咱们在使用spring-cloud-square-okhttp.jar的时候,要自己写一个配置类来实例化OkHttpClient.Builder,如下所示,因此可见:OkHttpBuilderBeanPostProcessor就是给咱们创建的OkHttpClient.Builder实例准备的,简单的说,就是OkHttpClient.Builder在创建后,就有OkHttpBuilderBeanPostProcessor将OkHttpLoadBalancerInterceptor传递给OkHttpClient.Builder:

package com.bolingcavalry.consumer;

import okhttp3.OkHttpClient;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

@Configuration

class OkHttpClientConfig{

@Bean

@LoadBalanced

public OkHttpClient.Builder okHttpClientBuilder() {

return new OkHttpClient.Builder();

}

}

  • 此刻的您有没有恍然大悟呢?原来如此啊,所谓spring-cloud-square-okhttp,其实就是要求用户自己做一个OkHttpClient.Builder实例,然后spring-cloud-square-okhttp负责将OkHttpLoadBalancerInterceptor塞给OkHttpClient.Builder实例,如此一来,我们在使用OkHttpClient做远程调用的时候,OkHttpLoadBalancerInterceptor的intercept方法就会被执行了!

  • 最后要看的就是OkHttpLoadBalancerInterceptor了,其实聪明的您此刻已经猜到它的作用了,它持有了LoadBalancerClient实例,那么在访问网络的时候,就可以将URL中的服务名抠出来,用LoadBalancerClient查到对应的服务地址,然后OkHttpClient远程访问可以用这个地址了,没错,就是如此:

在这里插入图片描述

收获

  • 其实整个源码的核心就是给OkHttpClient塞进去一个Interceptor,这个Interceptor可以将服务名替换成IP和地址,功能仅此而已,但是收获是否会止步于此呢?这是个主观问题,各人的收获都不一样吧,我这最大的收获有以下两点:
  1. OkHttpClient的链式处理很精彩,Interceptor.intercept中强制要求执行chain.proceed方法,让我想起了装饰者模式中的叠加处理逻辑

  2. 如何用spring.factories + AutoConfig + BeanPostProcessor + SpringCloud LoadBalance协同作战,spring-cloud-square-okhttp算是给我上了一课,尤其是OkHttpLoadBalancerAutoConfiguration中三个构造器的顺序注入,让人有种鼓掌叫好的冲动,我能写出这样简洁明快的starter吗?

  • 至此,spring-cloud-square源码速读的spring-cloud-squarespring-cloud-square-okhttp篇已经完成了,在您学习spring的道路上,希望本文能够带给您一些参考

  • 接下来要挑战的是spring-cloud-square的retrofit相关源码,代码量会增加很多,但是,何惧之有?欣宸原创,必不会辜负您的期待!

你不孤单,欣宸原创一路相伴

最后

ActiveMQ消息中间件面试专题

  • 什么是ActiveMQ?
  • ActiveMQ服务器宕机怎么办?
  • 丢消息怎么办?
  • 持久化消息非常慢怎么办?
  • 消息的不均匀消费怎么办?

必看视频!获取2024年最新Java开发全套学习资料 备注Java

  • 死信队列怎么办?
  • ActiveMQ中的消息重发时间间隔和重发次数吗?

ActiveMQ消息中间件面试专题解析拓展:

BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM


redis面试专题及答案

  • 支持一致性哈希的客户端有哪些?
  • Redis与其他key-value存储有什么不同?
  • Redis的内存占用情况怎么样?
  • 都有哪些办法可以降低Redis的内存使用情况呢?
  • 查看Redis使用情况及状态信息用什么命令?
  • Redis的内存用完了会发生什么?
  • Redis是单线程的,如何提高多核CPU的利用率?

BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM


Spring面试专题及答案

  • 谈谈你对 Spring 的理解
  • Spring 有哪些优点?
  • Spring 中的设计模式
  • 怎样开启注解装配以及常用注解
  • 简单介绍下 Spring bean 的生命周期

Spring面试答案解析拓展

BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM


高并发多线程面试专题

  • 现在有线程 T1、T2 和 T3。你如何确保 T2 线程在 T1 之后执行,并且 T3 线程在 T2 之后执行?
  • Java 中新的 Lock 接口相对于同步代码块(synchronized block)有什么优势?如果让你实现一个高性能缓存,支持并发读取和单一写入,你如何保证数据完整性。
  • Java 中 wait 和 sleep 方法有什么区别?
  • 如何在 Java 中实现一个阻塞队列?
  • 如何在 Java 中编写代码解决生产者消费者问题?
  • 写一段死锁代码。你在 Java 中如何解决死锁?

高并发多线程面试解析与拓展

BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM


jvm面试专题与解析

  • JVM 由哪些部分组成?
  • JVM 内存划分?
  • Java 的内存模型?
  • 引用的分类?
  • GC什么时候开始?

JVM面试专题解析与拓展!

BAT面试文档:ActiveMQ+redis+Spring+高并发多线程+JVM

消费者问题?

  • 写一段死锁代码。你在 Java 中如何解决死锁?

高并发多线程面试解析与拓展

[外链图片转存中…(img-nbxzOVGE-1716356395008)]


jvm面试专题与解析

  • JVM 由哪些部分组成?
  • JVM 内存划分?
  • Java 的内存模型?
  • 引用的分类?
  • GC什么时候开始?

JVM面试专题解析与拓展!

[外链图片转存中…(img-5bPuRMsL-1716356395009)]

  • 19
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值