• java初探之代理模式


    代理模式

    代理模式一般有三种角色:

    在这里插入图片描述

    没有使用代理模式的话可能就会直接去操作真实的对象

    加入代理模式就是加入了 隔离 把我们的真实对象与调用者隔离了一下(代理对象)

    代理对象的好处?

    使用者(client)跟真实的对象是没有直接的交集的。不会直接操作到真实对象

    实例
    //1.代理角色对象 定义了服务的接口
    public interface Massage{
        void message();
    }
    
    • 1
    • 2
    • 3
    • 4
    //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("精通各种手法")
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    //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交互
            
    }
    
    • 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

    每个代理类只能为一个接口来服务

    如果有多个功能就要写多个代理类如:

    public class WashAgent implements Wash{
        @Override
        public void wash(){
            
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    想办法通过一个代理类实现全部的代理功能!->动态代理

    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...");
        }
    }
    
    
    • 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

    源码解析

    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();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    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);
            }
        }
        
    }    
    
    • 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

    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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    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();
    
    • 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
    //记录请求类型 请求参数 完整地址
    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);
            }
        } 
    }
    
    • 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
    //
    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中
            }
        }
    }
    
    • 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

    /回调到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中
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    }

    
    
    • 1
  • 相关阅读:
    如何用在线模版快速制作活动海报?
    C语言实现:删除链表倒数第k个元素
    【图像处理】关于颜色的万花筒(RGB--HSV)
    Fast R-CNN
    【编解码格式】Dirac、VC-2、VC-1、WMV3(WMV9)
    R语言快速绘制多因素回归分析森林图
    Java核心知识体系5:反射机制详解
    C练题笔记之:Leetcode-658. 找到 K 个最接近的元素
    使用Jtest 2022.2简化严格的Java测试
    使用VSCode新建解决方案,添加ClassLib类库工程
  • 原文地址:https://blog.csdn.net/yuhang01/article/details/134431671