前言

Github:https://github.com/HealerJean

博客:http://blog.healerjean.com

1、Proxy代理模式

1.1、解释

Proxy是代理人的意思,指的是代替别人进行工作,工作强度是有限的。当代理人无法完成的时候,就会去找本人去解决问题

代理提供的接口和原本的接口是一样的,代理模式的作用是不把实现直接暴露给client,而是通过代理这个层,代理能够做一些处理

使用场景 :在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。 为其他对象提供一种代理对象以控制对这个对象的访问

1.2、示例代码

在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。

1.2.1、买房子接口

public interface BuyHouse {

    void buyHosue();
}

1.2.1.1、买房子实现类

public class BuyHouseImpl implements BuyHouse {

    @Override
    public void buyHosue() {
        System.out.println("我要买房");
    }
}

1.2.2、静态代理

1.2.2.1、BuyHouseProxy实现 BuyHouse

会发现是委托模式,有点像适配器和装饰器吧

public class BuyHouseProxy implements BuyHouse {

    private BuyHouse buyHouse;

    public BuyHouseProxy(BuyHouse buyHouse) {
        this.buyHouse = buyHouse;
    }

    @Override
    public void buyHosue() {
        buyHouse.buyHosue();
    }

}

1.2.3、测试

public class ProxyTest {
    public static void main(String[] args) {
        BuyHouse buyHouse = new BuyHouseImpl();
        buyHouse.buyHosue();
        BuyHouseProxy buyHouseProxy = new BuyHouseProxy(buyHouse);
        buyHouseProxy.buyHosue();
    }
}

1.3、jdk动态代理

1.3.1、jdk动态代理控制器

public class DynamicProxyHandler implements InvocationHandler {

    private Object object;

    public DynamicProxyHandler(final 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;
    }
}

1.3.2、测试

public class DynamicProxyTest {

    public static void main(String[] args) {
        BuyHouse buyHouse = new BuyHouseImpl();
        System.out.println("buyHouse " + buyHouse.getClass().getName());

        DynamicProxyHandler handler = new DynamicProxyHandler(buyHouse);
        // 1、第一个参数 指定当前目标对象使用的类加载器
        // 2、第二个参数 指定目标对象实现的接口的类型 接口列表
        // 3、第三个参数 指定动态处理器,
        BuyHouse proxyBuyHouse = (BuyHouse) 
            Proxy.newProxyInstance(BuyHouse.class.getClassLoader(), 
                                   buyHouse.getClass().getInterfaces(), 
                                   handler);
        System.out.println("proxyBuyHouse :" + proxyBuyHouse.getClass().getName());
        proxyBuyHouse.buyHosue();

        byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy0", buyHouse.getClass().getInterfaces());
        String  code = IOUtils.toString(bytes, "utf-8");

        FileOutputStream fileOutputStream = new FileOutputStream("D:/study/HealerJean.github.io/_posts/1_设计模式/hlj-design-pattern/porxy.class");
        IOUtils.write(bytes, fileOutputStream);

    }

}

1.3.3、$Proxy0代理类

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

import com.hlj.moudle.design.D09避免浪费.D21Proxy代理模式.BuyHouse;
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 BuyHouse {
    private static Method m1;
    private static Method m2;
    private static Method m4;
    private static Method m0;
    private static Method m3;

    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 int countAdd(int var1) throws  {
        try {
            return (Integer)super.h.invoke(this, m4, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    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);
        }
    }

    public final void buyHosue() throws  {
        try {
            super.h.invoke(this, m3, (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.hlj.moudle.design.D09避免浪费.D21Proxy代理模式.BuyHouse").getMethod("countAdd", Integer.TYPE);
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            m3 = Class.forName("com.hlj.moudle.design.D09避免浪费.D21Proxy代理模式.BuyHouse").getMethod("buyHosue");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

1.3.3.1、源码解析

// 1、第一个参数 指定当前目标对象使用的类加载器
// 2、第二个参数 指定目标对象实现的接口的类型 接口列表
// 3、第三个参数 指定动态处理器,
BuyHouse proxyBuyHouse = (BuyHouse) Proxy.newProxyInstance(
    BuyHouse.class.getClassLoader(),
    buyHouse.getClass().getInterfaces(),
    handler);
public class Proxy implements java.io.Serializable {

    private static final long serialVersionUID = -2222568056686623797L;

    /** parameter types of a proxy class constructor */
    private static final Class<?>[] constructorParams =
    { InvocationHandler.class };

    protected InvocationHandler h;


    private Proxy() {
    }

    // 传入代理处理器,也就是我们自定义的那个 DynamicProxyHandler
    protected Proxy(InvocationHandler h) {
        Objects.requireNonNull(h);
        this.h = h;
    }


}

@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);
    }

    //获取通过接口生成 $Proxy0 代理类	
    Class<?> cl = getProxyClass0(loader, intfs);


    try {
        if (sm != null) {
            checkNewProxyPermission(Reflection.getCallerClass(), cl);
        }

        //获取有参构造器 参数为 InvocationHandler.class  (我们这是 DynamicProxyHandler )
        final Constructor<?> cons = cl.getConstructor(constructorParams);
        // h -》  DynamicProxyHandler对象
        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);
    }
}

1.3、CGLIB动态代理

1.3.1、动态代理类

public class CglibProxy implements MethodInterceptor {

    @SuppressWarnings("unchecked")
    public <T> T getInstance(Object target, Class<T> clazz) {
        //字节码加强器:用来创建动态代理类
        Enhancer enhancer = new Enhancer();
        //代理的目标对象
        enhancer.setSuperclass(target.getClass());
        //回调类,在代理类方法调用时会回调Callback类的intercept方法
        enhancer.setCallback(this);

        //创建代理类
        Object result = enhancer.create();
        return (T)result;
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        //调用目标类(父类)的方法
        Object result = proxy.invokeSuper(obj, args);
        return result;
    }

}

1.3.2、测试

public class CglibProxyTest {

    public static void main(String[] args){
        BuyHouseImpl buyHouse = new BuyHouseImpl();
        CglibProxy cglibProxy = new CglibProxy();
        BuyHouseImpl buyHouseCglibProxy =cglibProxy.getInstance(
            buyHouse,
            BuyHouseImpl.class);
        buyHouseCglibProxy.buyHosue();
    }
}