代理模式

作者: 晓晓桑 | 来源:发表于2019-08-17 21:52 被阅读0次

概述

为其他对象提供一种代理,用以控制对这个对象对访问

分类

静态代理、动态代理

静态代理

image.png
AbstractObject接口
public interface IAbstract {
    public void operation();
}
ProxyObject 代理类,实现接口

在代理类里面对被代理类调用operation()方法前后可以加更多逻辑限制。
例如:在开发过程中,想要对原有的方法做改进,方法一:直接改原来的方法,方法二:调用代理类,对产生的结果进行控制,这就是代理模式

//代理类
public class ProxyI implements IAbstract {

    //被代理类对象
    RealI mRealObject;

    public ProxyI(RealI mRealObject) {
        this.mRealObject = mRealObject;
    }

    @Override
    public void operation() {
        if (mRealObject == null) {
            mRealObject = new RealI();
        }
        //在代理类里面对被代理类调用operation()方法前后可以加更多逻辑限制。
        //例如:在开发过程中,想要对原有对方法做改进,方法一:直接改原来对方法,方法二:调用代理类,对产生对结果进行控制,这就是代理模式
        mRealObject.operation();
       System.out.println("ProxyI: operation()");

    }
}
被代理类,同样实现接口
//被代理类
public class RealI implements IAbstract {

    @Override
    public void operation() {
          System.out.println("RealI: operation()");
    }
}
测试类
public class ProxyTest {
    public static void main(String[] args) {
        //
        RealI realObject = new RealI();
        ProxyI father = new ProxyI(realObject);
        father.operation();
    }
}

运行结果:


image.png

动态代理

什么是动态代理?
代理类是在程序运行时创建的代理方式,代理类他不是在java代码中定义的,而是程序运行时,根据我们在java代码中的配置动态生成的。相比于静态代理,他可以很方便的对代理类的函数进行统一处理,而不用频繁修改每一个代理类的函数(根据你的业务逻辑)

  • 无侵入式扩展代码: 不修改原来对代码情况下,增强方法

jdk动态代理

动态代理的实现:

所要实现的接口

//所要实现的接口
public interface ISubject {
    void shopping();
}

被代理类

//被代理类
public class Man implements ISubject {
    @Override
    public void shopping() {
        System.out.println("Man :Man Shopping");
    }
}

代理类

//代理类

//动态代理的代理类 必须要实现InvocationHandler接口,并且每个代理类的实例都关联到了一个handler。
//代理对象调用程序的时候,一定要实现的接口,
// 当通过代理对象调用方法的时候,
// 这个方法就会把他指派到InvocationHandler的invoke(Object proxy, Method method, Object[] args)上
public class Proxy implements InvocationHandler {

    private Object target;//要代理的真实对象

    public Proxy(Object target) {
        this.target = target;
    }

    //Object proxy:  指代我们所代理的那个真实对象(真实对象就是被代理对象)
    //Method method:  指代的是我们所要调用真实对象的某个方法的Method对象
    //Object[] args:   指代的是调用真实对象某个方法时接受的所有参数
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("proxy :" + proxy.getClass().getName());
        System.out.println("proxy :method: " + method);

        //在代理真实对象前我们可以添加一些自己的操作
        System.out.println("proxy :在代理真实对象前我们可以添加一些自己的操作");

        //当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
        method.invoke(target, args);

        //在代理真实对象后我们也可以添加一些自己的操作
        System.out.println("proxy :在代理真实对象后我们也可以添加一些自己的操作");
        return null;
    }
}

实现接口方法

public class ProxyTest {
    public static void main(String[] args) {
        //被代理者
        ISubject man = new Man();
        //代理者
        Proxy proxy = new Proxy(man);

        //首先我们解释一下为什么我们这里可以将其转化为Subject类型的对象?
        //原因就是在newProxyInstance这个方法的第二个参数上,我们给这个代理对象proxy提供了一组什么接口,那么我这个代理对象proxy就会实现了这组接口,
        //这个时候我们当然可以将这个代理对象强制类型转化为这组接口中的任意一个,因为这里的接口是ISubject类型,所以就可以将其转化为ISubject类型了。
        ISubject subject = (ISubject) java.lang.reflect.Proxy
                .newProxyInstance(man.getClass().getClassLoader(), man.getClass().getInterfaces(), proxy);

        System.out.println("ProxyTest " + subject.getClass().getName());
        //代理对象调用接口方法时,会关联到InvocationHandler到invoke中的方法去执行
        subject.shopping();
    }
}

