摘要: Retrofit通过Java动态代理 在运行时生成接口的实现类。当调用声明了HTTP注解(如@GET
)的接口方法时,代理拦截请求:
- 解析方法注解和参数,构建HTTP请求模板;
- 将参数注入请求模板生成完整请求;
- 委托OkHttp执行网络调用。
此机制实现声明式API,开发者只需定义接口,Retrofit+OkHttp自动处理网络通信,极大简化代码。
思维导图: 1.设计模式 2.线程池,队列 3.网络知识
1.完整流程分析(从代理创建到请求发起)
使用的过程
less
// 原始接口方法
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
swift
// 1. 创建Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
// 2. 创建动态代理对象
GitHubService service = retrofit.create(GitHubService.class);
// 3. 调用接口方法
Call<List<Repo>> call = service.listRepos("octocat");
// 4. 发起网络请求
call.enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
// 处理成功响应
List<Repo> repos = response.body();
}
@Override
public void onFailure(Call<List<Repo>> call, Throwable t) {
// 处理失败
}
});
第一步骤: 创建Retrofit
第二步骤: 创建动态代理对象 GitHubService service = retrofit.create(GitHubService.class);
第三步骤: 代理的是接口调用方法: Call<List> call = service.listRepos("octocat");
第四步骤: 请求放入线程池执行

1.1.1 根本的作用:核心目标:将Java接口方法转换为HTTP请求,无需手动实现接口。
1.1.2 create()方法: 返回的是一个接口!
ini
UserService service = retrofit.create(UserService.class);
create()
返回的是一个动态生成的接口代理对象,该对象:
- 在方法调用时实时解析注解
- 封装网络请求为可执行对象
- 通过适配器支持多种返回类型
- 本身不包含状态,仅作为访问 Retrofit 核心功能的入口
1.1.3 方法拦截机制
当调用接口方法时,实际执行的是 InvocationHandler.invoke()
:
typescript
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
// 1. 解析方法注解
ServiceMethod<?> serviceMethod = loadServiceMethod(method);
// 2. 创建网络请求对象
OkHttpCall<?> okHttpCall = new OkHttpCall<>(serviceMethod, args);
// 3. 适配返回类型
return serviceMethod.adapt(okHttpCall);
}
}
方法调用流程图

