首页 > 其他分享 >设计模式之代理模式

设计模式之代理模式

时间:2023-02-25 12:11:51浏览次数:41  
标签:lang sell java 代理 模式 proxy throwable 设计模式 public

  • 简介
    在某些场景下,我们需要增强某个对象的使用,比如我们在执行某个方法前加输出一条日志,但是我们不能直接改这个类,我们可以用代理对象来实现这个功能

  • 模式应用
    Spring AOP/日志/事务 等

  • 类图

  • 源码实现
    静态代理

jdk动态代理

点击查看代码
package designpattern.proxy.jdk_proxy;

public interface SellInterface {
    void sell();
}

点击查看代码
package designpattern.proxy.jdk_proxy;

public class Sell implements SellInterface {


    @Override
    public void sell() {
        System.out.println("sell");
    }
}

点击查看代码
package designpattern.proxy.jdk_proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Client {

    public static void main(String[] args) {
        Sell sell = new Sell();
//        Proxy.newProxyInstance(Sell.class.getClassLoader(),Sell.class.getInterfaces(),);
        SellInterface obj = (SellInterface)Proxy.newProxyInstance(sell.getClass().getClassLoader(), sell.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("invoke...");
                return method.invoke(sell,args);
            }
        });
        System.out.println(obj.getClass());
        obj.sell();

//        System.out.println(Sell.class == sell.getClass());

        while (true){

        }

    }
}

使用arthas工具查看动态代理类的源码

选择进程7

用sc命令查询jvm已加载的类

我们程序Client后运行输出的代理类名称是 com.sun.proxy.$Proxy0,在这个地方

用jad命令反编译,得到源码

源码如下:

点击查看代码
/*
 * Decompiled with CFR.
 *
 * Could not load the following classes:
 *  designpattern.proxy.jdk_proxy.SellInterface
 */
package com.sun.proxy;

import designpattern.proxy.jdk_proxy.SellInterface;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0
extends Proxy
implements SellInterface {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $Proxy0(InvocationHandler invocationHandler) {
        super(invocationHandler);
    }

    public final boolean equals(Object object) {
        try {
            return (Boolean)this.h.invoke(this, m1, new Object[]{object});
        }
        catch (Error | RuntimeException throwable) {
            throw throwable;
        }
        catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    public final String toString() {
        try {
            return (String)this.h.invoke(this, m2, null);
        }
        catch (Error | RuntimeException throwable) {
            throw throwable;
        }
        catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    public final void sell() {
        try {
            this.h.invoke(this, m3, null);
            return;
        }
        catch (Error | RuntimeException throwable) {
            throw throwable;
        }
        catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    public final int hashCode() {
        try {
            return (Integer)this.h.invoke(this, m0, null);
        }
        catch (Error | RuntimeException throwable) {
            throw throwable;
        }
        catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
            m3 = Class.forName("designpattern.proxy.jdk_proxy.SellInterface").getMethod("sell", new Class[0]);
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
            return;
        }
        catch (NoSuchMethodException noSuchMethodException) {
            throw new NoSuchMethodError(noSuchMethodException.getMessage());
        }
        catch (ClassNotFoundException classNotFoundException) {
            throw new NoClassDefFoundError(classNotFoundException.getMessage());
        }
    }
}

稍微整理下源码,把toString hashCode equals这些方法删掉

点击查看代码
/*
 * Decompiled with CFR.
 *
 * Could not load the following classes:
 *  designpattern.proxy.jdk_proxy.SellInterface
 */
package com.sun.proxy;

import designpattern.proxy.jdk_proxy.SellInterface;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0
extends Proxy
implements SellInterface {
    private static Method m3;

    public $Proxy0(InvocationHandler invocationHandler) {
        super(invocationHandler);
    }



    public final void sell() {
            this.h.invoke(this, m3, null);
            return;
    }


    static {
            m3 = Class.forName("designpattern.proxy.jdk_proxy.SellInterface").getMethod("sell", new Class[0]);
            return;
    }
}

可以看到,使用代理类执行sell 方法调用的是代理类对象内成员变量h的invoke方法,而这个h对象在我们创建代理对象的时候已经创建好了

标签:lang,sell,java,代理,模式,proxy,throwable,设计模式,public
From: https://www.cnblogs.com/jiaqirumeng/p/17154107.html

相关文章

  • java——spring boot集成RabbitMQ——topics模式——实现消费者
           ......
  • 设计模式(十五)-面向对象概念
    一、设计原则1、单一职责:设计目的单一的类。2、开放-封闭原则:对扩展开放,对修改关闭。3、里氏替换原则:子类可代替父类。4、依赖倒置:要依赖与接口,而不是具体实现,针对接口编程......
  • 6_代理模式下开发各种功能-1_多种参数传递问题
     1单个基本数据类型2多个基本数据类型3单个引用数据类型4map集合数据类型5多个引用数据类型接口packagecom.msb.mapper;importcom.msb.pojo.Emp;importorg.apache.ibati......
  • 6_代理模式下开发各种功能-1_多种参数传递问题
     1单个基本数据类型2多个基本数据类型3单个引用数据类型4map集合数据类型5多个引用数据类型接口packagecom.msb.mapper;importcom.msb.pojo.Emp;importorg.apache.ibati......
  • 18-桥接器模式
    18-桥接器模式概念桥接模式(Bridge),将抽象部分与它的实现部分分离,使它们都可以独立的变化,实现指的是抽象类和它的派生类用来实现自己的对象。实现系统可能有多角度分类,......
  • 6_代理模式下开发各种功能-1_多种参数传递问题
    ​ 1单个基本数据类型2多个基本数据类型3单个引用数据类型4map集合数据类型5多个引用数据类型接口packagecom.msb.mapper;importcom.msb.pojo.Emp;importorg......
  • 6_代理模式下开发各种功能-1_多种参数传递问题
    ​ 1单个基本数据类型2多个基本数据类型3单个引用数据类型4map集合数据类型5多个引用数据类型接口packagecom.msb.mapper;importcom.msb.pojo.Emp;importorg......
  • 学习中设计模式的总结
    首先要了解什么是设计模式呢?设计模式:可以简单的理解为两个字“经验”,就是码农们在各种需求中间,总结出来的一种最优的解法称之为设计模式;1,单例模式......
  • 设计模式-适配器与门面模式
    1.适配器模式#include<iostream>usingnamespacestd;classThreePhasePlug{public: voiddoThreePhasePlug(){ cout<<"threephase"<<endl; }};c......
  • Redis:六、哨兵模式
    @目录一、哨兵模式简介二、哨兵的搭建三、哨兵工作原理一、哨兵模式简介哨兵(Sentinel)是一个分布式系统,用于对主从结构中的每台服务器进行监控,当出现故障时通过投票机......