美文网首页
《读_Head_First_有感》_“代理模式_完结”

《读_Head_First_有感》_“代理模式_完结”

作者: tjhuey | 来源:发表于2018-10-25 13:37 被阅读81次

    前言:
    今天是设计模式我想说的最后模式————代理模式代理模式我认为是最重要的模式了,常用于开源框架底层封装,如Spring,Mybatis,HDFS,RPC,xxl-job 等;主要是aop的思想,业务中常用日志切面,接口访问量,并发量控制,简单的说是拦截相关请求做自己想做的事等,今天简单写个例子,并分享一下相关源码

    今日主题

    代理模式:概述:为其他对象提供一种代理可以控制这个对象的访问

    场景:

    假设某些操作处理,需要其他事物执行,并在执行时动态的去扩展,可以采用。
    在这里,我简单写了个demo,模拟某些操作需要代理,其中计算操作代理,计算操作前后需要处理一些事情。

    代码如下

    '设计模式'代码

    package com.huey.designpattern.dynamicproxy;
    
    /**
    * ┏┓   ┏┓
    * ┏┛┻━━━┛┻┓
    * ┃       ┃  
    * ┃   ━   ┃
    * ┃ ┳┛ ┗┳ ┃
    * ┃       ┃
    * ┃   ┻   ┃
    * ┃       ┃
    * ┗━┓   ┏━┛
    * ┃   ┃ 神兽保佑        
    * ┃   ┃ 代码无BUG!
    * ┃   ┗━━━┓
    * ┃       ┣┓
    * ┃       ┏┛
    * ┗┓┓┏━┳┓┏┛
    * ┃┫┫ ┃┫┫
    * ┗┻┛ ┗┻┛
     * @author huey
     * @Description : 代理操作
     * @Date Created in 2018/10/21 20:23
    */
    public interface ProxyOperation<T> {
    
        /**
         * @author huey
         * @Description : 其他对象初始化
         * @Date Created in 2018/10/21 20:27
         */
        void init();
        /**
         * @author huey
         * @Description : 钩子 是否计算了
         * @Date Created in 2018/10/21 20:25
         */
        boolean isCalc(boolean flag);
    
        /**
         * @author huey
         * @Description : 计算后,其他对象后置处理
         * @Date Created in 2018/10/21 20:27
         */
        void postProcessor();
    }
    package com.huey.designpattern.dynamicproxy;
    
    /**
    * ┏┓   ┏┓
    * ┏┛┻━━━┛┻┓
    * ┃       ┃  
    * ┃   ━   ┃
    * ┃ ┳┛ ┗┳ ┃
    * ┃       ┃
    * ┃   ┻   ┃
    * ┃       ┃
    * ┗━┓   ┏━┛
    * ┃   ┃ 神兽保佑        
    * ┃   ┃ 代码无BUG!
    * ┃   ┗━━━┓
    * ┃       ┣┓
    * ┃       ┏┛
    * ┗┓┓┏━┳┓┏┛
    * ┃┫┫ ┃┫┫
    * ┗┻┛ ┗┻┛
     * @author huey
     * @Description : 业务:计算
     * 实际目标对象接口
     * @Date Created in 2018/10/21 20:18
    */
    public interface ProxyCalcOperation extends ProxyOperation {
    
         void calc();
    }
    package com.huey.designpattern.dynamicproxy;
    
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * ┏┓   ┏┓
     * ┏┛┻━━━┛┻┓
     * ┃       ┃
     * ┃   ━   ┃
     * ┃ ┳┛ ┗┳ ┃
     * ┃       ┃
     * ┃   ┻   ┃
     * ┃       ┃
     * ┗━┓   ┏━┛
     * ┃   ┃ 神兽保佑
     * ┃   ┃ 代码无BUG!
     * ┃   ┗━━━┓
     * ┃       ┣┓
     * ┃       ┏┛
     * ┗┓┓┏━┳┓┏┛
     * ┃┫┫ ┃┫┫
     * ┗┻┛ ┗┻┛
     *
     * @author huey
     * @Description : 业务默认计算操作目标对象
     * @Date Created in 2018/10/21 20:21
     */
    @Slf4j
    public class ProxyCalcOperationDefault implements ProxyCalcOperation {
    
        @Override
        public void calc() {
            log.info("ProxyCalcOperationDefault --> {}","calc");
        }
    
        /**
         * @author huey
         * @Description : 其他对象初始化
         * @Date Created in 2018/10/21 20:27
         */
        @Override
        public void init() {
            log.info("ProxyCalcOperationDefault --> {}","init");
        }
    
        /**
         * @param flag
         * @author huey
         * @Description : 钩子 是否计算了
         * @Date Created in 2018/10/21 20:25
         */
        @Override
        public boolean isCalc(boolean flag) {
            return false;
        }
    
        /**
         * @author huey
         * @Description : 计算后,其他对象后置处理
         * @Date Created in 2018/10/21 20:27
         */
        @Override
        public void postProcessor() {
            log.info("ProxyCalcOperationDefault --> {}","postProcessor");
        }
    }
    package com.huey.designpattern.dynamicproxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    
    /**
     * ┏┓   ┏┓
     * ┏┛┻━━━┛┻┓
     * ┃       ┃
     * ┃   ━   ┃
     * ┃ ┳┛ ┗┳ ┃
     * ┃       ┃
     * ┃   ┻   ┃
     * ┃       ┃
     * ┗━┓   ┏━┛
     * ┃   ┃ 神兽保佑
     * ┃   ┃ 代码无BUG!
     * ┃   ┗━━━┓
     * ┃       ┣┓
     * ┃       ┏┛
     * ┗┓┓┏━┳┓┏┛
     * ┃┫┫ ┃┫┫
     * ┗┻┛ ┗┻┛
     *
     * @author huey
     * @Description : 代理简单工具类
     * @Date Created in 2018/10/21 20:33
     */
    public class ProxyOperationUtil {
    
        public static ProxyCalcOperation getProxy(ProxyOperation proxyOperation) {
    
            ClassLoader loader = proxyOperation.getClass().getClassLoader();
    
            Class<?>[] interfaces = proxyOperation.getClass().getInterfaces();
    
            //代理类执行的代码,lamda,联想aop
            InvocationHandler h = (proxy, method, args) -> {
                //前置扩展,非业务代码,模拟其他方法栈调用
                proxyOperation.init();
                //目标方法
                Object result = method.invoke(proxyOperation, args);
    
                //后置扩展,非业务代码,模拟其他方法栈调用
                proxyOperation.postProcessor();
                return result;
            };
            ProxyCalcOperation newProxyInstance = (ProxyCalcOperation) Proxy.newProxyInstance(loader, interfaces, h);
            return newProxyInstance;
        }
    }
    package com.huey.designpattern.dynamicproxy;
    
    import lombok.extern.slf4j.Slf4j;
    import org.junit.Test;
    import sun.misc.ProxyGenerator;
    
    import java.io.FileOutputStream;
    
    @Slf4j
    public class ProxyOperationTest {
    
        /**
         * @author huey
         * @Description : 普通
         * @Date Created in 2018/10/21 20:52
         */
    
        @Test
        public void test1() {
            ProxyCalcOperation proxyCalcOperation = new ProxyCalcOperationDefault();
            proxyCalcOperation.calc();
        }
    
        /**
         * @author huey
         * @Description : 代理
         * @Date Created in 2018/10/21 20:52
         */
        @Test
        public void test2() {
            ProxyCalcOperation proxyCalcOperation = new ProxyCalcOperationDefault();
            // 从源码中得知,设置这个值,可以把生成的代理类,输出出来。
            ProxyCalcOperation proxy = ProxyOperationUtil.getProxy(proxyCalcOperation);
            proxy.calc();
        }
    
        /**
         * @author huey
         * @Description : 生成后 反编译下 查看
         * @Date Created in 2018/10/21 22:13
         */
        @Test
        public void test3() {
            //生成的jdk代理类
            byte[] bytes = ProxyGenerator.generateProxyClass("$ProxyTl", new Class[]{ProxyCalcOperation.class});
            try {
                FileOutputStream fileOutputStream = new FileOutputStream("E:\\company\\$ProxyTl.class");
                fileOutputStream.write(bytes);
                fileOutputStream.flush();
                fileOutputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    
    }
    
    

    联想

    spring中的代理模式是什么样的呢?简单列出了4个图,jdk和cglib两种方式,默认jdk,UT3中的代理类反编译后可看默认继承Proxy实现目标接口,为啥jdk代理必须是接口形式呢,其实很简单,因为java是单继承。如果哪天再总结spring的小编再跟踪下

    spring_jdk_proxy.png spring_cglib_proxy_1.png spring_cglib_proxy_2.png
    is_cglib_default.png

    jdk代理源码配图

    1.png 2.png 3.png 4.png 5.png 6.png 7.png 8.png

    总结

    设计模式【六大原则和23种模式】是个学不完的东西,还是要看自己想到哪种程度,读源码,了解框架,非常的敏感,过瘾
    最后,谢谢读者们的欣赏,也希望指出其中的不足,小编还会继续边学习边总结
    谢谢HeadFirst 作者。设计模式的学习层面结束了!


    代码请参考码云:https://gitee.com/tjhuey/CodingGroup
    设计模式相关概念请参考:http://naotu.baidu.com/file/5811bf42020e6a2d877b992cfca90d26

    进度

    • [x] 策略模式,<span style="color: #43A047; ">已完成</span>
    • [x] 观察者模式,<span style="color: #43A047; ">已完成</span>;
    • [x] 装饰者模式,<span style="color: #43A047; ">已完成</span>;
    • [x] 工厂方法模式,<span style="color: #43A047; ">已完成</span>;
    • [x] 抽象工厂模式,<span style="color: #43A047; ">已完成</span>;
    • [x] 单例模式,<span style="color: #43A047; ">已完成</span>;
    • [x] 命令模式,<span style="color: #43A047; ">已完成</span>;
    • [x] 适配模式,<span style="color: #43A047; ">已完成</span>;
    • [x] 外观模式,<span style="color: #43A047; ">已完成</span>;
    • [x] 模板模式,<span style="color: #43A047; ">已完成</span>;
    • [x] 状态模式,<span style="color: #43A047; ">已完成</span>;
    • [x] 代理模式,<span style="color: #43A047; ">已完成</span>;

    相关文章

      网友评论

          本文标题:《读_Head_First_有感》_“代理模式_完结”

          本文链接:https://www.haomeiwen.com/subject/ubgqtqtx.html