一个简单的Retrofit实现(注解+动态代理)

项目整体结构

项目整体结构

自定义WeatherApi类

package com.example.lsn_compose.BarryLRetrofit.api;

import com.example.lsn_compose.BarryLRetrofit.retrofit.annotation.Field;
import com.example.lsn_compose.BarryLRetrofit.retrofit.annotation.GET;
import com.example.lsn_compose.BarryLRetrofit.retrofit.annotation.POST;
import com.example.lsn_compose.BarryLRetrofit.retrofit.annotation.Query;


import okhttp3.Call;
import retrofit2.http.FormUrlEncoded;

public interface BarryLWeatherApi {
    @POST("/v3/weather/weatherInfo")
    @FormUrlEncoded
    Call postWeather(@Field("city") String city, @Field("key") String key);

    @GET("/v3/weather/weatherInfo")
   Call getWeather(@Query("city") String city, @Query("key") String key);
}

注解部分

@Target(PARAMETER)//参数注解
@Retention(RUNTIME)//运行时注解,只有用运行时注解才能反射获取
public @interface Field {

    String value();
}
package com.example.lsn_compose.BarryLRetrofit.retrofit.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target(METHOD)
@Retention(RUNTIME)
public @interface GET {

    String value() default "";
}
package com.example.lsn_compose.BarryLRetrofit.retrofit.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;


import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target(METHOD)
@Retention(RUNTIME)
public @interface POST {

    String value() default "";
}
package com.example.lsn_compose.BarryLRetrofit.retrofit.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Query {

    String value();
}

自定义Retrofit类

package com.example.lsn_compose.BarryLRetrofit.retrofit;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import okhttp3.Call;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;

/**
 * @author BoyuanLiu
 * @date 2021年04月27日 12:19
 */
public class BarryLRetrofit {

    final Map<Method, ServiceMethod> serviceMethodCache = new ConcurrentHashMap<>();
    final Call.Factory callFactory;
    final HttpUrl baseUrl;

    BarryLRetrofit(Call.Factory callFactory, HttpUrl baseUrl) {
        this.callFactory = callFactory;
        this.baseUrl = baseUrl;
    }

    public <T> T create(final Class<T> service) {
        //动态代理+反射
        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service}, new InvocationHandler() {
            @Override
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                //解析这个method上所有的注解信息
                ServiceMethod serviceMethod = loadServiceMethod(method);
               //反射
                return serviceMethod.invoke(objects);
            }
        });
    }

    private ServiceMethod loadServiceMethod(Method method) {
        //先不上锁,避免synchronized的性能损失
        ServiceMethod result = serviceMethodCache.get(method);
        if (result != null) return result;
        //多线程下,避免重复解析,
        synchronized (serviceMethodCache) {
            result = serviceMethodCache.get(method);
            if (result == null) {
                result = new ServiceMethod.Builder(this, method).build();
                serviceMethodCache.put(method, result);
            }
        }
        return result;
    }


    /**
     * 构建者模式,将一个复杂对象的构建和它的表示分离,可以使使用者不必知道内部组成的细节。
     */
    public static final class Builder {
        private HttpUrl baseUrl;

        private okhttp3.Call.Factory callFactory;


        public Builder callFactory(okhttp3.Call.Factory factory) {
            this.callFactory = factory;
            return this;
        }

        public Builder baseUrl(String baseUrl) {
            this.baseUrl = HttpUrl.get(baseUrl);
            return this;
        }

        public BarryLRetrofit build() {
            if (baseUrl == null) {
                throw new IllegalStateException("Base URL required.");
            }
            okhttp3.Call.Factory callFactory = this.callFactory;
            if (callFactory == null) {
                callFactory = new OkHttpClient();
            }

            return new BarryLRetrofit(callFactory, baseUrl);
        }
    }

}

参数传递类,一个用于拼接注解上得到的key-value的handler,是一个抽象类

package com.example.lsn_compose.BarryLRetrofit.retrofit;

/**
 * @author BoyuanLiu
 * @date 2021年04月27日 12:19
 */
public abstract class ParameterHandler {

    abstract void apply(ServiceMethod serviceMethod, String value);

    static class QueryParameterHandler extends ParameterHandler {

        String key;

        public QueryParameterHandler(String key) {
            this.key = key;
        }

        @Override
        void apply(ServiceMethod serviceMethod, String value) {
            serviceMethod.addQueryParameter(key, value);
        }
    }

    static class FieldParameterHandler extends ParameterHandler {

        String key;

        public FieldParameterHandler(String key) {
            this.key = key;
        }


        @Override
        void apply(ServiceMethod serviceMethod, String value) {
            serviceMethod.addFiledParameter(key, value);
        }
    }
}

ServiceMethod类

package com.example.lsn_compose.BarryLRetrofit.retrofit;

import com.example.lsn_compose.BarryLRetrofit.retrofit.annotation.Field;
import com.example.lsn_compose.BarryLRetrofit.retrofit.annotation.GET;
import com.example.lsn_compose.BarryLRetrofit.retrofit.annotation.POST;
import com.example.lsn_compose.BarryLRetrofit.retrofit.annotation.Query;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import okhttp3.Call;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.Request;

