• 代理模式与动态代理深入理解


    一,代理模式的简单认识

    1.参与者: 代理对象,被代理对象

    代理对象相当于现实生活中的房产中介被代理对象
    相当于 房东

    2.目的:保护被代理对象

    避免外界直接修改被代理对象,破坏掉被代理对象原本的功能。
    将对被代理对象功能的增强放在代理对象中,
    代理对象中存在一个对被代理对象的引用,在使用被代理对象之前或者之后,代理对象可以做一些额外的添油加醋方法。
    (这符合开闭原则: 对修改关闭,对拓展开放
    在这里插入图片描述

    被代理对象 ProxyObjected.java

    package src.com.liu.proxy;
    //被代理对象(房东)
    public class ProxyObjected {
        public void process(){
            System.out.println("我是被代理对象的方法 process");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    代理对象 ProxyObject.java

    package src.com.liu.proxy;
    //代理对象(中介)
    public class ProxyObject {
        private ProxyObjected obj;
        ProxyObject(ProxyObjected obj){
            this.obj = obj;
        }
        public void process(){
            ProxyObjected obj = this.obj;
    
            System.out.println("====被代理对象的方法执行之前,执行添油加醋的动作");
            //执行被代理对象
            obj.process();
            System.out.println("====被代理对象的方法执行之后,执行一些添油加醋的动作");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    测试代码

    package src.com.liu.proxy;
    
    public class Test {
        public static void main(String[] args) {
                //创建被代理对象
                ProxyObjected obj = new ProxyObjected();
                //创建代理对象(把被代理对象当作参数传入)
                ProxyObject proxyObject = new ProxyObject(obj);
                //执行代理对象的方法(先执行添油加醋,再执行被代理对象的process,再执行添油加醋)
                proxyObject.process();
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    二,动态代理

    动态代理的意思是我们不直接生成我们的proxyObject,
    而是提供 1.被代理对象和 2.增强方法(那些添油加醋方法)3.以及各自调用时机,然后在代码运行时自动帮我们生成一个proxyObject。
    好处: 将代理对象方法和增强方法(添油加醋方法)解耦分离,使代码更具拓展型和可维护性。

    这里只讲jdk动态代理

    2.1 被代理对象 TestDao.java

    package src.com.liu.proxy.dynamic.jdk;
    
    public interface TestDao {
        public void save();
        public void modify();
        public void delete();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.2 被代理对象实现类 TestDaoImpl.java

    package src.com.liu.proxy.dynamic.jdk;
    
    public class TestDaoImpl implements TestDao{
        @Override
        public void save() {
            System.out.println("保存");
        }
    
        @Override
        public void modify() {
            System.out.println("修改");
        }
    
        @Override
        public void delete() {
            System.out.println("删除");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    2.3 代理对象的增强方法 类 Enhancement.java

    package src.com.liu.proxy.dynamic.jdk;
    //代理对象的增强方法 类
    public class Enhancement {
        public void check(){
            System.out.println("模拟权限控制");
        }
        public void except(){
            System.out.println("模拟异常处理");
        }
        public void log(){
            System.out.println("模拟日志记录");
        }
        public  void monitor(){
            System.out.println("性能监测");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2.4 代理对象类 JDKDynamicProxy.java

    package src.com.liu.proxy.dynamic.jdk;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    //代理对象类
    public class JDKDynamicProxy implements InvocationHandler
    {
        private TestDao testDao;//被代理对象
        JDKDynamicProxy(TestDao dao){
            this.testDao= dao;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Enhancement enhancement = new Enhancement();
            enhancement.check();
            enhancement.except();
    
            //调用被代理对象方法
            Object obj = method.invoke(testDao,args);
    
            enhancement.log();
            enhancement.monitor();
            return  obj;
        }
    }
    
    
    • 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

    2.5 JDKDynamicTest.java

    package src.com.liu.proxy.dynamic.jdk;
    
    import java.lang.reflect.Proxy;
    
    public class JDKDynamicTest {
        public static void main(String[] args) {
            //创建被代理对象
            TestDao testDao = new TestDaoImpl();
            //创建代理对象,并将被代理对象注入到代理对象中
            JDKDynamicProxy jdkDynamicProxy = new JDKDynamicProxy(testDao);
    
    
            //得到一个类加载器
            ClassLoader classLoader = JDKDynamicProxy.class.getClassLoader();
            //得到被代理对象的所有接口
            Class[] clazz = testDao.getClass().getInterfaces();
            //生成代理对象
            TestDao testDaoAdvice = (TestDao) Proxy.newProxyInstance(classLoader,clazz,jdkDynamicProxy);
    
            //执行方法
            testDaoAdvice.save();
            System.out.println("====================");
            testDaoAdvice.modify();
            System.out.println("====================");
            testDaoAdvice.delete();
        }
    }
    
    
    • 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

    2.6效果:
    在这里插入图片描述

    2.7 改变 Enhancement.java类中增强方法里的内容时,不改变现有代码运行
    在这里插入图片描述
    运行结果:
    在这里插入图片描述
    这实现了 代理对象里那些添油加醋增强方法 的结偶,
    当这些增强方法需要修改时,不用动代理对象类里的代码

  • 相关阅读:
    vue中含有iframe的页面如何避免路由切换时keep-alive不起作用
    面试高潮季即将来袭,Android 开发者能否在其中鲤鱼跃龙门?
    C#多线程下的调优
    插入排序.
    Map.get、Map.set、Map.has方法
    JSON parse error: Cannot deserialize instance of `xxx` out of START_ARRAY token
    DC/DC开关电源学习笔记(九)Buck降压拓扑原理
    安装vllm的时候卡主:Collecting vllm-nccl-cu12<2.19,>=2.18 (from vllm)
    初识Cpp之 二、IO与文件
    会跳舞的网站引导页HTML源码
  • 原文地址:https://blog.csdn.net/weixin_43225966/article/details/128054867