设计模式中的动态代理模式

Posted Fly博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式中的动态代理模式相关的知识,希望对你有一定的参考价值。

动态代理模式可以增强方法,在不改变原来方法的基础上添加我们自己的逻辑代码,例如添加日志,权限等。

public interface Sell {


    void sell();


    void ad();
}


public class Vendor implements Sell {
    @Override
    public void sell() {
        System.out.println("Shop sell goods");
    }

    @Override
    public void ad() {
        System.out.println("Shop advert goods");
    }
}


public interface InvocationHandler {

    Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}



public class LogHandler implements java.lang.reflect.InvocationHandler {
    Object target;  // 被代理的对象,实际的方法执行者

    public LogHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(target, args);  // 调用 target 的 method 方法
        after();
        return result;  // 返回方法的执行结果
    }
    // 调用invoke方法之前执行
    private void before() {
        System.out.println(String.format("log start time [%s] ", new Date()));
    }
    // 调用invoke方法之后执行
    private void after() {
        System.out.println(String.format("log end time [%s] ", new Date()));
    }
}



public class DynamicProxyMain {

    public static void main(String[] args) {
        // 创建中介类实例
        LogHandler logHandler = new LogHandler(new Vendor());
        // 设置该变量可以保存动态代理类,默认名称$Proxy0.class
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

        // 获取代理类实例Sell

        Sell sell = (Sell) (Proxy.newProxyInstance(Vendor.class.getClassLoader(), new Class[]{Sell.class}, logHandler));
        // 通过代理类对象调用代理类方法,实际上会转到invoke方法调用
        sell.sell();
//        sell.ad();
    }
}

 

注意:动态代理中invoke方法中的proxy对象其实是$Proxy0,这个才是真正的代理类,main方法中sell.sell()其实调用的是$Proxy0中的sell()方法。

sell()方法又调用的是LogHandler中的invoke方法,所以这就是为什么调用方法时为什么会调用invoke()方法。

$Proxy0类如下:

 

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.sun.proxy;

import com.jjy.modules.model.stock.Sell;
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 Sell {
    private static Method m1;
    private static Method m2;
    private static Method m4;
    private static Method m3;
    private static Method m0;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

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

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void ad() throws  {
        try {
            super.h.invoke(this, m4, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void sell() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m4 = Class.forName("com.jjy.modules.model.stock.Sell").getMethod("ad");
            m3 = Class.forName("com.jjy.modules.model.stock.Sell").getMethod("sell");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

 

以上是关于设计模式中的动态代理模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式中的动态代理模式

#yyds干货盘点# 设计模式之代理模式:动态代理

java中的动态代理

动态代理

设计模式 - 动态代理原理及模仿JDK Proxy 写一个属于自己的动态代理

设计模式之动态代理