本文介绍: 通过上面的代理代码我们可以看出代理模式的特点,代理类接受一个Subject接口对象,任何实现接口对象,都可以通过代理类进行代理,增加了通用性。但是也有缺点,每一个代理类都必须实现一遍委托类(也就是realsubject)的接口,如果接口增加方法,则代理类也必须跟着修改。从UML图中,可以看出代理类与真正实现的类都是继承抽象主题类,这样的好处在于代理类可以与实际的类有相同方法可以保证客户端使用透明性。这样做的好处是:可以目标对象实现的基础上,增强额外功能操作实现目标功能扩展

来和大家聊聊代理模式

代理模式

代理模式:即通过代理对象访问目标对象实现目标对象方法。这样做的好处是:可以在目标对象实现的基础上,增强额外功能操作,实现对目标功能的扩展

这涉及到一个编程思想:不要随意去修改别人已经写好的代码或者方法(有坑)。如果需要修改可以通过代理模式实现

代理模式通常有三种实现写法静态代理、动态代理、Cglib代理

代理模式的UML图

在这里插入图片描述

从UML图中,可以看出代理类与真正实现的类都是继承抽象主题类,这样的好处在于代理类可以与实际的类有相同方法,可以保证客户端使用透明性。

1、静态代理

我们先看针对上面UML实现的例子,再看静态代理的特点。
Subject接口的实现

public interface Subject {
    void visit();
}

实现了Subject接口两个类:

public class RealSubject implements Subject {

    private String name = "byhieg";
    @Override
    public void visit() {
        System.out.println(name);
    }
}
public class ProxySubject implements Subject{

    private Subject subject;

    public ProxySubject(Subject subject) {
        this.subject = subject;
    }

    @Override
    public void visit() {
        subject.visit();
    }
}

具体调用如下

public class Client {

    public static void main(String[] args) {
        ProxySubject subject = new ProxySubject(new RealSubject());
        subject.visit();
    }
}

通过上面的代理代码,我们可以看出代理模式的特点,代理类接受一个Subject接口的对象,任何实现该接口的对象,都可以通过代理类进行代理,增加了通用性。但是也有缺点,每一个代理类都必须实现一遍委托类(也就是realsubject)的接口,如果接口增加方法,则代理类也必须跟着修改。其次,代理类每一个接口对象对应一个委托对象,如果委托对象非常多,则静态代理类就非常臃肿,难以胜任。

2、动态代理

动态代理有别于静态代理,是根据代理的对象,动态创建代理类。这样,就可以避免静态代理中代理类接口过多的问题动态代理是实现方式,是通过反射来实现的,借助Java自带java.lang.reflect.Proxy,通过固定规则生成
步骤如下

编写一个委托类的接口,即静态代理的(Subject接口)
实现一个真正的委托类,即静态代理的(RealSubject类)
创建一个动态代理类,实现InvocationHandler接口,并重写invoke方法
测试类中生成动态代理的对象。
第一二步骤,和静态代理一样,不过说了。第三步,代码如下

public class DynamicProxy implements InvocationHandler {
    private Object object;
    public DynamicProxy(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(object, args);
        return result;
    }
}

第四步,创建动态代理的对象

Subject realSubject = new RealSubject();
DynamicProxy proxy = new DynamicProxy(realSubject);
ClassLoader classLoader = realSubject.getClass().getClassLoader();
Subject subject = (Subject) Proxy.newProxyInstance(classLoader, new  Class[]{Subject.class}, proxy);
subject.visit();

创建动态代理的对象,需要借助Proxy.newProxyInstance。该方法的三个参数分别是:

ClassLoader loader表示当前使用到的appClassloaderClass<?&gt;[] interfaces表示目标对象实现的一组接口。
InvocationHandler h表示当前InvocationHandler实现实例对象。
jdk自带动态代理

java.lang.reflect.Proxy

java.lang.reflect.InvocationHandler(处理器接口)

3、Cglib代理

要实现Cglib代理,必须引入cglib.jar 包,由于Springcore包中已经包含cglib功能,且大部分Java项目引入spring 相关jar包,这边使用springcglib讲解。(他俩实现方式都是一样的)

public class CglibProxy implements MethodInterceptor {
    //目标对象
    private Object obj;
    public CglibProxy(Object obj){
        this.obj=obj;
    }
 
    //给目标对象创建一个代理对象
    public Object getProxyInstance(){
        //1.工具
        Enhancer en = new Enhancer();
        //2.设置父类
        en.setSuperclass(obj.getClass());
        //3.设置回调函数
        en.setCallback(this);
        //4.创建子类(代理对象)
        return en.create();
    }
 
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("CglibProxy--------->");
        return method.invoke(obj,objects);
    }
}

说明:可以看出,Cglib代理模式实现不需要目标对象一定实现接口,故目标对象如果没有实现接口,可以使用cglib代理模式。其实Spring的代理模式也是这么实现的。

原文地址:https://blog.csdn.net/weixin_44797327/article/details/134723434

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_42646.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注