首页 > 其他分享 >代理模式

代理模式

时间:2024-08-15 19:39:47浏览次数:7  
标签:代理 接口 InvocationHandler 模式 new 动态 public

专业的解释:代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。简单的说就是,我们在访问实际对象时,是通过代理对象来访问的,代理模式就是在访问实际对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途。

通俗的话讲,就是代理类和被代理类拥有/实现了相同的接口类,并且代理类中持有被代理类的实例对象,被代理类通过代理类来调用自己的方法,并且可以在调用自己方法前后做一些事情。

代理模式又分为静态代理和动态代理,静态代理需要自己编写代理类,并且一个代理类对应一个被代理类,代码繁琐冗余,这里不做多余介绍。

动态代理则是指代理类在程序运行时才被创建的代理模式,动态代理常用的有两种 JDK动态代理、 CGLib动态代理

JDK动态代理

JDK动态代理两个核心类:Proxy类 和 InvocationHandler接口 都位于java.lang.reflect包下
创建动态代理对象的步骤:

1、创建一个InvocationHandler对象(创建一个与代理对象相关联的InvocationHandler)
2、使用Proxy类的getProxyClass静态方法生成一个动态代理类
3、获得stuProxyClass 中一个带InvocationHandler参数的构造器constructor
4、通过构造器constructor来创建一个动态实例stuProxy
public interface ActionIng {

    /**
     * 执行动作
     */
    void doAction();
}

@Data
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class StudentIng implements ActionIng {

    private String name;

    @Override
    public void doAction() {
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            System.out.println("嘀嘀嘀嘀哒哒~~~~~~~");
        }
        System.out.println(name + "正在上课");
    }
}

public class StudentInvocationHandler<T> implements InvocationHandler {

    T target;

    public StudentInvocationHandler(T target) {
        this.target = target;
    }


    /**
     * @param proxy 是在代理实例上调用该方法的代理实例
     * @param method 是在代理实例上调用的接口方法对应的{@code method}实例。{@code Method}对象的声明类将是该方法被声明的接口,该接口可能是代理类继承该方法所通过的代理接口的超接口。
     * @param args 一个对象数组,包含在代理实例上的方法调用中传递的参数值,或者如果接口方法不接受参数,则{@code null}。基本类型的参数被包装在适当的基本包装器类的实例中,例如{@code java.lang。Integer}或{@code java.lang.Boolean}。
     * @return @throw Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理执行" + method.getName() + "方法");
        // 其他操作
        try {
            Thread.sleep(2000);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return method.invoke(target, args);
    }
}


public class StaticProxy {

    @Test
    public void testDynamicProxy() {
        StudentIng studentIng = new StudentIng("宋昕冉");
        InvocationHandler invocationHandler = new StudentInvocationHandler<ActionIng>(studentIng);
        ActionIng proxyInstance = (ActionIng) Proxy.newProxyInstance(ActionIng.class.getClassLoader(), new Class<?>[]{ActionIng.class}, invocationHandler);
        proxyInstance.doAction();
    }

}

    JDK1.8 Proxy中的newProxyInstance()方法
    @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        Objects.requireNonNull(h);

        final Class<?>[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        /*
         * Look up or generate the designated proxy class.
         */
        Class<?> cl = getProxyClass0(loader, intfs);

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }

            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            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);
        }
    }

JDK动态代理为什么只能代理接口,因为生成的代理类$Proxy0 extends Proxy implements 代理接口,代理类继承了Proxy类,Java的继承机制(单继承)注定了JDK动态代理只能代理接口。

标签:代理,接口,InvocationHandler,模式,new,动态,public
From: https://www.cnblogs.com/kris-cbl/p/18359723

相关文章

  • 1289、仿真-51单片机垃圾分类处理电机控制手自动模式蜂鸣器报警设计
    毕设帮助、开题指导、技术解答(有偿)见文末。目录一、设计功能二、Proteus仿真三、程序源码四、资料包括一、设计功能1、单片机型号:STC89C52/51、AT89C52/51、AT89S52/51都可通用。2、分为手动模式和自动模式,通过按键“模式”切换。 3、当在手动模式下,按下......
  • 设计模式实战:内容管理系统的设计与实现
    系统功能需求内容创建:支持多种内容类型的创建,如文章、页面、媒体等。内容管理:提供灵活的管理策略,如按时间发布、按用户分组显示等。内容发布:根据不同的策略发布内容,如即时发布、定时发布等。设计分析建造者模式建造者模式用于创建复杂对象,通过逐步构建内容对象的各......
  • UE4利用委托实现观察者模式
    应用场景当游戏运行过程中,当一个MainActor某个行为的发生会对其他多个object产生影响时可以采用观察者模式,这样可以避免MainActor与其他object发生强耦合关系。如果不采用观察者模式,可能的做法是将object加入到MainActor的行为方法中,如果有多个object那么该方法将显得非常复杂。......
  • 设计模式(单例模式)
    概念单例模式(SingletonPattern)是指确保一个类在一个容器下只有一个实例存在,并提供一个全局访问点。单例模式最大的特点就是构造方法私有化。通常情况下,可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的方法就是让类自身负责保存它的唯一实例。......
  • 基于Nexus实现配置阿里云代理仓库过程解析
    基于Nexus实现配置阿里云代理仓库过程解析更新时间:2020年07月09日09:19:07  作者:咔咔kk 这篇文章主要介绍了基于Nexus实现配置阿里云代理仓库过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下Nexus默认远程仓......
  • 面试官:JDK中都用了哪些设计模式?
    设计模式是前辈们经过实践验证总结的解决方案,帮助我们构建出更具可维护性、可扩展性和可读性的代码。当然,在面试的过程中,也会或多或少的被问到。那么今天,我们就来看一道设计模式中的常见面试问题:JDK中都用了哪些设计模式?我按照大家比较熟悉且好理解的方式,把JDK中使用的设计模......
  • 解决 Docker CE 在无根模式(rootless)下无法通过 IPv6 拉取映像的问题
    折腾一天快把我逼疯了本来Docker对IPv6的支持就不好,再来个rootless,雪上加霜首先,我们要区分DockerEngine和里面的Image。拉取映像是DockerEngine在工作,也就是那个Daemon本身,而不是某个container或image。RootlessDocker使用RootlessKit来管理用户命名......
  • 超低功耗模式在合宙模组中的应用与配置
    随着物联网技术的飞速发展,设备功耗成为影响系统稳定性和续航能力的重要因素。合宙科技推出的多款模组,如Air780E&600E(EC618平台)、780EP系列(EC718平台)、以及780EL_780ET_700EL_700ET系列(EC716S平台),均支持超低功耗模式,以满足不同应用场景下的节能需求。本文将详细介绍两种主要的低......
  • 设计模式的7大基本原则
    设计模式是解决问题的经验总结,是软件开发中常用的一种设计思想和方法。在软件开发过程中,遵循设计模式可以提高代码的可重用性、可维护性和可扩展性。设计模式的基本原则是软件开发过程中的指导方针,它们是在解决问题时需要遵循的基本原则。本文将介绍设计模式的7大基本原则,......
  • VMware中的三种网络模式
    VMware中的三种网络模式介绍VMware提供了三种网络工作模式,分别是Bridged(桥接模式)、NAT(网络地址转换模式)*和*Host-Only(仅主机模式)。当VMware软件安装完成之后,会在电脑上虚拟出三块虚拟交换机和两块虚拟网卡。VMnet0:用于虚拟桥接网络下的虚拟交换机。VMnet1:用于虚拟Host-Onl......