又是很久没有写博客了,疫情结束后经济萧条,很多年轻人受疫情的影响而被迫离职至今未找到工作。今年受疫情影响,招聘需求明显萎缩,离职人员近几个月大幅增加,这应该是最难找工作的一年,相信不管是在职或离职的小伙伴应该都不太轻松。有工作经验的人尚且如此,今年毕业的应届生求职可能会更加艰难。生活不易,但是我们仍要以积极的心态去应对,相信终有一天这一切都会过去,生活又美好如初。受疫情影响今年我也经历了找工作这段痛苦的日子,受老天眷顾找到了一份新的工作,但仍然感觉自己的技术实力还需提高,作为程序员扎实的基础是核心竞争力中不可缺少的一部分,在扎实的基础下进一步扩展深度,学习更多的计算机底层原理,同时扩展广度,学习当下的新技术,只有保证自己的核心竞争力,才能在任何时候面对危机和考验从容应对。代理模式是设计模式中的常考点且很多开源框架都用到了这个模式,有必要学习并加深理解,在此做一个学习记录。
静态代理 外地拼搏的年轻人总是要面对租房的问题,这里以租房为例,理解静态代理模式。首先我们需要一个租赁接口,这个接口中只有一个方法就是租房
1 2 3 public interface Rent { void rentHouse () ; }
有一个年轻人叫小明,在外地拼搏的他需要租房,需要继承租赁这个接口并实现租房的方法
1 2 3 4 5 6 public class XiaoMing implements Rent { @Override public void rentHouse () { Log.v("proxy" ,"小明需要租房" ); } }
有一个中介机构链家可以帮你租房,你将租房需求告诉他们,当你满意成功租房后需要支付给他们中介费
1 2 3 4 5 6 7 8 9 10 11 12 13 public class LianJia implements Rent { private Rent rent; public LianJia (Rent rent) { this .rent = rent; } @Override public void rentHouse () { Log.v("proxy" ,"链家获取你的租房需求" ); rent.rentHouse(); Log.v("proxy" ,"链家帮你租房" ); } }
接下来让链家帮小明租房
1 2 3 4 5 6 Rent xiaoMing = new XiaoMing(); LianJia lianJia = new LianJia(xiaoMing); lianJia.rentHouse();
动态代理 Java中有个代理器可以实现接口对象的代理并生成对应的代理对象,我们利用Proxy.newProxyInstance生成实现了Rent接口的小明并生成代理对象,invoke方法中第一个参数是代理对象,第二个参数是被代理的方法,第三个参数是当前方法传入的参数值
1 2 3 4 5 6 Object o = Proxy.newProxyInstance(SplashActivity.class.getClassLoader(), new Class[]{Rent.class}, new InvocationHandler() { @Override public Object invoke (Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(xiaoMing,args); } });
将代理对象转化为Rent接口的实例并调用租房的方法
1 2 3 Rent xiaoMingProxy = (Rent) o; xiaoMingProxy.rentHouse();
手写Retrofit框架 Retrofit的核心就是通过动态代理,将注解参数拼接成一个完整的http请求再给网络请求框架去处理
自定义注解 Field 1 2 3 4 5 @Target (ElementType.PARAMETER) @Retention (RetentionPolicy.RUNTIME) public @interface Field { String value () ; }
GET 1 2 3 4 5 @Target (ElementType.METHOD) @Retention (RetentionPolicy.RUNTIME) public @interface GET { String value () ; }
POST 1 2 3 4 5 @Target (ElementType.METHOD) @Retention (RetentionPolicy.RUNTIME) public @interface POST { String value () ; }
Query 1 2 3 4 5 @Target (ElementType.PARAMETER) @Retention (RetentionPolicy.RUNTIME) public @interface Query { String value () ; }
实现Retrofit 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 public class MyRetrofit { final Map<Method, ServiceMethod> serviceMethodMap = new ConcurrentHashMap<>(); final Call.Factory callFactory; final HttpUrl baseUrl; public MyRetrofit (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 proxy, Method method, Object[] args) throws Throwable { ServiceMethod serviceMethod = loadServiceMethod(method); return serviceMethod.invoke(args); } }); } private ServiceMethod loadServiceMethod (Method method) { ServiceMethod serviceMethod = serviceMethodMap.get(method); if (serviceMethod == null ){ synchronized (serviceMethodMap){ serviceMethod = serviceMethodMap.get(method); if (serviceMethod == null ){ serviceMethod = new ServiceMethod.Builder(this ,method).build(); serviceMethodMap.put(method,serviceMethod); } } } return serviceMethod; } public static final class Builder { private HttpUrl baseUrl; private Call.Factory callFactory; public Builder callFactory (Call.Factory callFactory) { this .callFactory = callFactory; return this ; } public Builder baseUrl (String url) { this .baseUrl = HttpUrl.parse(url); return this ; } public MyRetrofit build () { if (baseUrl == null ){ throw new IllegalStateException("base url required" ); } Call.Factory callFactory = this .callFactory; if (callFactory == null ){ callFactory = new OkHttpClient(); } return new MyRetrofit(callFactory, baseUrl); } } }
实现方法参数解析服务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 public class ServiceMethod { private final Call.Factory callFactory; private final String url; private final boolean hasBody; private final ParameterHandler[] parameterHandlers; private FormBody.Builder formBuild; HttpUrl baseUrl; String httpMethod; HttpUrl.Builder urlBuilder; public ServiceMethod (Builder builder) { baseUrl = builder.retrofit.baseUrl; callFactory = builder.retrofit.callFactory; httpMethod = builder.httpMethod; url = builder.url; hasBody = builder.hasBody; parameterHandlers = builder.parameterHandlers; if (hasBody) { formBuild = new FormBody.Builder(); } } public Object invoke (Object[] args) { for (int i = 0 ; i < parameterHandlers.length; i++) { ParameterHandler handlers = parameterHandlers[i]; handlers.apply(this , args[i].toString()); } HttpUrl httpUrl; if (urlBuilder == null ) { urlBuilder = baseUrl.newBuilder(url); } httpUrl = urlBuilder.build(); FormBody formBody = null ; if (formBuild != null ) { formBody = formBuild.build(); } Request request = new Request.Builder().url(httpUrl).method(httpMethod, formBody).build(); return callFactory.newCall(request); } public void addQueryParameter (String key, String value) { if (urlBuilder == null ) { urlBuilder = baseUrl.newBuilder(url); } urlBuilder.addQueryParameter(key, value); } public void addFiledParameter (String key, String value) { formBuild.add(key, value); } public static class Builder { private final MyRetrofit retrofit; private final Annotation[] methodAnnotations; private final Annotation[][] parameterAnnotations; ParameterHandler[] parameterHandlers; private String httpMethod; private String url; private boolean hasBody; public Builder (MyRetrofit retrofit, Method method) { this .retrofit = retrofit; methodAnnotations = method.getAnnotations(); parameterAnnotations = method.getParameterAnnotations(); } public ServiceMethod build () { for (Annotation methodAnnotation : methodAnnotations) { if (methodAnnotation instanceof POST) { this .httpMethod = "POST" ; this .url = ((POST) methodAnnotation).value(); this .hasBody = true ; } else if (methodAnnotation instanceof GET) { this .httpMethod = "GET" ; this .url = ((GET) methodAnnotation).value(); this .hasBody = false ; } } int length = parameterAnnotations.length; parameterHandlers = new ParameterHandler[length]; for (int i = 0 ; i < length; i++) { Annotation[] annotations = parameterAnnotations[i]; for (Annotation annotation : annotations) { if (annotation instanceof Field) { String value = ((Field) annotation).value(); parameterHandlers[i] = new ParameterHandler.FieldParameterHandler(value); } else if (annotation instanceof Query) { String value = ((Query) annotation).value(); parameterHandlers[i] = new ParameterHandler.QueryParameterHandler(value); } } } return new ServiceMethod(this ); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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); } } }
定义网络请求Api 1 2 3 4 5 6 7 public interface WeatherApi { @POST ("/v3/weather/weatherInfo" ) Call postWeather (@Field("city" ) String city, @Field ("key" ) String key) ; @GET ("/v3/weather/weatherInfo" ) Call getWeather (@Query("city" ) String city, @Query ("key" ) String key) ; }
自定义Retrofit发起请求 初始化Retrofit 1 2 MyRetrofit myRetrofit = new MyRetrofit.Builder().baseUrl("https://restapi.amap.com" ).build(); weatherApi = myRetrofit.create(WeatherApi.class);
发起post请求 1 2 3 4 5 6 7 8 9 10 11 12 13 okhttp3.Call getCall = weatherApi.getWeather("110101" , "ae6c53e2186f33bbf240a12d80672d1b" ); getCall.enqueue(new okhttp3.Callback() { @Override public void onFailure (okhttp3.Call call, IOException e) { } @Override public void onResponse (okhttp3.Call call, okhttp3.Response response) throws IOException { Log.i("onResponse" , "onResponse enjoy get: " + response.body().string()); response.close(); } });
发起get请求 1 2 3 4 5 6 7 8 9 10 11 12 13 okhttp3.Call postCall = weatherApi.postWeather("110101" , "ae6c53e2186f33bbf240a12d80672d1b" ); postCall.enqueue(new okhttp3.Callback() { @Override public void onFailure (okhttp3.Call call, IOException e) { } @Override public void onResponse (okhttp3.Call call, okhttp3.Response response) throws IOException { Log.i("onResponse" , "onResponse enjoy post: " + response.body().string()); response.close(); } });