0%

代理模式-学习笔记


又是很久没有写博客了,疫情结束后经济萧条,很多年轻人受疫情的影响而被迫离职至今未找到工作。今年受疫情影响,招聘需求明显萎缩,离职人员近几个月大幅增加,这应该是最难找工作的一年,相信不管是在职或离职的小伙伴应该都不太轻松。有工作经验的人尚且如此,今年毕业的应届生求职可能会更加艰难。生活不易,但是我们仍要以积极的心态去应对,相信终有一天这一切都会过去,生活又美好如初。受疫情影响今年我也经历了找工作这段痛苦的日子,受老天眷顾找到了一份新的工作,但仍然感觉自己的技术实力还需提高,作为程序员扎实的基础是核心竞争力中不可缺少的一部分,在扎实的基础下进一步扩展深度,学习更多的计算机底层原理,同时扩展广度,学习当下的新技术,只有保证自己的核心竞争力,才能在任何时候面对危机和考验从容应对。代理模式是设计模式中的常考点且很多开源框架都用到了这个模式,有必要学习并加深理解,在此做一个学习记录。


静态代理

外地拼搏的年轻人总是要面对租房的问题,这里以租房为例,理解静态代理模式。首先我们需要一个租赁接口,这个接口中只有一个方法就是租房

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) // 表单提交,作用在POST请求的参数上
@Retention(RetentionPolicy.RUNTIME) // 运行期保留
public @interface Field {
String value();
}

GET

1
2
3
4
5
@Target(ElementType.METHOD) // 声明GET请求,作用在方法上
@Retention(RetentionPolicy.RUNTIME) // 运行期保留
public @interface GET {
String value();
}

POST

1
2
3
4
5
@Target(ElementType.METHOD) // 声明POST请求,作用在方法上
@Retention(RetentionPolicy.RUNTIME) // 运行期保留
public @interface POST {
String value();
}

Query

1
2
3
4
5
@Target(ElementType.PARAMETER) // url上拼接,作用在请求的参数上
@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;// 请求服务器url地址

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;// 请求服务器url
String httpMethod; // 请求方式post/get
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;

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

// 处理传参
public Object invoke(Object[] args) {
// 处理请求的地址与参数
for (int i = 0; i < parameterHandlers.length; i++) {
ParameterHandler handlers = parameterHandlers[i];
//handler内本来就记录了key,现在给到对应的value
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);
}

// get请求, 按http的方式处理参数
public void addQueryParameter(String key, String value) {
if (urlBuilder == null) {
urlBuilder = baseUrl.newBuilder(url);
}
urlBuilder.addQueryParameter(key, value);
}

//Post请求, 按http的方式处理参数
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() {

//处理POST与GET
for (Annotation methodAnnotation : methodAnnotations) {
if (methodAnnotation instanceof POST) {
//记录请求方式
this.httpMethod = "POST";
//记录请求url的path
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) {
// 如果是Field注解
if (annotation instanceof Field) {
//得到注解上的value也就是请求参数的key
String value = ((Field) annotation).value();
// 传入参数的key
parameterHandlers[i] = new ParameterHandler.FieldParameterHandler(value);
}
// 如果是Query注解
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();
}
});