代理模式
代理模式一般有三种角色:
没有使用代理模式的话可能就会直接去操作真实的对象
加入代理模式就是加入了 隔离 把我们的真实对象与调用者隔离了一下(代理对象)
代理对象的好处?
使用者(client)跟真实的对象是没有直接的交集的。不会直接操作到真实对象
实例
//1.代理角色对象 定义了服务的接口
public interface Massage{
void message();
}
//2.真实的实现类:提供马杀鸡服务的路西
public class Lucy implements Massage{
@Override
public void message(){
System.out.println("手法一流");
}
}
public class Alvin implements Massage{
@Override
public void massage(){
System.out.println("精通各种手法")
}
}
//3.代理对象 马杀鸡经纪人
public class Agent implements Massage{
private final Massage massage;
public Agent(Massage massage){
this.massage = massage;
}
//前置处理
public void before(){
System.out.println("前置开始");
}
//后置处理
public void after(){
System.out.println("后置处理");
}
@Override
public void massage(){
before();
massage.massage();
after();
}
}
public class MyClass{
public static void main(String[] args) throws Exception{
//静态代理
Massage massage = new Lucy();
Agent agent = new Agent(massage);
agent.massage();//没有直接跟lucy交互
}
每个代理类只能为一个接口来服务
如果有多个功能就要写多个代理类如:
public class WashAgent implements Wash{
@Override
public void wash(){
}
}
想办法通过一个代理类实现全部的代理功能!->动态代理
public class MyClass{
public static void main(String[] args) throws Exception{
//动态代理 完成足浴与按摩
Alvin alvin = new Alvin();//真实的要操作的对象
//Proxy创建 动态代理对象
Object o = Proxy.newProxyInstance(MyClass.class.getClassLoader(),new Class[]{Message.class,Wash.class},new InvocationHandler(){
@OVerride
public Object invoke(Object o,Method method,Object[] objects)throws Throwable{
//System.out.println(o.toString()); 死循环 o就是Object o 调用o.任何方法都会进入invoke()中 就会一直调然后死循环
//invoke(在那个对象上执行的方法,方法参数)
return method.invoke(alvin,objects);
}
});
Massage massage = (Massage) o;
massage.massage();
Wash wash = (Wash) o;
wash.wash();
}
}
public class Alvin implements Massage,Wash{
@Override
public void massage(){
System.out.println("massage...");
}
@Override
public void wash(){
System.out.println("washing...");
}
}
源码解析
Proxy.class:
//生成 class数据 动态代理为我们创建的对象
byte[] var22 = ProxyGenerator.generateProxyClass(var23,var2,var17);
test:
private static void proxy() throws Exception{
String name = Massage.class.getName()+"$Proxy0";
//生成代理指定接口的class数据
byte[] bytes = ProxyGenerator.generateProxyClass(name,new Class[]{Massage.class});
FileOutputStream fos = new FileOutputStream("lib/"+name+".class");
fos.wirte(bytes);
fos.close();
}
com.enjoy.lib.Massage$Proxy0.class
public final class Massage$Proxy0 extends Proxy implements Massage{
public Massage$Proxy0(InvocationHandler var1)throws{
//这里的invovationHandler就是new ProxyInstance传入的
super(var1);
}
public final void massage() throws{
try{
//super.h===var1;
//给接口赋值 这样newProxyInstance就会被回调出去
super.h.invoke(this,m3,(Object][])null);
}catch(Throwable var3){
throw new UndeclaredThrowableException(var3);
}
}
public final String toString() throws{
try{
return (String)super.h.invoke(this,m2,(Object[])null);
}catch(Throwable var3){
throw new UndeclaredThrowableException(var3);
}
}
}
Retrofit实操
public interface WetherApi{
@POST("/v3/weather/weatherInfo")
@FormUrlEncoded
Call<ResponseBody> getWeather(@Field("city") String city,@Field("key") String key);
@GET("/v3/weather/weatherInfo")
Call<ResponseBody> getWeather(@Query("city") String city,@Query("key") String key);
}
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://restapi.amap.com").build();
//create()就是内部完成了动态代理
WeatherApi weatherApi = retrofit.create(WetherApi.class);
public class EnjoyRetrofit{
//第一次调用解析一次 第二次调用又去解析一次吗
final Map<Method,ServiceMethod> serviceMethodCache = new ConcurrentHashMap<>();
final Call.Factory callFactory;
final HttpUrl baseUrl;
EnjoyRetrofit(Call.Factory callFactory,HttpUrl baseUrl){
this.callFactory = callFactory;
this.baseUrl = baseUrl;
}
public <T> T create(final Class<T> service){
return (T) Proxy.newInstance(service.getClassLoader(),new Class[]{service},new InvocationHandler(){
@Override
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
//实现对应的postWeather/getWeather
//解析method上所有的注解信息
loadServiceMethod(method);
return serviceMethod.invoke(args);//返回Call
}
});
}
//解析方法上的注解
private ServiceMethod loadServiceMethod(Method method){
//先不上锁 避免synchronized的性能损耗
ServiceMethod result = serviceMethodCache.get(method);
if(result!=null) return result;
//多线程下避免重复解析
synchronized(serviceCache){
//线程A和B进入时 A先进 result=null 给result赋值后B进入 如果不判断是否为空 会再次解析一次
result = serviceCache.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 EnjoyRetrofit build(){
if(baseUrl==null){
throw new IllegalStateException("Base URL,required");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if(callFactory==null){
callFactory = new OkHttpClient();
}
return new EnjoyRetrofit(callFactory,baseUrl);
}
}
}
//可以设置也可以不设置 build会进行校验
EnjoyRetrofit.Builder().baseUrl("https").callFactory(new OkHttpClient.Builder().callTimeout(1)).build();
//记录请求类型 请求参数 完整地址
public class ServiceMethod{
String baseUrl;
private final okhttp3.Call.Factory callFactory;
String httpMethod;
String relativeUrl;
Boolean hasBody;
private FormBody.Builder formBuild;
//每个参数的key
ParameterHandler[] parameterHandler;
HttpUrl.Builder urlBuilder;//完整的url
public ServiceMethod(Builder builder){
baseUrl = builder.enjoyRetrofit.baseUrl;
callFactory = builder.enjoyRetrofit.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){
//处理请求的地址与参数 重点
for(int i=0;i<parameterHandler.length;i++){
ParameterHandler handlers = parameterHandler[i]; //handler记录了key
//handler内本来就记录了key 现在给到了对应的value
handlers.apply(this,args[i].toString());//this->ServiceMethod记录了请求地址 args[i]记录了参数的value
}
//获取最终请求地址
HttpUrl url;
if(urlBuilder ==null){//说明不是get请求
urlBuilder = baseUrl.newBuilder(relativeUrl);
}
url = urlBuilder.build();
//请求体
FormBody formBody = null;
if(formBuild!=null){
formBody = formBuild.build();
}
//使用okhttp发送请求 get请求时formBody==null没关系可以传入
Request request = new Request.Builder().url(url).method(httpMethod,formBody).build();
return callFactory.newCall(request);
}
//get请求 把k-v 拼到url里面
public void addQueryParameter(String key,String value){
if(urlBuilder ==null){
urlBuilder = baseUrl.newBuilder(relativeUrl);
}
urlBuilder.addQuery(key,value);
}
//吧k-v放到请求体中
public void addFieldParameter(String key,String value){
formBuild.add(key,value);
}
public static class Builder{
private final EnjoyRetrofit enjoyRetrofit;
private final Annotation[] methodA nnotations;
private final Annotation[][] parameterAnnotations;
private String httpMethod;
private String relativeUrl;
private Boolean hasBody;
private ParameterHandler[] parameterHandler;
public Builder(EnjoyRetrofit enjoyRetrofit,Method method){
this.enjoyRetrofit = enjoyRetrofit;
//获取方法上的所有注解
methodAnnotations = method.getAnnotations();
//获得方法参数的所有的注解(一个参数可以有多个注解,一个方法又会有多个参数)
paramterAnnotations = method.getParameterAnnotations();
}
public ServiceMethod build(){
//1.解析方法上的注解 只处理POST和GET
for(Annotation methodAnnotation:methodAnnotations){
if(methodAnnotation instance of POST){//post请求
//记录当前请求方式
this.httpMethod = "POST";
//记录当前url的path
this.relativeUrl = ((POST) methodAnnotation).getValue();
//是否有请求体
this.hasBody = true;
}else if(methodAnnotation instance of GET){
this.httpMethod = "GET";
this.relativeUrl = ((GET) methodAnnotation).getValue();
this.hasBody = false;
}
}
//2.解析方法参数的注解
int length = paramterAnnotations.length;//有多少个参数
parameterHandler = new ParameterHandler[length];
for(int i=0;i< length;i++){
//一个参数上面所有的注解
Annotation[] annotations = parameterAnnotations[i];
//处理参数上的每一个注解
for(Annotation annotation:annotations){
if(annotation instance of Field){
//得到注解上的value 请求参数的key
String value = ((Field) annotation).getValue();
//又在一个新的类中记录了请求参数的key
parameterHandler[i] = new ParameterHandler.FieldParameterHandler(value);
}else if(annotation instance of Query){
String value = ((Query) annotation).getValue();
parameterHandler[i] = new ParameterHandler.QueryParameterHandler(value);
}
}
}
return new ServiceMethod(this);
}
}
}
//
public abstract class ParameterHandler{
abstract void apply(ServiceMethod serviceMethod,String value);
//只处理get请求 没有请求头
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);//回调到serviceMethod中
}
}
//只处理post请求 带请求头
static class FiledParameterHander extends ParameterHandler{
String key;
public FiledParameterHandler(String key){
this.key = key;
}
@Override
void apply(ServiceMethod serviceMethod,String value){
serviceMethod.addFieldParameter(key,value);//回调到serviceMethod中
}
}
}
/回调到serviceMethod中
}
}
//只处理post请求 带请求头
static class FiledParameterHander extends ParameterHandler{
String key;
public FiledParameterHandler(String key){
this.key = key;
}
@Override
void apply(ServiceMethod serviceMethod,String value){
serviceMethod.addFieldParameter(key,value);//回调到serviceMethod中
}
}
}