InvocationHandler类源码

public interface InvocationHandler {
    //Object proxy:  指代我们所代理的那个真实对象(真实对象就是被代理对象)
    //Method method:  指代的是我们所要调用真实对象的某个方法的Method对象
    //Object[] args:   指代的是调用真实对象某个方法时接受的所有参数
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}
  • 在动态代理中,每个代理类的对象都会关联一个表示内部处理逻辑都InvocationHandler接口的实现,当我们调用了代理对象所代理的接口中的方法的时候,这个方法的调用就会被转发到InvocationHandler这个接口的 invoke 方法来进行调用。
  • invoke方法的参数可以获取:
  • 所代理的真实对象(被代理对象)、
  • 所要调用的真实对象的方法、
  • 所要调用的真实对象的方法的参数
  • invoke()返回值返回给我们使用者

newProxyInstance

java.lang.reflect.Proxy作用是动态创建一个对象的类,他提供了很多方法我们用的最多的就是 newProxyInstance 这个方法

 public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
            throws IllegalArgumentException {
    Objects.requireNonNull(h);
        final Class<?>[] intfs = interfaces.clone();
 /*
         * Look up or generate the designated proxy class.
         */
        Class<?> cl = getProxyClass0(loader, intfs);
 try {
 final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
 cons.setAccessible(true);
   }
            return cons.newInstance(new Object[]{h});
        } catch (IllegalAccessException | InstantiationException e) {
            throw new InternalError(e.toString(), e);
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new InternalError(t.toString(), t);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
  }
动态代理总结

调用java.lang.reflect.Proxy类的newProxyInstanced(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)方法,他会根据我们传递来的class对象,生成一个代理类,每当代理类执行接口方法的时候,就会调用InvocationHandler里面的invoke(Object proxy, Method method, Object[] args)方法,在invoke方法中可以执行想要的操作,这就是动态代理。
注意⚠️:

  • 代理类他不是在java代码中手动码的代码,而是程序运行时,根据我们在java代码中的配置动态生成的
  • 代理类实现InvocationHandler接口
  • 反射包中的java.lang.reflect.Proxy类newProxyInstance()创建动态代理
  • 动态代理与静态代理最大的不同:动态代理代理类不需要手动生成,是运行时候动态生成,根据我们在java代码中的配置在运行期动态生成的,这个动态生成的代理类,已经实现了代理中的相关接口。

CFLIB动态代理

CGLIB(Code Generation Library)是一个开源项目!是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。Hibernate用它来实现PO(Persistent Object 持久化对象)字节码的动态生成。详解有待更新。

相关文章

  • 设计模式

    单例模式 模板方法模式 工厂模式 代理模式 静态代理 JDK动态代理

  • 设计模式

    单例模式 代理模式 静态代理 jdk动态代理 cglib动态代理 工厂模式 适配器模式 建造者模式 观察者模式

  • kube-proxy的3种模式

    userspace代理模式 iptables代理模式 IPVS代理模式 https://kubernetes.io...

  • 第4章 结构型模式-代理模式

    一、代理模式简介 二、代理模式3个角色 三、代理模式的优点 四、代理模式的实例(游戏代练)

  • 理解代理模式

    原创博客地址 简介 代理模式,也叫做委托模式,分为:静态代理动态代理 代理模式也是平时比较常用的设计模式之一,代理...

  • 结构型 代理模式(文末有项目连接)

    1:什么是代理模式 2:没用代理模式时的实例 3:使用代理模式将其解耦(静态代理) 3:使用代理模式将其解耦(动态...

  • 设计模式-动态代理模式

    之前介绍了代理模式,大家也都了解了代理模式,不过之前介绍的代理模式是静态代理,静态代理什么意思?静态代理指的是代理...

  • 代理模式

    一、什么是代理模式 代理模式(Proxy pattern):代理模式又叫委托模式,是为某个对象提供一个代理对象,并...

  • 设计模式之代理模式(Proxy模式)

    代理模式的引入 代理模式的实例程序 代理模式的分析 代理模式的引入 Proxy是代理人的意思,指的是代替别人进行工...

  • Java设计模式之代理模式

    Java设计模式之代理模式 代理模式 静态代理 动态代理 为什么需要代理 通过代理,我们能够不用知道委托人是谁,而...

网友评论

    本文标题:代理模式

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