森林源代码探索
Forest 是一个开源的 Java HTTP 客户端框架,它能够将 HTTP 的所有请求信息(包括 URL、Header 以及 Body 等信息)绑定到您自定义的 Interface 方法上,能够通过调用本地接口方法的方式发送 HTTP 请求。
本篇通过分析其源代码,列出了相关重要组件类,并最终通过一个流程图,分析其整个编码实现,以分享给大家。最主要这个工程源代码,通过引入大量设计模式(模板方法、工厂、代理、策略等),使得代码组织地相当美感,整洁,有助于提高你的阅读兴趣,因此写了这篇文章留念并分享给大家。
[toc]
一、相关介绍
1、为什么使用 Forest?
使用 Forest 就像使用类似 Dubbo 那样的 RPC 框架一样,只需要定义接口,调用接口即可,不必关心具体发送 HTTP 请求的细节。同时将 HTTP 请求信息与业务代码解耦,方便您统一管理大量 HTTP 的 URL、Header 等信息。而请求的调用方完全不必在意 HTTP 的具体内容,即使该 HTTP 请求信息发生变更,大多数情况也不需要修改调用发送请求的代码。
2、Forest 如何使用?
Forest 不需要您编写具体的 HTTP 调用过程,只需要您定义一个接口,然后通过 Forest 注解将 HTTP 请求的信息添加到接口的方法上即可。请求发送方通过调用您定义的接口便能自动发送请求和接受请求的响应。
3、Forest 的工作原理
Forest 会将您定义好的接口通过动态代理的方式生成一个具体的实现类,然后组织、验证 HTTP 请求信息,绑定动态数据,转换数据形式,SSL 验证签名,调用后端 HTTP API(httpclient 等 API)执行实际请求,等待响应,失败重试,转换响应数据到 Java 类型等脏活累活都由这动态代理的实现类给包了。 请求发送方调用这个接口时,实际上就是在调用这个干脏活累活的实现类。
4、Forest 的架构
5、官网地址
【官网地址】:forest.dtflyx.com/
【工程源码】:gitee.com/dromara/for…
二、源码分析
由于forest的源代码看起来挺多,但是工程模块划分的相关美感。从包的命名就可以看出来,每个类的职责。下面,主要列举一些重要的类,进而分析其作用。而这些类,构成了整个创建请求、请求组装、请求响应、响应解析等一些列功能。
1、ForestConnectionManager
该类负责通过
ForestConfiguration
获取相关配置参数,进而创建HttpClient
,它包含了两个实现类HttpclientConnectionManager
和OkHttp3ConnnectionManager
。
public interface ForestConnectionManager {
void init(ForestConfiguration configuration);
}
1.1、OkHttp3ConnectionManager
基于okhttp3实现http connection管理器
public void init(ForestConfiguration configuration) {
pool = new ConnectionPool();
}
该类实现了init方法,通过源码可以看出仅仅初始化了ConnectionPool
对象。
getClient
其中比较重要的方法
public OkHttpClient getClient(ForestRequest request, LifeCycleHandler lifeCycleHandler)
根据ForestRequest
和LifeCycleHandler
,通过OkHttpClient.Builder
建造者创建OkHttpClient
实例对象,方法内部初始化了实例的相关参数,包括设置HttpProxy
,以及处理是否支持HTTPS
协议。
1.2、HttpclientConnectionManager
基于apache httpclient 实现http connection管理器
该类实现了init方法,通过源码可以看出,通过ForestConfiguration
类传入的参数,初始化成员变量,成员变量包括如下
private static PoolingHttpClientConnectionManager tsConnectionManager;
private static PoolingNHttpClientConnectionManager asyncConnectionManager;
private static Lookup<AuthSchemeProvider> authSchemeRegistry;
比较重要的成员方法是
public HttpClient getHttpClient(ForestRequest request, CookieStore cookieStore)
,其中也提供了创建异步的CloseableHttpAsyncClient
成员方法。
2、HttpExecutor
通过
LifeCycleHandler
以及ConnectionManager
发起Http请求,请求类型包括POST
、POST
、PUT
、DELETE
等,接口包含两个重要的方法execute(LifeCycleHandler)
和close
,对于支持apache client
和okhttp3
,分别提供了对应的抽象类AbstractHttpclientExecutor
、AbstractOkHttp3Executor
。
2.1、AbstractHttpclientExecutor
基于
Apache HttpClient
实现Http
调用的执行器,该类继承了AbstractHttpExecutor
类,最核心的方法execute
。
该类包含三个重要的成员变量
protected final HttpclientResponseHandler httpclientResponseHandler;
protected String url;
protected final String typeName;
protected T httpRequest;
protected BodyBuilder<T> bodyBuilder;
protected CookieStore cookieStore;
以及父类AbstractHttpExecutor
类的成员变量
protected final ForestRequest request;
protected HttpclientRequestSender requestSender;
protected ForestResponse response;
该类核心方法
public void execute(int retryCount, LifeCycleHandler lifeCycleHandler)
源码分析
public void execute(int retryCount, LifeCycleHandler lifeCycleHandler) {
Date startDate = new Date();
ForestResponseFactory forestResponseFactory = new HttpclientForestResponseFactory();
try {
//这里实际委托给 HttpclientRequestSender#sendRequest 发送http请求
//本身内部通过判断 retryCount 然后进行充实操作,如果重试次数>=request.getRetryCount(),
//则调用httpRequest.abort()丢弃本次请求
requestSender.sendRequest(
request,
httpclientResponseHandler,
httpRequest,
lifeCycleHandler,
cookieStore,
startDate, 0);
} catch (IOException e) {
if (retryCount >= request.getRetryCount()) {
httpRequest.abort();
response = forestResponseFactory.createResponse(request, null, lifeCycleHandler, e, startDate);
lifeCycleHandler.handleSyncWithException(request, response, e);
return;
}
log.error(e.getMessage());
} catch (ForestRuntimeException e) {
httpRequest.abort();
throw e;
}
}
2.1.1、HttpclientRequestSender
该类包含两个重要的成员变量HttpclientConnectionManager
和ForestRequest
protected final HttpclientConnectionManager connectionManager;
protected final ForestRequest request;
public AbstractHttpclientRequestSender(HttpclientConnectionManager connectionManager, ForestRequest request) {
this.connectionManager = connectionManager;
this.request = request;
}
从上述代码可以看出,对于 Apache Http Client
,HttpExecutor -> RequestSender -> ConnectionManager
。
HttpclientRequestSender 接口仅仅只包含一个方法sendRequest
,两个抽象类AsyncHttpclientRequestSender
和SyncHttpclientRequestSender
分别基于异步或者同步处理方式实现了该方法。
public interface HttpclientRequestSender {
void sendRequest(ForestRequest request,
HttpclientResponseHandler responseHandler,
HttpUriRequest httpRequest,
LifeCycleHandler lifeCycleHandler,
CookieStore cookieStore,
Date startDate,
int retryCount) throws IOException;
}
2.1.2、AsyncHttpclientRequestSender
基于异步处理的HttpClient请求发送
public void sendRequest(
final ForestRequest request, final HttpclientResponseHandler responseHandler,
final HttpUriRequest httpRequest, LifeCycleHandler lifeCycleHandler,
CookieStore cookieStore, Date startDate, int retryCount) {
//1、从connectionManager.getHttpAsyncClient获取client对象,然后调用client.start()
final CloseableHttpAsyncClient client = connectionManager.getHttpAsyncClient(request);
client.start();
//2、调用logRequest方法记录请求日志
final ForestResponseFactory forestResponseFactory = new HttpclientForestResponseFactory();
logRequest(retryCount, (HttpRequestBase) httpRequest);
//3、调用client.execute发起请求,并设置回调函数,completed、failed、cancelled 的相关业务处理
final Future<HttpResponse> future = client.execute(httpRequest, new FutureCallback<HttpResponse>() {
@Override
public void completed(final HttpResponse httpResponse) {
ForestResponse response = forestResponseFactory.createResponse(request, httpResponse, lifeCycleHandler, null, startDate);
if (response.isError()) {
ForestNetworkException networkException =
new ForestNetworkException("", response.getStatusCode(), response);
ForestRetryException retryException = new ForestRetryException(
networkException, request, request.getRetryCount(), retryCount);
try {
request.getRetryer().canRetry(retryException);
} catch (Throwable throwable) {
responseHandler.handleError(response);
return;
}
//3.1、如果响应错误,根据request.getRetryer().canRetry判断是否可以发起重试,然后递归调用sendRequest
sendRequest(request, responseHandler, httpRequest, lifeCycleHandler, cookieStore, startDate, retryCount + 1);
return;
}
//3.2、通过lifeCycleHandler.handleSaveCookie处理cookie,
// 然后调用responseHandler.handleSuccess处理响应结果。
ForestCookies cookies = getCookiesFromHttpCookieStore(cookieStore);
lifeCycleHandler.handleSaveCookie(request, cookies);
responseHandler.handleSuccess(response);
}
@Override
public void failed(final Exception ex) {
ForestResponse response = forestResponseFactory.createResponse(request, null, lifeCycleHandler, ex, startDate);
ForestRetryException retryException = new ForestRetryException(
ex, request, request.getRetryCount(), retryCount);
try {
request.getRetryer().canRetry(retryException);
} catch (Throwable throwable) {
responseHandler.handleError(response, ex);
return;
}
//3.3、如果请求发送失败,根据request.getRetryer().canRetry判断是否可以发起重试,然后递归调用sendRequest
sendRequest(request, responseHandler, httpRequest, lifeCycleHandler, cookieStore, startDate, retryCount + 1);
}
@Override
public void cancelled() {
}
});
//4、委托给 responseHandler.handleFuture 处理响应结果
responseHandler.handleFuture(future, startDate, forestResponseFactory);
}
2.1.3、SyncHttpclientRequestSender
基于同步处理的HttpClient请求发送
public void sendRequest(
ForestRequest request, HttpclientResponseHandler responseHandler,
HttpUriRequest httpRequest, LifeCycleHandler lifeCycleHandler,
CookieStore cookieStore, Date startDate, int retryCount)
throws IOException {
HttpResponse httpResponse = null;
ForestResponse response = null;
client = getHttpClient(cookieStore);
ForestResponseFactory forestResponseFactory = new HttpclientForestResponseFactory();
try {
logRequest(retryCount, (HttpRequestBase) httpRequest);
httpResponse = client.execute(httpRequest);
response = forestResponseFactory.createResponse(request, httpResponse, lifeCycleHandler, null, startDate);
} catch (IOException e) {
httpRequest.abort();
ForestRetryException retryException = new ForestRetryException(
e, request, request.getRetryCount(), retryCount);
try {
request.getRetryer().canRetry(retryException);
} catch (Throwable throwable) {
response = forestResponseFactory.createResponse(request, httpResponse, lifeCycleHandler, throwable, startDate);
lifeCycleHandler.handleSyncWithException(request, response, e);
return;
}
response = forestResponseFactory.createResponse(request, httpResponse, lifeCycleHandler, null, startDate);
logResponse(response);
sendRequest(request, responseHandler, httpRequest, lifeCycleHandler, cookieStore, startDate, retryCount + 1);
return;
} finally {
connectionManager.afterConnect();
if (response == null) {
response = forestResponseFactory.createResponse(request, httpResponse, lifeCycleHandler, null, startDate);
}
logResponse(response);
}
if (response.isError()) {
ForestNetworkException networkException =
new ForestNetworkException("", response.getStatusCode(), response);
ForestRetryException retryException = new ForestRetryException(
networkException, request, request.getRetryCount(), retryCount);
try {
request.getRetryer().canRetry(retryException);
} catch (Throwable throwable) {
responseHandler.handleSync(httpResponse, response);
return;
}
sendRequest(request, responseHandler, httpRequest, lifeCycleHandler, cookieStore, startDate, retryCount + 1);
return;
}
try {
lifeCycleHandler.handleSaveCookie(request, getCookiesFromHttpCookieStore(cookieStore));
responseHandler.handleSync(httpResponse, response);
} catch (Exception ex) {
if (ex instanceof ForestRuntimeException) {
throw ex;
}
else {
throw new ForestRuntimeException(ex);
}
}
}
2.2、AbstractOkHttp3Executor
基于
OkHttp3
实现Http
调用的执行器,该类实现了HttpExecutor
接口,最核心的方法execute
。
该类包含三个重要的成员变量
protected final ForestRequest request;
private final OkHttp3ConnectionManager connectionManager;
private final OkHttp3ResponseHandler okHttp3ResponseHandler;
该类默认构造方法
protected AbstractOkHttp3Executor(ForestRequest request, OkHttp3ConnectionManager connectionManager, OkHttp3ResponseHandler okHttp3ResponseHandler) {
this.request = request;
this.connectionManager = connectionManager;
this.okHttp3ResponseHandler = okHttp3ResponseHandler;
}
该类核心方法
public void execute(final LifeCycleHandler lifeCycleHandler, int retryCount)
源码分析
public void execute(final LifeCycleHandler lifeCycleHandler, int retryCount) {
//1、通过getClient方法创建 OkHttpClient 实例对象
OkHttpClient okHttpClient = getClient(request, lifeCycleHandler);
URLBuilder urlBuilder = getURLBuilder();
String url = urlBuilder.buildUrl(request);
//2、构建 Request.Builder 实例对象,并调用prepareX相关方法进行相关初始化
Request.Builder builder = new Request.Builder().url(url);
prepareMethod(builder);
prepareHeaders(builder);
prepareBody(builder, lifeCycleHandler);
//3、构建 Request 实例对象
final Request okRequest = builder.build();
Call call = okHttpClient.newCall(okRequest);
//4、构建 OkHttp3ForestResponseFactory 实例对象,并调用 logRequest 方法记录请求request对象相关日志
final OkHttp3ForestResponseFactory factory = new OkHttp3ForestResponseFactory();
logRequest(retryCount, okRequest, okHttpClient);
Date startDate = new Date();
long startTime = startDate.getTime();
//5、判断request是否异步请求类型,然后执行不同策略
if (request.isAsync()) {
final OkHttp3ResponseFuture future = new OkHttp3ResponseFuture();
//5.1、调用Call的 enqueue方法,内部设置回调函数处理 onFailure 和 onResponse
// 在 onFailure 如果不做异常,则记录ForestResponse日志同步,递归调用 execute 本方法进行重试操作。
// 在 onResponse 方法中,调用 logResponse 记录响应日志,同时判断ForestResponse#isSuccess 方法是否成功
// ,否则 retryOrDoError 执行该方法进行重试,最终委托给 okHttp3ResponseHandler#handleFuture处理结果
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
ForestRetryException retryException = new ForestRetryException(
e, request, request.getRetryCount(), retryCount);
try {
request.getRetryer().canRetry(retryException);
} catch (Throwable throwable) {
future.failed(e);
ForestResponse response = factory.createResponse(request, null, lifeCycleHandler, throwable, startDate);
logResponse(response);
lifeCycleHandler.handleError(request, response, e);
return;
}
execute(lifeCycleHandler, retryCount + 1);
}
@Override
public void onResponse(Call call, Response okResponse) throws IOException {
ForestResponse response = factory.createResponse(request, okResponse, lifeCycleHandler, null, startDate);
logResponse(response);
Object result = null;
if (response.isSuccess()) {
if (request.getOnSuccess() != null) {
result = okHttp3ResponseHandler.handleSuccess(response);
}
else {
result = okHttp3ResponseHandler.handleSync(okResponse, response);
}
future.completed(result);
} else {
retryOrDoError(response, okResponse, future, lifeCycleHandler, retryCount, startTime);
}
}
});
okHttp3ResponseHandler.handleFuture(future, startDate, factory);
}
//5.2、通过call#execute()方法执行处理,如果捕捉异常,同样递归重试操作
else {
Response okResponse = null;
ForestResponse response = null;
try {
okResponse = call.execute();
} catch (IOException e) {
ForestRetryException retryException = new ForestRetryException(
e, request, request.getRetryCount(), retryCount);
try {
request.getRetryer().canRetry(retryException);
} catch (Throwable throwable) {
response = factory.createResponse(request, null, lifeCycleHandler, e, startDate);
logResponse(response);
lifeCycleHandler.handleSyncWithException(request, response, e);
return;
}
response = factory.createResponse(request, null, lifeCycleHandler, e, startDate);
logResponse(response);
execute(lifeCycleHandler, retryCount + 1);
return;
} finally {
if (response == null) {
response = factory.createResponse(request, okResponse, lifeCycleHandler, null, startDate);
}
logResponse(response);
}
if (response.isError()) {
retryOrDoError(response, okResponse, null, lifeCycleHandler, retryCount, startTime);
return;
}
okHttp3ResponseHandler.handleSync(okResponse, response);
}
}
3、HttpBackend
该类包括一个抽象类
AbstractHttpBackend
,并最终有两个实现类HttpclientBackend
和OkHttp3Backend
。
public interface HttpBackend {
String getName();
HttpExecutor createExecutor(ForestRequest request, LifeCycleHandler lifeCycleHandler);
void init(ForestConfiguration configuration);
interface HttpExecutorCreator {
HttpExecutor createExecutor(ForestConnectionManager connectionManager, ForestRequest request, LifeCycleHandler lifeCycleHandler);
}
}
3.1、AbstractHttpBackend
该类包括两个实现类
HttpclientBackend
和OkHttp3Backend
,通过对外暴露createExecutor
方法,以根据ForestRequest
和LifeCycleHandler
,创建request请求,进而根据请求方式类型,通过从executorCreatorMap
中根据请求类型,查找对应的HttpExecutor
执行发送HTTP请求以及处理响应结果。
该类包含两个重要的成员变量
private volatile boolean initialized = false;
private final Map<ForestRequestType, HttpExecutorCreator> executorCreatorMap = new HashMap<>();
private final ForestConnectionManager connectionManager;
public AbstractHttpBackend(ForestConnectionManager connectionManager) {
this.connectionManager = connectionManager;
}
核心方法createExecutor()
根据ForestRequest获取type,然后从executorCreatorMap获取对应HttpExecutorCreator,进而调用httpExecutorCreator.createExecutor。
public HttpExecutor createExecutor(ForestRequest request, LifeCycleHandler lifeCycleHandler) {
ForestRequestType type = request.getType();
HttpExecutorCreator httpExecutorCreator = executorCreatorMap.get(type);
if (httpExecutorCreator == null) {
throw new ForestRuntimeException("Http request type \"" + type.getName() + "\" is not be supported.");
}
HttpExecutor executor = httpExecutorCreator.createExecutor(connectionManager, request, lifeCycleHandler);
return executor;
}
3.2、HttpclientBackend
httpclient的请求后端,实现
AbstractHttpBackend
抽象类的一系列抽象方法,方法内部创建不通请求类型OkHttpXXXExecutor实例。
3.3、OkHttp3Backend
okhttp的请求后端,实现
AbstractHttpBackend
抽象类的一系列抽象方法,方法内部创建不通请求类型OkHttpXXXExecutor实例。
4、HttpBackendSelector
该类的主要职责,通过对外暴露select方法,我们通常全局会通过
forest.backend
来指定选择okhttp3
或者httpclient
,所以该类的主要作用就是根据ForestConfiguration
通过反射创建支持okhttp3
或者httpclient
的HttpBackend
实例。
static {
BACKEND_MAP.put(HTTPCLIENT_BACKEND_NAME, HTTPCLIENT_BACKEND_CREATOR);
BACKEND_MAP.put(OKHTTP3_BACKEND_NAME, OKHTTP3_BACKEND_CREATOR);
}
public HttpBackend select(ForestConfiguration configuration) {
String name = configuration.getBackendName();
if (StringUtils.isNotEmpty(name)) {
HttpBackendCreator backendCreator = BACKEND_MAP.get(name);
if (backendCreator == null) {
throw new ForestRuntimeException("Http setBackend \"" + name + "\" can not be found.");
}
return backendCreator.create();
}
HttpBackend backend = null;
backend = findOkHttp3BackendInstance();
if (backend != null) {
return backend;
}
backend = findHttpclientBackendInstance();
if (backend != null) {
return backend;
}
throw new ForestRuntimeException("Http Backed is undefined.");
}
HttpBackendCreator
通过类路径反射创建实例
static class HttpBackendCreator {
public String className;
public HttpBackendCreator(String className) {
this.className = className;
}
public HttpBackend create() {
try {
Class klass = Class.forName(className);
return (HttpBackend) klass.newInstance();
} catch (ClassNotFoundException e) {
throw new ForestRuntimeException(e);
} catch (InstantiationException e) {
throw new ForestRuntimeException(e);
} catch (IllegalAccessException e) {
throw new ForestRuntimeException(e);
}
}
}
5、ForestConfiguration
该类的主要职责类似一个上线文对象,通过装载forest相关配置信息,同时也是相关各个组件的数据传输纽带。
configuration()
该方法用于初始化配置
/**
* 实例化ForestConfiguration对象,并初始化默认值
* @return 新创建的ForestConfiguration实例
*/
public static ForestConfiguration configuration() {
ForestConfiguration configuration = new ForestConfiguration();
configuration.setId("forestConfiguration" + configuration.hashCode());
configuration.setJsonConverterSelector(new JSONConverterSelector());
configuration.setXmlConverter(new ForestJaxbConverter());
configuration.setTextConverter();
configuration.getConverterMap().put(ForestDataType.AUTO, new DefaultAutoConverter(configuration));
configuration.getConverterMap().put(ForestDataType.BINARY, new DefaultBinaryConverter());
setupJSONConverter(configuration);
configuration.setTimeout(3000);
configuration.setConnectTimeout(2000);
configuration.setMaxConnections(500);
configuration.setMaxRouteConnections(500);
configuration.setRetryer(BackOffRetryer.class);
configuration.setRetryCount(0);
configuration.setMaxRetryInterval(0);
// configuration.setSslProtocol(SSLUtils.TLS_1_2);
configuration.registerFilter("json", JSONFilter.class);
configuration.registerFilter("xml", XmlFilter.class);
configuration.setLogHandler(new DefaultLogHandler());
RequestBodyBuilder.registerBodyBuilder(CharSequence.class, new RequestBodyBuilder.StringRequestBodyBuilder());
RequestBodyBuilder.registerBodyBuilder(String.class, new RequestBodyBuilder.StringRequestBodyBuilder());
RequestBodyBuilder.registerBodyBuilder(File.class, new RequestBodyBuilder.FileRequestBodyBuilder());
RequestBodyBuilder.registerBodyBuilder(byte[].class, new RequestBodyBuilder.ByteArrayRequestBodyBuilder());
RequestBodyBuilder.registerBodyBuilder(InputStream.class, new RequestBodyBuilder.InputStreamBodyBuilder());
RequestBodyBuilder.registerBodyBuilder(Object.class, new RequestBodyBuilder.ObjectRequestBodyBuilder());
return configuration;
}
createInstance()
该方法用于动态代理实例创建
/**
* 创建请求接口的动态代理实例
* @param clazz 请求接口类
* @param <T> 请求接口类泛型
* @return 动态代理实例
*/
public <T> T createInstance(Class<T> clazz) {
ProxyFactory<T> proxyFactory = getProxyFactory(clazz);
return proxyFactory.createInstance();
}
6、ProxyFactory
接口代理工工厂类
核心代码如下
/**
* @author gongjun[dt_flys@hotmail.com]
* @since 2016-03-25 18:17
*/
public class ProxyFactory<T> {
private ForestConfiguration configuration;
private Class<T> interfaceClass;
public ProxyFactory(ForestConfiguration configuration, Class<T> interfaceClass) {
this.configuration = configuration;
this.interfaceClass = interfaceClass;
}
public Class<T> getInterfaceClass() {
return interfaceClass;
}
public void setInterfaceClass(Class<T> interfaceClass) {
this.interfaceClass = interfaceClass;
}
public T createInstance() {
T instance = (T) configuration.getInstanceCache().get(interfaceClass);
boolean cacheEnabled = configuration.isCacheEnabled();
if (cacheEnabled && instance != null) {
return instance;
}
synchronized (configuration.getInstanceCache()) {
instance = (T) configuration.getInstanceCache().get(interfaceClass);
if (cacheEnabled && instance != null) {
return instance;
}
InterfaceProxyHandler<T> interfaceProxyHandler = new InterfaceProxyHandler<T>(configuration, this, interfaceClass);
instance = (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{interfaceClass, ForestClientProxy.class}, interfaceProxyHandler);
if (cacheEnabled) {
configuration.getInstanceCache().put(interfaceClass, instance);
}
return instance;
}
}
}
7、InterfaceProxyHandler
接口代理工工厂类
构造函数
在构造函数中,我们可以看到同时调用了两个成员方法prepareBaseInfo()和initMethods()
public InterfaceProxyHandler(ForestConfiguration configuration, ProxyFactory proxyFactory, Class<T> interfaceClass) {
this.configuration = configuration;
this.proxyFactory = proxyFactory;
this.interfaceClass = interfaceClass;
this.interceptorFactory = configuration.getInterceptorFactory();
try {
defaultMethodConstructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class);
if (!defaultMethodConstructor.isAccessible()) {
defaultMethodConstructor.setAccessible(true);
}
defaultMethodLookup = defaultMethodConstructor.newInstance(interfaceClass, MethodHandles.Lookup.PRIVATE);
} catch (Throwable e) {
throw new ForestRuntimeException(e);
}
prepareBaseInfo();
initMethods();
}
prepareBaseInfo方法
private void prepareBaseInfo() {
Annotation[] annotations = interfaceClass.getAnnotations();
for (int i = 0; i < annotations.length; i++) {
Annotation annotation = annotations[i];
if (annotation instanceof BaseURL) {
BaseURL baseURLAnn = (BaseURL) annotation;
String value = baseURLAnn.value();
if (value == null || value.trim().length() == 0) {
continue;
}
baseURL = value.trim();
baseMetaRequest.setUrl(baseURL);
} else {
BaseLifeCycle baseLifeCycle = annotation.annotationType().getAnnotation(BaseLifeCycle.class);
MethodLifeCycle methodLifeCycle = annotation.annotationType().getAnnotation(MethodLifeCycle.class);
if (baseLifeCycle != null || methodLifeCycle != null) {
if (baseLifeCycle != null) {
Class<? extends BaseAnnotationLifeCycle> interceptorClass = baseLifeCycle.value();
if (interceptorClass != null) {
BaseAnnotationLifeCycle baseInterceptor = interceptorFactory.getInterceptor(interceptorClass);
baseInterceptor.onProxyHandlerInitialized(this, annotation);
}
}
baseAnnotations.add(annotation);
}
}
}
}
initMethods方法
扫描接口类的接口方法,然后创建ForestMethod实例,并添加到forestMethodMap中,以供其成员方法invoke供外部调用使用。
private void initMethods() {
Method[] methods = interfaceClass.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
if(method.isDefault()){
continue;
}
ForestMethod forestMethod = new ForestMethod(this, configuration, method);
forestMethodMap.put(method, forestMethod);
}
}
invoke方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
if (method.isDefault()) {
return invokeDefaultMethod(proxy, method, args);
}
if ("toString".equals(methodName) && (args == null || args.length == 0)) {
return "{Forest Proxy Object of " + interfaceClass.getName() + "}";
}
if ("equals".equals(methodName) && (args != null && args.length == 1)) {
Object obj = args[0];
if (Proxy.isProxyClass(obj.getClass())) {
InvocationHandler h1 = Proxy.getInvocationHandler(proxy);
InvocationHandler h2 = Proxy.getInvocationHandler(obj);
return h1.equals(h2);
}
return false;
}
//根据请求的接口方法,然后从forestMethodMap中查找ForestMethod实例对象,这里的forestMethodMap实际在构造函数中,通过扫描接口的接口方法然后初始化
ForestMethod forestMethod = forestMethodMap.get(method);
return forestMethod.invoke(args);
}
8、ForestMethod
通过代理调用的实际执行的方法对象
/**
* 调用方法
* @param args 调用本对象对应方法时传入的参数数组
* @return 调用本对象对应方法结束后返回的值,任意类型的对象实例
*/
public Object invoke(Object[] args) {
ForestRequest request = makeRequest(args);
MethodLifeCycleHandler<T> lifeCycleHandler = new MethodLifeCycleHandler<>(
this, onSuccessClassGenericType);
request.setBackend(configuration.getBackend())
.setLifeCycleHandler(lifeCycleHandler);
lifeCycleHandler.handleInvokeMethod(request, this, args);
// 如果返回类型为ForestRequest,直接返回请求对象
if (ForestRequest.class.isAssignableFrom(returnClass)) {
Type retType = getReturnType();
if (retType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) retType;
Type[] genTypes = parameterizedType.getActualTypeArguments();
if (genTypes.length > 0) {
Type targetType = genTypes[0];
returnClass = ReflectUtils.getClassByType(targetType);
returnType = targetType;
} else {
returnClass = String.class;
returnType = String.class;
}
}
return request;
}
return request.execute();
}
9、ForestRequest
Forest请求对象
/**
* 执行请求发送过程
*
* @param backend HTTP后端,{@link HttpBackend}接口
上一篇: CSS 图片廊
下一篇: 在 Python 中使用请求模块
推荐阅读
-
C# 委托探索猫和老鼠
-
R 语言实现,用于评估随机森林模型和重要预测变量的重要性
-
2024 Python 中最完整的 python,让童年成为回忆【猫和老鼠的游戏】(附源代码+详细解析
-
用 python 制作童年回忆 [猫捉老鼠游戏](含源代码 + 详细分析)
-
容器与服务:metrics-server 安装探索
-
[蛇的 C 语言实现](附源代码)
-
????WebRTC 原理探索] 了解 WebRTC 的第一步。
-
基于 matlab 的 [5G 通信] 5G 通信新多载波技术 GFDM [含 Matlab 源代码 106 个问题] - I. 引言
-
Go 语言在云计算中的应用与探索
-
美国*最受欢迎的五个开放源代码项目!