1.2 代理对象返回的实际类型
实际返回的是ServiceMethod.adapt()的结果 return serviceMethod.adapt(okHttpCall);
less
public <T> T create(final Class<T> service) {
return (T) Proxy.newProxyInstance(
service.getClassLoader(),
new Class<?>[]{service},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
// 核心逻辑:解析方法并执行请求:cite[1]:cite[3]
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
});
}
整个T,就是返回的T
public interface GitHubService {
// T = Call<List<Repo>>
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
// T = Observable<List<Repo>>
@GET("users/{user}/repos")
Observable<List<Repo>> listReposRx(@Path("user") String user);
// T = Deferred<List<Repo>>
@GET("users/{user}/repos")
Deferred<List<Repo>> listReposDeferred(@Path("user") String user);
}
中间过程: 1)。 注解解析 : 2)。参数处理 : 3)。适配器与转换器:
最终封装的是一个call对象! T,是实体对象
1.2.1 拦截方法调用(InvocationHandler.invoke()
)
当调用接口方法时,触发以下流程:
- 解析方法元数据 :通过
loadServiceMethod(method)
加载或创建ServiceMethod
对象,解析方法注解(如@GET
)、参数注解(如@Path
)及返回值类型。 - 构造OkHttpCall :将解析后的参数封装为
OkHttpCall
,内部持有OkHttp请求配置。 - 适配返回值 :通过
serviceMethod.adapt()
将OkHttpCall
转换为目标类型(如Call<T>
、Observable<T>
)
1.2.2 ServiceMethod: 核心类
ini
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
// 1. 解析方法注解
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
// 2. 解析返回类型
Type returnType = method.getGenericReturnType();
// 3. 获取CallAdapter
CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(method);
// 4. 获取Converter
Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(method);
// 5. 创建ServiceMethod
result = new ServiceMethod<>(requestFactory, callAdapter, responseConverter);
// 6. 缓存结果
serviceMethodCache.put(method, result);
return result;
}
}
ServiceMethod的核心职责
- 注解解析 :使用
RequestFactory
解析方法注解,生成HTTP请求模板(URL、方法类型等)。 - 数据转换 :通过
Converter.Factory
将参数转换为HTTP请求体(如JSON序列化 - 适配调度 :调用
CallAdapter.adapt()
将OkHttpCall
适配为接口声明的返回值类型
1.3 动态生成的代理类源码(模拟)
typescript
// JVM 动态生成的代理类(伪代码)
public final class $Proxy0 extends Proxy implements GitHubService {
private static Method m1; // hashCode()
private static Method m2; // equals()
private static Method m3; // toString()
private static Method m4; // listRepos()
static {
try {
m4 = Class.forName("com.example.GitHubService")
.getMethod("listRepos", String.class);
} catch (Exception e) {
throw new Error(e);
}
}
public $Proxy0(InvocationHandler h) {
super(h);
}
@Override
public Call<List<Repo>> listRepos(String user) {
try {
// 所有调用转发给InvocationHandler
return (Call<List<Repo>>) h.invoke(this, m4, new Object[]{user});
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
}
问题:代理的是啥?生成的是啥?
less
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
// 代理前:纯接口,无实现
GitHubService service = ? // 无法直接实例化
// 代理后:生成实现类
GitHubService service = retrofit.create(GitHubService.class);
service.listRepos("octocat"); // 触发网络请求

1.4 适配器模式(CallAdapter)的联动
流程图:

1. 注册适配器工厂
scss
Retrofit retrofit = new Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 注册RxJava适配器
.build();
2. 接口方法声明目标类型
less
public interface GitHubService {
@GET("users/{user}/repos")
Observable<List<Repo>> listRepos(@Path("user") String user); // 返回Observable
}
3. 关键源码定位(简化版)
typescript
// ServiceMethod 中完成适配
final class ServiceMethod<R> {
CallAdapter<R, ?> callAdapter;
Object adapt(Call<R> call) {
return callAdapter.adapt(call); // 关键适配点
}
}
// RxJavaCallAdapter 实现
final class RxJavaCallAdapter implements CallAdapter<R, Observable<?>> {
@Override
public Observable<?> adapt(Call<R> call) {
return Observable.create(emitter -> {
call.enqueue(new Callback<R>() {
@Override public void onResponse(Call<R> c, Response<R> response) {
emitter.onNext(response.body());
emitter.onComplete();
}
@Override public void onFailure(Call<R> c, Throwable t) {
emitter.onError(t);
}
});
});
}
}
Retrofit 的适配器模式实现了"网络请求执行"与"结果处理方式"的分离: 我们需要什么结果类型,自动转换成什么样的数据类型!
有哪些适配器
- Kotlin 项目 → 首选 协程
suspend
函数(Retrofit 2.6.0+ 原生支持) - 响应式项目 → RxJava (Android) / Reactor (Spring)
- Java 项目 →
CompletableFuture
(Java 8+) 或 RxJava - 特殊需求 → 自定义适配器(如
Optional
、Result
封装)
1.5 Okhttp和Retrofit的对比
有了Okhttp,为什么还要Retrofit,它是为了解决什么问题
- 每个 API 都需要手动构建
Request
对象 - 需要手动拼接 URL 和参数
- 需要重复编写响应解析逻辑
从下面的使用对比: okhttp需要手动封装请求和处理json数据! Retrofit的动态代理和适配器模式就是解决了这2个问题!
1.5.1 okhttp的使用
scss
private void okhttp(){
// 1. 创建客户端
OkHttpClient client = new OkHttpClient();
// 2. 手动构建请求
Request request = new Request.Builder()
.url("https://api.github.com/users/octocat/repos")
.build();
// 3. 发送请求并处理原始响应
client.newCall(request).enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) throws IOException {
// 4. 手动解析 JSON
String json = response.body().string();
List<Repo> repos = new Gson().fromJson(json, new TypeToken<List<Repo>>(){}.getType());
// 5. 手动线程切换
runOnUiThread(() -> updateUI(repos));
}
@Override
public void onFailure(Call call, IOException e) {
// 错误处理
}
});
}
1.5.2 Retrofit的使用
less
private void retrofit(){
// 1. 定义接口(声明式API)
interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
// 2. 创建服务实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
GitHubService service = retrofit.create(GitHubService.class);
// 3. 直接调用接口方法
service.listRepos("octocat").enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
// 4. 自动获得解析后的对象(主线程回调)
updateUI(response.body());
}
@Override
public void onFailure(Call<List<Repo>> call, Throwable t) {
// 错误处理
}
});
}
两者关系如图:

