设计模式 -- 代理模式

版权声明:转载原创博客请附上原文链接 https://blog.csdn.net/weixin_43495590/article/details/89156006

一:概述

代理模式分为静态代理与动态代理,动态代理相对于静态代理可以更加灵活进行处理,不需要逐个方法进行中转。静态代理过于简单不在本文讨论范围,本文着重与讨论JDK自带的Proxy代理与Cglib代理应用实现

二:JDK动态代理

2.1 简单应用
  1. 被代理类实现接口,被代理类必须实现接口
  2. 必须实现接口是JDK动态代理一个弊端也是和Cglib主要的区别
  3. 实现接口作用在于Proxy进行组装时需要这个接口的Class对象
public interface PublicInterface {
    void testMethod();
}
public class TrueImplement implements  PublicInterface{
    @Override
    public void testMethod() {
        System.out.println("真正处理实现");
    }
}
  1. 实现InvocationHandler接口重写invoke()方法,方法中定义代理方法执行逻辑
  2. invoke()参数proxy代指代理对象、method代指代理方法、args代指方法参数
  3. Proxy类的newProxyInstance()根据类加载器、代理对象实现接口Class进行代理对象组装
  4. newProxyInstancee()第三个参数InvocationHandler对象用于Proxy对象组装时反射操作构造函数的实参
public class ProxyImplement implements InvocationHandler {

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("进入方法");
        method.invoke(new TestImplement(),args);
        System.out.println("结束方法");
        return null;
    }

    public <T> T getProxy(){
        return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                   PublicInterface.class.getInterfaces(),
                   this);
    }
}
public class Test {
    
    public static void main(String[] args) {
        ProxyImplement pi = new ProxyImplement();
        PublicInterface proxy = pi.getProxy();
        proxy.testMethod();
    }

}
2.2 源码解析

newProxyInstance()作为入口查看,里面做的操作都是在获取到Proxy类Class对象后构造函数获取权限判断修改对象实例化等操作

    private static final Class<?>[] constructorParams =
        { InvocationHandler.class };
        
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
    	// 检查第三个参数InvocationHandler实例是否为空
        Objects.requireNonNull(h);

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

        // 获取proxy代理类
        Class<?> cl = getProxyClass0(loader, intfs);

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

			// 获取Proxy类构造函数
            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;
                    }
                });
            }
			
			// 返回创建Proxy实例
            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);
        }
    }

再看newProxyInstance()中获取Proxy类的Class对象方法getProxyClass0(),这里面进行了两个操作。对接口长度限制调用WeakCache类get()

    private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
        // 文件字节码中的固定规定不能超过65535字节
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }

		// 给定接口如果存在将返回储存副本
		// 如果不存在则使用ProxyClassFactory创建
        return proxyClassCache.get(loader, interfaces);
    }

截取get()中最重要一行代码,紧接着追入apply()查看。apply()位于Proxy类的内部类ProxyClassFactory

 value = Objects.requireNonNull(valueFactory.apply(key, parameter));
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

    Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
    for (Class<?> intf : interfaces) {
        Class<?> interfaceClass = null;
        try {
            //通过类加载器加载class到内存
            interfaceClass = Class.forName(intf.getName(), false, loader);
        } catch (ClassNotFoundException e) {
        }
        if (interfaceClass != intf) {
            throw new IllegalArgumentException(
                intf + " is not visible from class loader");
        }
        //判断class是否接口
        if (!interfaceClass.isInterface()) {
            throw new IllegalArgumentException(
                interfaceClass.getName() + " is not an interface");
        }
        //没有重复定义的接口
        if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
            throw new IllegalArgumentException(
                "repeated interface: " + interfaceClass.getName());
        }
    }

    //proxy Class所在包
    String proxyPkg = null; 
    int accessFlags = Modifier.PUBLIC | Modifier.FINAL;

    //判断非public类是否在同一包下
    for (Class<?> intf : interfaces) {
        int flags = intf.getModifiers();
        if (!Modifier.isPublic(flags)) {
            accessFlags = Modifier.FINAL;
            String name = intf.getName();
            int n = name.lastIndexOf('.');
            String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
            if (proxyPkg == null) {
                proxyPkg = pkg;
            } else if (!pkg.equals(proxyPkg)) {
                throw new IllegalArgumentException(
                    "non-public interfaces from different packages");
            }
        }
    }

    if (proxyPkg == null) {
        // 等价于com.sun.proxy.
        proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
    }

    long num = nextUniqueNumber.getAndIncrement();
    //proxyPkg == null时,等价于com.sun.proxy.$proxy0,num会根据动态代理类的数量增加
    String proxyName = proxyPkg + proxyClassNamePrefix + num;

    //得到生成的字节码
    byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
        proxyName, interfaces, accessFlags);
    try {
        //本地方法调用
        return defineClass0(loader, proxyName,
                            proxyClassFile, 0, proxyClassFile.length);
    } catch (ClassFormatError e) {
        throw new IllegalArgumentException(e.toString());
    }
}

