zoukankan      html  css  js  c++  java
  • 06、代理模式

    代理模式定义(Proxy):提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样就可以在不修改原目标对象的前提下,提供额外的操作功能,扩展目标对象的功能 

    一、静态代理

      常用于对原有业务逻辑的扩充,通过让代理类持有真实对象,然后再原有代码中调用代理类方法。

    公共接口:

    public interface Action {
    
          void doSomething();
    }
    public class RealObject implements Action{
        @Override
        public void doSomething() {
            System.out.println("真实设备操作.......");
        }
    }
    public class ProxyObject implements Action{
    
        private Action realObject;
    
        public ProxyObject(Action realObject){
            this.realObject = realObject;
        }
    
        @Override
        public void doSomething() {
            System.out.println("开启代理");
            realObject.doSomething();
        }
    }
    public class Client {
    
        public static void main(String []args){
    
    
            ProxyObject proxyObject = new ProxyObject(new RealObject());
            proxyObject.doSomething();
        }
    }

    静态代理比较简单,通过 proxy 持有真实对象的引用,并进行一层封装。

    静态代理的优缺点:

    优点:扩展原功能,不侵入原代码

    缺点:原对象多个方法需要代理时,导致 proxy 膨胀

    二、动态代理

      动态代理指在运行时动态生成代理类。即代理类的字节码将在运行时生成并载入当前代理的 ClassLoader 。 与静态代理处理类相比,动态代理有相当好处。

    动态代理类使用字节码动态生成加载技术,在运行时生成加载类。生成动态代理类的方法很多,如 jdk 自带的动态代理,cglib ,javassist 或者 ASM 库。cglib 和 javassist

    是高级的字节码生成库,性能比JDK 自带的动态代理好。ASM 是低级的字节码生成工具。

     方法一:使用 cglib 

      动态的生成一个子类,然后子类覆盖代理类中的方法,如果是 private 或者 final 修饰的方法,中则不会被重写

    cglib 是一个开源项目,代码托管在 github ,地址:https://github.com/cglib/cglib

     

     

     

     方法二、Jdk  自带的动态代理

    接口:

    public interface Subject {
        public int sellBooks();
    
        public String speak();
    }

    真实对象:

    public class RealSubject implements Subject{
        @Override
        public int sellBooks() {
            System.out.println("卖书");
            return 1 ;
        }
    
        @Override
        public String speak() {
            return null;
        }
    }

    处理器对象:

    public class MyInvocationHandler implements InvocationHandler{
        /**
         * 因为需要处理真实角色,所以要把真实角色传进来
         */
        Subject realSubject ;
    
        public MyInvocationHandler(Subject realSubject) {
            this.realSubject = realSubject;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("开启代理。。。。。");
            if(method.getName().equals("sellBooks")){
                int invoke = (int)method.invoke(realSubject,args);
                System.out.println("调用的是卖书的方法");
                return invoke ;
            }else {
                String string = (String)method.invoke(realSubject,args);
                System.out.println("调用的是说话的方法");
                return  string ;
            }
        }
    }

    测试端:

    public class Client {
    
        public static void main(String []args){
    
    
            Subject realSubject = new RealSubject();
    
            MyInvocationHandler myInvocationHandler = new MyInvocationHandler(realSubject);
    
            Subject proxyClass = (Subject) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Subject.class},myInvocationHandler);
    
            proxyClass.sellBooks();
    
            proxyClass.speak();
        }
    }

  • 相关阅读:
    [单链表]链表指针追赶问题
    二叉查找树与平衡二叉树
    二叉树的下一个结点
    fork进程函数总结
    《Effective C++》Item2:尽量以const,enum,inline替换#define
    Hash表的使用
    [数字]整数数字的算法
    算法题:找出整数数组中两个只出现一次的数字
    删除元素的操作
    [Reprinted] 使用Spring Data Redis操作Redis(一) 很全面
  • 原文地址:https://www.cnblogs.com/bytecodebuffer/p/10552237.html
Copyright © 2011-2022 走看看