• 设计模式之代理模式的理解


    设计模式之代理模式的理解

    设计模式之代理模式



    前言

    1)代理模式:为一个对象提供一个替身,以控制对这个对象的访问。即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。
    2)被代理的对象可以是远程对象、创建开销大的对象或需要安全控制的对象
    3)代理模式有不同的形式,主要有三种静态代理、动态代理(JDK代理、接口代理和Cglib代理(可以在内存动态的创建对象,而不需要实现接口,他是属于动态代理的范畴。4)代理模式示意图


    提示:以下是本篇文章正文内容,下面案例可供参考

    一、代理模式的分类

    1,静态代理
    2,动态代理
    3,Cglib代理

    二、实现步骤

    1.静态代理

    优点

    在不修改目标对象的功能前提下,能通过代理对象对目标功能扩展

    缺点

    因为代理对象需要与目标实现一样的接口,所以就会有很多代理类

    一旦接口增加方法,目标对象与代理对象都要维护

    抽象(被代理对象)

    public interface ITeacherDao {
    
        void teach();
    }
    
    • 1
    • 2
    • 3
    • 4

    实现

    public class TeacherDao implements ITeacherDao {
        @Override
        public void teach() {
            System.out.println("老师授课中");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    代理对象

    public class TeacherDaoProxy implements ITeacherDao {
    
        private ITeacherDao target;
    
        public TeacherDaoProxy(ITeacherDao target) {
            this.target = target;
        }
    
        @Override
        public void teach() {
            System.out.println("代理开始");
            target.teach();
            System.out.println("代理结束");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    使用

    public class Client {
    
        public static void main(String[] args) {
    
            TeacherDao teacherDao = new TeacherDao();
    
            TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);
    
            teacherDaoProxy.teach();
    
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    输出

    在这里插入图片描述

    2.动态代理

    动态代理模式的基本介绍

    1)代理对象,不需要实现接口,但是目标对象要实现接口,否则不能用动态代理
    2)代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象
    3)动态代理也叫做:JDK代理、接口代理

    JDK中生成代理对象的API

    1)代理类所在包:java.lang.reflect.Proxy
    2)JDK实现代理只需要使newProxyInstance方法,但是该方法需要接收三个参数,完
    整的写法是:static Object newProxylnstance(ClassLoader loaderClass[]interfaces.InvocationHandler h)

    抽象类

    public interface ITeacherDao {
    
        void teach();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    实现类

    public class TeacherDao implements ITeacherDao {
        @Override
        public void teach() {
            System.out.println("老师授课中");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    代理类

    public class ProxyFactory {
        // 维护目标对象
        private Object object;
        public ProxyFactory(Object object) {
            this.object = object;
        }
        //给目标对象  生产一个代理对象
        public Object getProxyInstance(){
            /**
             * 参数1,ClassLoader loader 指定当前目标对象使用的类加载器,获取加载器的方法固定
             * 参数2,目标对象实现的接口类型,使用泛型方法确认类型
             * 参数3,事件处理,执行目标对象的方法时,会触发事件处理器方法,会把当前执行的目标对象作为参数传入
             */
          return Proxy.newProxyInstance(object.getClass().getClassLoader()
                  , object.getClass().getInterfaces(),(o, method, objects) -> {
                      System.out.println("JDK代理开始~");
                      Object invoke = method.invoke(object, objects);
                      return invoke;
                  }
          );
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    调用

    public class Client {
    
    
        public static void main(String[] args) {
            ITeacherDao target = new TeacherDao();
            // 给目标对象,创建代理对象
            ITeacherDao iTeacherDao =(ITeacherDao) new ProxyFactory(target).getProxyInstance();
            iTeacherDao.teach();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    3.Cglib代理

    Cglib代理模式的基本介绍

    实体类

    public class CglibService {
    
        public void cg1(){
            System.out.println("cg1方法被调用了");
        }
    
        public void cg2(){
            System.out.println("cg2方法被调用了");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    代理类

    public class CgServiceInterceptor implements MethodInterceptor {
        private Object target;
    
        public CgServiceInterceptor(Object target) {
            this.target = target;
        }
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("执行方法"+method.getName());
            System.out.println(method.getName()+"方法执行前");
            Object result = methodProxy.invokeSuper(o, objects);
            System.out.println(method.getName()+"方法执行后");
            return result;
        }
    
        public static <T> T createProxy(T target) {
            CgServiceInterceptor cglibProxyTest = new CgServiceInterceptor(target);
            Enhancer enhancer = new Enhancer();
            enhancer.setCallback(cglibProxyTest);
            enhancer.setSuperclass(target.getClass());
            return (T) enhancer.create();
        }
    }
    
    
    • 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

    调用

    public class TestCg {
        public static void main(String[] args) {
            CglibService cglibService = CgServiceInterceptor.createProxy(new CglibService());
            cglibService.cg1();
            cglibService.cg2();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    输出

    在这里插入图片描述
    1)静态代理和JDK代理模式都要求目标对象是实现一个接口,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候可使用目标对象子类来实现代理-这就是Cglib代理
    2)Cglib代理也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能扩展,有些书也将Cglib代理归属到动态代理。
    3)Cglib是一个强大的高性能的代码生成包,它可以在运行期扩展iava类与实现iava接口.它广泛的被许多AOP的框架使用,例如Spring AOP,实现方法拦截
    4)在AOP编程中如何选择代理模式:
    4.1目标对象需要实现接口,用JDK代理
    4.2目标对象不需要实现接口,用Cglib代理
    5)Cglib包的底层是通过使用字节码处理框架ASM来转换字节码并生成新的类


    代理模式(Proxy)的变体

    在这里插入图片描述

    防火墙代理

    内网通过代理穿透防火墙,实现对公网的访问。

    缓存代理

    比如:当请求图片文件等资源时,先到缓存代理取,如果取到资源则ok如果取不到资源,再到公网或者数据库取,然后缓存。

    远程代理

    远程对象的本地代表,通过它可以把远程对象当本地对象来调用。远程代理通过网络和真正的远程对象沟通信息。

    同步代理

    主要使用在多线程编程中,完成多线程间同步工作

    学习来源:B站韩顺平

  • 相关阅读:
    搞水产的人都笑了,智慧水产养殖水质监测解决方案
    项目型ERP系统哪家做得好?
    2022年天猫8月份有什么大的活动?
    (仿牛客社区项目)Java开发笔记7.8:将文件上传至服务器
    微信自动化推送天气预报信息教程【Python版源代码】
    InnoDB和MyISAM的区别
    Springboot实现ENC加密
    c++数据处理----图像修补:cv::inpaint()
    前端对用户名密码加密处理,后端解密
    cookies,sessionStorage 和 localStorage 的区别
  • 原文地址:https://blog.csdn.net/Susan003/article/details/126687565