2.3 反编译代理生成类
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

import com.zsl.TrueImplement;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class CustomProxy extends Proxy implements TrueImplement {
    private static Method m1;
    private static Method m8;
    private static Method m2;
    private static Method m6;
    private static Method m5;
    private static Method m3;
    private static Method m7;
    private static Method m9;
    private static Method m0;
    private static Method m4;

    public CustomProxy(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 void notify() throws  {
        try {
            super.h.invoke(this, m8, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    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 wait(long var1) throws InterruptedException {
        try {
            super.h.invoke(this, m6, new Object[]{var1});
        } catch (RuntimeException | InterruptedException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

    public final void wait(long var1, int var3) throws InterruptedException {
        try {
            super.h.invoke(this, m5, new Object[]{var1, var3});
        } catch (RuntimeException | InterruptedException | Error var5) {
            throw var5;
        } catch (Throwable var6) {
            throw new UndeclaredThrowableException(var6);
        }
    }
	
	// 这个方法对invoke()的调用才是代理核心
    public final void testMethod() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

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

    public final void notifyAll() throws  {
        try {
            super.h.invoke(this, m9, (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);
        }
    }

    public final void wait() throws InterruptedException {
        try {
            super.h.invoke(this, m4, (Object[])null);
        } catch (RuntimeException | InterruptedException | 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"));
            m8 = Class.forName("com.zsl.TrueImplement").getMethod("notify");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m6 = Class.forName("com.zsl.TrueImplement").getMethod("wait", Long.TYPE);
            m5 = Class.forName("com.zsl.TrueImplement").getMethod("wait", Long.TYPE, Integer.TYPE);
            m3 = Class.forName("com.zsl.TrueImplement").getMethod("testMethod");
            m7 = Class.forName("com.zsl.TrueImplement").getMethod("getClass");
            m9 = Class.forName("com.zsl.TrueImplement").getMethod("notifyAll");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            m4 = Class.forName("com.zsl.TrueImplement").getMethod("wait");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

三:Cglib

3.1 简单应用
  1. 实现MethodInterceptor接口,重写intercept(),该方法类似于拦截实现
  2. 代理对象实例化依赖Enhancer类,setSuperClass()参数为被代理类Class对象,setCallback()指代调用interceptor()的类,create()创建代理对象
  3. 源码查看可以从create()作为入口开始,没看懂留待以后补充
public class CglibImplement implements MethodInterceptor {

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("代理之前");
        methodProxy.invokeSuper(o,args);
        System.out.println("代理之后");
        return null;
    }

    @SuppressWarnings("unchecked")
    public <T> T getProxy(Class<T> clazz) {
        Enhancer en = new Enhancer();
        //进行代理
        en.setSuperclass(clazz);
        en.setCallback(this);
        //生成代理实例
        return (T)en.create();
    }
}
    public static void main(String[] args) {
        PublicInterface ci = new CglibImplement().getProxy(TrueImplement.class);
        ci.testMethod();
    }
3.2 JDK与Cglib区别
  1. JDK依赖于接口实现
  2. Cglib依赖于继承实现
  3. JDK采用原生反射实现,代理类生成效率优于Cglib
  4. Cglib方法代理的处理效率上高于JDK

猜你喜欢

转载自blog.csdn.net/weixin_43495590/article/details/89156006