整体的架构图
设计优势:
- 解耦:接口定义与实现分离
- 复用:统一处理所有API方法
2. 如果不用动态代理,怎么实现retrofit的那部分
2.1、手动实现接口方案(静态代理)
java
// 接口定义
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
// 手动实现类
public class ManualGitHubService implements GitHubService {
private final Retrofit retrofit;
public ManualGitHubService(Retrofit retrofit) {
this.retrofit = retrofit;
}
@Override
public Call<List<Repo>> listRepos(String user) {
// 1. 手动解析注解
String path = "users/" + user + "/repos";
// 2. 构建请求
HttpUrl url = retrofit.baseUrl().resolve(path);
Request request = new Request.Builder()
.url(url)
.get()
.build();
// 3. 创建OkHttpCall
okhttp3.Call rawCall = retrofit.callFactory().newCall(request);
// 4. 创建Converter
Converter<ResponseBody, List<Repo>> converter = retrofit.responseBodyConverter(
new TypeToken<List<Repo>>(){}.getType(),
new Annotation[0]
);
// 5. 返回包装后的Call
return new OkHttpCall<>(request, rawCall, converter);
}
}
// 客户端使用
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = new ManualGitHubService(retrofit);
Call<List<Repo>> call = service.listRepos("octocat");
call.enqueue(...);
缺点:
- 每个接口都需要手动创建实现类
- 注解解析逻辑重复
- 新增接口方法需要修改实现类
- 无法自动处理复杂参数(如@QueryMap)
反射调用(无动态代理)
- 原理:手动解析方法注解和参数,通过反射执行请求。
- 优点:灵活性高;无需生成代理类。
- 缺点:反射性能损耗;易出错(类型安全弱)。
2.2 手动实现 + Builder 模式
实现原理 :放弃接口声明,改用 Builder 链式调用
类似库:Volley、原生 OkHttp 封装
实现示例:
typescript
public class ApiClient {
private final String baseUrl;
private final OkHttpClient client;
public ApiClient(String baseUrl) {
this.baseUrl = baseUrl;
this.client = new OkHttpClient();
}
public RequestBuilder newRequest(String path) {
return new RequestBuilder(baseUrl + path);
}
public static class RequestBuilder {
private final String url;
private String method = "GET";
private Map<String, String> params = new HashMap<>();
public RequestBuilder(String url) {
this.url = url;
}
public RequestBuilder method(String method) {
this.method = method;
return this;
}
public RequestBuilder addParam(String key, String value) {
params.put(key, value);
return this;
}
public Call<List<Repo>> build() {
HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
urlBuilder.addQueryParameter(entry.getKey(), entry.getValue());
}
Request request = new Request.Builder()
.url(urlBuilder.build())
.method(method, null)
.build();
return new OkHttpCall<>(request);
}
}
}
// 使用方式
ApiClient client = new ApiClient("https://api.github.com/");
Call<List<Repo>> call = client.newRequest("users/octocat/repos")
.addParam("sort", "created")
.build();
2.3 、APT(注解处理器)方案
实现思路:
在编译时通过注解处理器生成接口实现类
less
// 1. 定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface GET {
String value();
}
// 2. 注解处理器生成实现类
public class ApiProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
for (Element element : env.getElementsAnnotatedWith(GET.class)) {
// 使用 JavaPoet 生成类似下面的代码
MethodSpec methodSpec = MethodSpec.methodBuilder("listRepos")
.addParameter(String.class, "user")
.returns(Call.class)
.addStatement("String url = BASE_URL + \"users/\" + user + \"/repos\"")
.addStatement("return new OkHttpCall<>(new Request.Builder().url(url).build())")
.build();
// 写入 Java 文件...
}
return true;
}
}
// 3. 生成的实现类
public class GitHubServiceImpl implements GitHubService {
@Override
public Call<List<Repo>> listRepos(String user) {
String url = "https://api.github.com/users/" + user + "/repos";
return new OkHttpCall<>(new Request.Builder().url(url).build());
}
}
// 4. 使用方式
GitHubService service = new GitHubServiceImpl();
Call<List<Repo>> call = service.listRepos("octocat");
问题: 那为什么Retrofit不用APT替代动态代理
理论是上可以的!
动态代理的价值 :Retrofit 的核心诉求是适配多变的应用场景(如调试模式切换、动态路由),运行时解析更符合这一目标
如下是更好的解释
2.4. APT 方案的挑战与局限
APT 更适用于生成固定逻辑的模板代码(如 ButterKnife)。
-
灵活性受限 :
动态代理可在运行时统一添加逻辑(如全局错误处理、日志拦截),而 APT 需为每个方法硬编码逻辑,复用性降低7。
-
注解组合复杂度 :
Retrofit 的注解(如
@Headers
+@QueryMap
)组合灵活,APT 需处理所有可能组合,生成代码复杂度高8。 -
动态行为支持弱 :
如动态 URL(
@Url
注解)或运行时条件请求,APT 难以在编译时完全预生成逻辑3。 -
要处理复杂注解 :像 Retrofit 的
@Path
、@Query
等注解的解析逻辑需要自己实现。
java
// 注解处理器
@AutoService(Processor.class)
public class RetrofitProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (Element element : roundEnv.getElementsAnnotatedWith(Service.class)) {
// 1. 解析接口
TypeElement typeElement = (TypeElement) element;
String className = typeElement.getSimpleName().toString() + "_Impl";
// 2. 生成Java类
JavaFileObject file = processingEnv.getFiler().createSourceFile(className);
Writer writer = file.openWriter();
// 3. 生成代码
writer.write("public class " + className + " implements " + typeElement + " {\n");
writer.write(" private final Retrofit retrofit;\n");
writer.write(" public " + className + "(Retrofit retrofit) {\n");
writer.write(" this.retrofit = retrofit;\n");
writer.write(" }\n");
// 4. 为每个方法生成实现
for (Element method : typeElement.getEnclosedElements()) {
if (method.getKind() == ElementKind.METHOD) {
ExecutableElement methodElement = (ExecutableElement) method;
// 解析方法注解并生成代码...
}
}
writer.write("}");
writer.close();
}
return true;
}
}
// 生成的实现类示例
public class GitHubService_Impl implements GitHubService {
private final Retrofit retrofit;
public GitHubService_Impl(Retrofit retrofit) {
this.retrofit = retrofit;
}
@Override
public Call<List<Repo>> listRepos(String user) {
// 自动生成的请求构建代码...
}
}
3. Retrofit的适配器模式解读?
无论使用 RxJava 还是协程适配器,Retrofit 适配器模式始终解决三个核心问题:
总结:适配器选择建议
- Kotlin 项目 → 首选 协程
suspend
函数(Retrofit 2.6.0+ 原生支持) - 响应式项目 → RxJava (Android) / Reactor (Spring)
- Java 项目 →
CompletableFuture
(Java 8+) 或 RxJava - 特殊需求 → 自定义适配器(如
Optional
、Result
封装)
4. Retrofit的设计模式有哪些?
4.1 Retrofit 设计模式总结表
设计模式 | 应用场景 | 关键实现点 | 优势 |
---|---|---|---|
动态代理模式 | 声明式 API 接口实现 | Proxy.newProxyInstance() 生成接口代理 |
免去手动实现接口逻辑 |
建造者模式 | 构建 Retrofit 复杂对象 | Retrofit.Builder() 链式配置参数 |
隔离构建逻辑,支持灵活配置 |
适配器模式 | 兼容不同异步处理机制 | CallAdapter 转换 Call 为 RxJava/协程等类型 |
解耦 HTTP 请求与异步处理方式 |
工厂模式 | 动态创建转换器/适配器 | Converter.Factory 创建 JSON/XML 解析器 |
扩展性强,支持自定义数据格式 |
外观模式 | 简化网络库调用复杂度 | Retrofit 类封装 OkHttp/解析/线程切换等底层逻辑 | 提供统一简洁的 API 入口 |
策略模式 | 动态切换数据解析策略 | 可配置多种 Converter.Factory (Gson/Moshi) |
灵活替换算法,满足不同需求 |
装饰器模式 | 增强网络请求功能 | OkHttp 拦截器链添加日志/缓存/重试逻辑 | 动态扩展功能,符合开闭原则 |
4.2 模式协作说明
-
入口 :用户通过动态代理定义 API 接口
-
配置 :建造者模式 组装
Retrofit
实例 -
扩展:
- 工厂模式 生成数据转换器 (
Converter
) - 适配器模式兼容异步框架 (RxJava/协程)
- 工厂模式 生成数据转换器 (
-
执行:
- 外观模式统一调用网络层 (OkHttp)
- 策略模式动态切换数据解析方式
-
增强 :装饰器模式通过拦截器添加额外功能
项目的地址: github.com/pengcaihua1...