Springboot整合Retrofit入门及源码分析
项目介绍
retrofit-spring-boot-starter
实现了Retrofit
与SpringBoot
框架快速整合,并且支持了部分功能增强,从而极大的简化spring-boot项目下http接口调用开发。
快速入门
- 引入依赖
<!--Retrofit依赖-->
<dependency>
<groupId>com.github.lianjiatech</groupId>
<artifactId>retrofit-spring-boot-starter</artifactId>
<version>2.3.10</version>
</dependency>
- 定义http接口,添加RetrofitClient
@RetrofitClient(baseUrl = "${remote.baseUrl}")
@Intercept(handler = TokenInterceptor.class)
public interface TestApi {
@GET("greet")
String greet();
}
- 添加拦截器
@Component
public class TokenInterceptor extends BasePathMatchInterceptor {
@Override
protected Response doIntercept(Chain chain) throws IOException {
Request request = chain.request();
System.out.println("intercept");
return chain.proceed(request);
}
}
- 注入使用
@SpringBootTest
public class RetrofitTest {
@Autowired
private TestApi testApi;
@Test
public void t1() {
System.out.println(testApi.greet());
}
}
源码分析
- 启动的核心是
AutoConfiguredRetrofitScannerRegistrar
。该类实现了ImportBeanDefinitionRegistrar
,往容器中注入类型是RetrofitFactoryBean的bean对象。
public void registerFilters() {
AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(RetrofitClient.class);
this.addIncludeFilter(annotationTypeFilter);
}
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
Iterator var3 = beanDefinitions.iterator();
while(var3.hasNext()) {
BeanDefinitionHolder holder = (BeanDefinitionHolder)var3.next();
GenericBeanDefinition definition = (GenericBeanDefinition)holder.getBeanDefinition();
if (log.isDebugEnabled()) {
log.debug("Creating RetrofitClientBean with name '" + holder.getBeanName() + "' and '" + definition.getBeanClassName() + "' Interface");
}
definition.getConstructorArgumentValues().addGenericArgumentValue(Objects.requireNonNull(definition.getBeanClassName()));
definition.setBeanClass(RetrofitFactoryBean.class);
}
}
- 调用请求,会获取对应的RetrofitClient,执行
RetrofitFactoryBean#getObject
。RetrofitFactoryBean#createRetrofit
该方法创建了Retrofit的对象,Retrofit#create
,根据传入的class对象生成代理。
public <T> T create(final Class<T> service) {
validateServiceInterface(service);
return (T)
Proxy.newProxyInstance(
service.getClassLoader(),
new Class<?>[] {service},
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override
public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}
ServiceMethod#parseAnnotations
根据Retrofit和调用的方法生成一个BodyCallAdapter对象,并调用adapt方法。也就是发送Http请求。
项目地址
- https://gitee.com/lianjiatech/retrofit-spring-boot-starter