/**
 * @author BoyuanLiu
 * @date 2021年04月27日 12:20
 */
public class ServiceMethod {
	//网络请求工厂  即okhttp的网络请求
    private final Call.Factory callFactory;
    //网络请求的相对地址 和baseUrl拼接起来就是实际地址
    private final String relativeUrl;
    private final boolean hasBody;
    //方法参数的处理器 比如我们定义的方法,get方法和后面的参数"city"、"key"
    private final ParameterHandler[] parameterHandler;
    //表单提交方式的表单体
    private FormBody.Builder formBuild;
    //网络基地址
    HttpUrl baseUrl;
    //网络请求的http方法 POST GET
    String httpMethod;
    HttpUrl.Builder urlBuilder;

    public ServiceMethod(Builder builder) {
        baseUrl = builder.barryLRetrofit.baseUrl;
        callFactory = builder.barryLRetrofit.callFactory;

        httpMethod = builder.httpMethod;
        relativeUrl = builder.relativeUrl;
        hasBody = builder.hasBody;
        parameterHandler = builder.parameterHandler;

        //如果是有请求体,创建一个okhttp的请求体对象
        if (hasBody) {
            formBuild = new FormBody.Builder();
        }
    }

    public Object invoke(Object[] args) {

        //1.处理请求的地址与参数
        for (int i = 0; i < parameterHandler.length; i++) {
            ParameterHandler handlers = parameterHandler[i];
            //handler内本来就记录了key,现在给到对应的value
            handlers.apply(this, args[i].toString());
        }
        //获取最终请求地址
        HttpUrl url;
        if (urlBuilder == null) {
            urlBuilder = baseUrl.newBuilder(relativeUrl);
        }
        url = urlBuilder.build();

        //请求体
        FormBody formBody = null;
        if (formBuild != null) {
            formBody = formBuild.build();
        }

        Request request = new Request.Builder().url(url).method(httpMethod, formBody).build();
        return callFactory.newCall(request);
    }

    //Post   把k-v 放到 请求体中
    public void addFiledParameter(String key, String value) {
        formBuild.add(key, value);
    }

    // get请求,  把 k-v 拼到url里面
    public void addQueryParameter(String key, String value) {
        if (urlBuilder == null) {
            urlBuilder = baseUrl.newBuilder(relativeUrl);
        }
        urlBuilder.addQueryParameter(key, value);
    }


    public static class Builder {

        private final BarryLRetrofit barryLRetrofit;
        private final Annotation[] methodAnnotations;
        private final Annotation[][] parameterAnnotations;
        ParameterHandler[] parameterHandler;
        private String httpMethod;
        private String relativeUrl;
        private boolean hasBody;

        public Builder(BarryLRetrofit barryLRetrofit, Method method) {
            this.barryLRetrofit = barryLRetrofit;
            //获取方法上的所有的注解
            methodAnnotations = method.getAnnotations();
            //获得方法参数的所有的注解 (一个参数可以有多个注解,一个方法又会有多个参数)
            parameterAnnotations = method.getParameterAnnotations();
        }

        public ServiceMethod build() {


            //1.解析方法上的注解, 只处理POST与GET

            for (Annotation methodAnnotation : methodAnnotations) {
                if (methodAnnotation instanceof POST) {
                    //记录当前请求方式
                    this.httpMethod = "POST";
                    //记录请求url的path
                    this.relativeUrl = ((POST) methodAnnotation).value();
                    // 是否有请求体
                    this.hasBody = true;
                } else if (methodAnnotation instanceof GET) {
                    this.httpMethod = "GET";
                    this.relativeUrl = ((GET) methodAnnotation).value();
                    this.hasBody = false;
                }
            }


            //2. 解析方法参数的注解
            int length = parameterAnnotations.length;
            parameterHandler = new ParameterHandler[length];
            for (int i = 0; i < length; i++) {
                // 一个参数上的所有的注解
                Annotation[] annotations = parameterAnnotations[i];
                // 处理参数上的每一个注解
                for (Annotation annotation : annotations) {
                    if (annotation instanceof Field) {
                        //得到注解上的value: 请求参数的key
                        String value = ((Field) annotation).value();
                        parameterHandler[i] = new ParameterHandler.FieldParameterHandler(value);
                    } else if (annotation instanceof Query) {
                        String value = ((Query) annotation).value();
                        parameterHandler[i] = new ParameterHandler.QueryParameterHandler(value);

                    }
                }
            }

            return new ServiceMethod(this);
        }
    }
}

调用

 BarryLRetrofit barryLRetrofit = new BarryLRetrofit.Builder().baseUrl("https://restapi.amap.com").build();
        barryLWeatherApi = barryLRetrofit.create(BarryLWeatherApi.class);
        barryGet();
        barryPost();

        public void barryGet() {
        Call call = barryLWeatherApi.getWeather("110101", "ae6c53e2186f33bbf240a12d80672d1b");
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

                Log.i(tag, "GET" + response.body().string());
                response.close();
            }
        });
    }

    public void barryPost() {
        Call call = barryLWeatherApi.postWeather("110101", "ae6c53e2186f33bbf240a12d80672d1b");
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

                Log.i(tag, "POST" + response.body().string());
                response.close();
            }
        });
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值