Retrofit 의 디자인 모델 - 동적 에이전트 모델

6701 단어
Retrofit 의 동적 에이전트 모드
최근 에 시간 이 나 서 소스 코드 의 리듬 을 보기 시 작 했 습 니 다. Retrofit 소스 코드 를 보면 동적 에이전트 모델 을 볼 수 있 습 니 다. 그러나 엄 밀 히 말 하면 진정한 동적 에이전트 모델 이 아니 라 이것 이 야 말로 진정한 큰 소의 코드 이 고 임기응변 하 며 고정 모델 의 영향 을 받 지 않 습 니 다.
1. 정규 동적 에이전트 모델
 /**
* Description:    
*/
public interface RetrofitInterface {
   String retrofitInterfaceFunc(String s);
}
/**
 * Description:    
 */
public class Retrofit implements RetrofitInterface {
    @Override
    public String retrofitInterfaceFunc(String s) {
        System.out.printf("progress " + s + "
"); return s; } }
/**
 * Description:    
 */
public class RetrofitProxy {
    private Retrofit retrofit;

    public RetrofitProxy(Retrofit retrofit) {
        this.retrofit = retrofit;
    }

    public  T create(Class service){
        if (!service.isInterface()){
            throw new IllegalArgumentException("API declarations must be interfaces. ");
        }
        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service},
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("before
"); method.invoke(retrofit, args); // System.out.printf("function name: " + method.getName() + "
"); // System.out.printf("function return type: " + method.getReturnType().getName() + "
"); // System.out.printf("args name: " + args[0].toString() + "
"); System.out.printf("after
"); return null; } }); } }
/**
 * Description:   
 */

public class TestMain {
    public static void main(String[] args) {
        RetrofitProxy proxy = new RetrofitProxy(new Retrofit());
        RetrofitInterface retrofitInterface =  proxy.create(RetrofitInterface.class);
        retrofitInterface.retrofitInterfaceFunc("12345");
    }
}

인쇄 결 과 는 다음 과 같 습 니 다.
before

progress 12345
after 

Process finished with exit code 0

이 인터넷 들 은 매우 많 습 니 다. 주로 Retrofit 의 동적 에이전트 와 비교 가 됩 니 다. 2. Retrofit 의 동적 대 리 는 먼저 우리 가 사용 할 때 호출 인 터 페 이 스 를 씁 니 다.
public interface RetrofitService {
    @Headers({"Content-type:application/json;charset=UTF-8"})
    @GET("data/{type}/20/{page}")
    Observable>> getNewsList(@Path("type") String type, @Path("page") int page);
}

지금 문제 가 생 겼 습 니 다. 우 리 는 뒤의 코드 에서 이 인 터 페 이 스 를 진정 으로 실현 한 적 이 없습니다. Retrofit 는 어떻게 동적 대 리 를 합 니까? 우리 가 뒤에 사용 하 는 이 인터페이스 가 바로 이 렇 습 니 다.
retrofit.create(RetrofitService.class);

따라 들 어가 보 자.
  public  T create(final Class service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, 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);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod serviceMethod = loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

진정 으로 작용 하 는 것 은
ServiceMethod serviceMethod = loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);

그러나 우 리 는 method. invoke 라 는 글 자 를 전혀 보지 못 했다. (앞의 것 은 아니 고 잘못 사용 한 판단 일 뿐이다) 사실은 여기 서 Retrofit 가 정규 적 인 동적 대 리 를 실현 하지 못 했다 는 것 을 생각 할 수 있다. 왜냐하면 우 리 는 대 리 를 요구 하 는 대상 이 들 어 오지 않 았 기 때문이다. 그 가 이렇게 쓰 는 것 은 바로 동태 대리 의 특성 으로 자신 이 원 하 는 데 이 터 를 얻 은 다음 에 그의 생각 에 따라(향 원 모드 구축 요청) 앞의 Demo 를 Retrofit 와 유사 한 상황 으로 바 꿀 수 있 습 니 다. 3. Retrofit 개조 후의 Demo 를 모방 할 수 있 습 니 다.
/**
 * Description:    
 */
public class RetrofitProxy {
//    private Retrofit retrofit;
//
//    public RetrofitProxy(Retrofit retrofit) {
//        this.retrofit = retrofit;
//    }

    public static  T create(Class service){
        if (!service.isInterface()){
            throw new IllegalArgumentException("API declarations must be interfaces. ");
        }
        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service},
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("before
"); // method.invoke(retrofit, args); System.out.printf("function name: " + method.getName() + "
"); System.out.printf("function return type: " + method.getReturnType().getName() + "
"); System.out.printf("args name: " + args[0].toString() + "
"); System.out.printf("after
"); return null; } }); } }
/**
 * Description:   
 */

public class TestMain {
    public static void main(String[] args) {
//        RetrofitProxy proxy = new RetrofitProxy(new Retrofit());
        RetrofitInterface retrofitInterface =  RetrofitProxy.create(RetrofitInterface.class);
        retrofitInterface.retrofitInterfaceFunc("12345");
    }
}

실행 결 과 는 다음 과 같 습 니 다.
before

function name: retrofitInterfaceFunc
function return type: java.lang.String
args name: 12345
after 

Process finished with exit code 0

프 록 시 대상 이 전달 되 지 않 았 지만 동적 프 록 시 특성 을 사용 하여 인터페이스 에 있 는 모든 인 자 를 가 져 와 자신의 일 을 실현 했다.

좋은 웹페이지 즐겨찾기