Open Source, Open Future!
  menu
107 文章
ღゝ◡╹)ノ❤️

代理模式

简介

为另一个对象提供代理,以便控制客户端对对象的访问。

使用场景
  • 远程代理: 与远程对象交互;
  • 虚拟代理:控制访问创建开销大的对象(先返回一个假引用);
  • 保护代理:控制对原始对象的访问;
  • 智能代理:当一个对象被引用时,提供一些额外的操作。
类图

image.png

角色说明:

  • ISubject:抽象角色,声明了目标对象和代理对象的共同接口;
  • RealSubject:真实角色,真正处理请求的目标对象;
  • Proxy:代理角色,内部持有目标对象的引用,所以可以随时调用目标对象。

静态代理

示例

接口:

public interface HelloService {
    void say(String message);
}

目标类:

public class HelloServiceImpl implements HelloService {

    @Override
    public void say(String message) {
        System.out.println(message);
    }
}

代理类:

public class HelloServiceProxy implements HelloService {

    private HelloService helloService;

    public HelloServiceProxy(HelloService helloService) {
        this.helloService = helloService;
    }

    @Override
    public void say(String message) {
        System.out.println("代理开始------------");
        helloService.say(message);
        System.out.println("代理结束------------");
    }
}

测试代码:

  public static void main(String[] args) {
        HelloService service = new HelloServiceProxy(new HelloServiceImpl());
        service.say("hello");
  }

输出结果:

代理开始------------
hello
代理结束------------

JDK动态代理

示例

接口:

public interface HelloService {
    void say(String message);
}

目标类:

public class HelloServiceImpl implements HelloService {

    @Override
    public void say(String message) {
        System.out.println(message);
    }
}

代理:

public class JdkProxyService implements InvocationHandler {

    private Object target;

    public JdkProxyService(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理开始------------");
        Object result = method.invoke(target, args);
        System.out.println("代理结束------------");
        return result;
    }

    public Object getProxy() {
        return Proxy.newProxyInstance(Thread.currentThread()
                .getContextClassLoader(), this.target.getClass()
                .getInterfaces(), this);
    }
}

测试代码:

 public static void main(String[] args) {
        HelloService service = (HelloService) new JdkProxyService(new HelloServiceImpl()).getProxy();
        service.say("hello");
        System.out.println(service.getClass());
 }

输出结果:

代理开始------------
hello
代理结束------------
class com.sun.proxy.$Proxy0

关键点有两处:

  • 实现InvocationHandler接口,重写invoke方法;
  • Proxy类的newProxyInstance方法生成代理;
  • 目标对象需要实现了接口。
原理

相关类汇总

说明
ProxyProxy
InvocationHandler
WeakCacheWeakCache
BiFunctionBiFunction
SupplierSupplier
ProxyGenerator

生成代理对象的逻辑在Proxy类的newProxyInstance方法中,newProxyInstance主要源码如下(省略了部分代码):

    @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException {
        final Class<?>[] intfs = interfaces.clone();
        // 获取代理类的 Class对象
        Class<?> cl = getProxyClass0(loader, intfs);
        // 获取代理类的构造器
        // constructorParams 是 Proxy 类的字段,值为数组: {InvocationHandler.class }
        final Constructor<?> cons = cl.getConstructor(constructorParams);
        final InvocationHandler ih = h;
        // 通过反射生成代理对象
        return cons.newInstance(new Object[]{h});
    }

getProxyClass0源码如下:

    private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) {
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }
        // If the proxy class defined by the given loader implementing
        // the given interfaces exists, this will simply return the cached copy;
        // otherwise, it will create the proxy class via the ProxyClassFactory
        return proxyClassCache.get(loader, interfaces);
    }

proxyClassCache缓存中获取代理类。

proxyClassCacheProxy类的字段,结构如下:

private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new Proxy.KeyFactory(), new Proxy.ProxyClassFactory());

继续跟进WeakCache类的get方法,源码如下:

源码
    public V get(K key, P parameter) {
        Objects.requireNonNull(parameter);

        expungeStaleEntries();

        Object cacheKey = CacheKey.valueOf(key, refQueue);

        // lazily install the 2nd level valuesMap for the particular cacheKey
        ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
        if (valuesMap == null) {
            ConcurrentMap<Object, Supplier<V>> oldValuesMap = map.putIfAbsent(cacheKey, valuesMap = new ConcurrentHashMap<>());
            if (oldValuesMap != null) {
                valuesMap = oldValuesMap;
            }
        }

        // create subKey and retrieve the possible Supplier<V> stored by that
        // subKey from valuesMap
        Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
        Supplier<V> supplier = valuesMap.get(subKey);
        Factory factory = null;

        while (true) {
            if (supplier != null) {
                // supplier might be a Factory or a CacheValue<V> instance
                V value = supplier.get();
                if (value != null) {
                    return value;
                }
            }
            // else no supplier in cache
            // or a supplier that returned null (could be a cleared CacheValue
            // or a Factory that wasn't successful in installing the CacheValue)

            // lazily construct a Factory
            if (factory == null) {
                factory = new WeakCache.Factory(key, parameter, subKey, valuesMap);
            }

            if (supplier == null) {
                supplier = valuesMap.putIfAbsent(subKey, factory);
                if (supplier == null) {
                    // successfully installed Factory
                    supplier = factory;
                }
                // else retry with winning supplier
            } else {
                if (valuesMap.replace(subKey, supplier, factory)) {
                    // successfully replaced
                    // cleared CacheEntry / unsuccessful Factory
                    // with our Factory
                    supplier = factory;
                } else {
                    // retry with current supplier
                    supplier = valuesMap.get(subKey);
                }
            }
        }
    }

get方法入参:key是类加载器,parameter是代理接口集合;

WeakCache类中有个字段map,结构如下:

    private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map = new ConcurrentHashMap<>();

可以把map看成是个二级缓存:

  • 第一级缓存的key为类加载器;
  • 第二级缓存的keysubKey,通过subKeyFactory.apply(key, parameter)可得到,所以是与代理接口集合关联的;
  • 第二级缓存的value为对应的代理;

主要流程:

  1. 以指定类加载器为key,去map中查询第二级缓存;
  2. 若找不到,则创建第二级缓存;
  3. subKeykey,去第二级缓存查询;
  4. 若找不到,则创建Factory类型(实现了Supplier<V>接口)的对象supplier,并放入缓存中;
  5. 调用supplier.get()返回代理类。

其中Factory类是WeakCache的内部类。

继续跟进Factory类的get方法,源码如下:

源码
        @Override
        public synchronized V get() { // serialize access
            // re-check
            Supplier<V> supplier = valuesMap.get(subKey);
            if (supplier != this) {
                // something changed while we were waiting:
                // might be that we were replaced by a CacheValue
                // or were removed because of failure ->
                // return null to signal WeakCache.get() to retry
                // the loop
                return null;
            }
            // else still us (supplier == this)

            // create new value
            V value = null;
            try {
                value = Objects.requireNonNull(valueFactory.apply(key, parameter));
            } finally {
                if (value == null) { // remove us on failure
                    valuesMap.remove(subKey, this);
                }
            }
            // the only path to reach here is with non-null value
            assert value != null;

            // wrap value with CacheValue (WeakReference)
            CacheValue<V> cacheValue = new CacheValue<>(value);

            // try replacing us with CacheValue (this should always succeed)
            if (valuesMap.replace(subKey, this, cacheValue)) {
                // put also in reverseMap
                reverseMap.put(cacheValue, Boolean.TRUE);
            } else {
                throw new AssertionError("Should not reach here");
            }

            // successfully replaced us with new CacheValue -> return the value
            // wrapped by it
            return value;
        }
    }

主要流程:

  1. subKeykey,在第二级缓存valuesMap中查询;
  2. 通过valueFactory.apply(key, parameter)得到value
  3. value封装成cacheValueCacheValue<V>类型);
  4. 用新值cacheValue覆盖第二级缓存中的旧值;
  5. 最后返回value

其中valueFactoryWeakCache类的字段,结构如下:

private final BiFunction<K, P, V> valueFactory;

值为new ProxyClassFactory()

ProxyClassFactory类的apply方法源码如下:

源码
        @Override
        public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
            for (Class<?> intf : interfaces) {
                /*
                 * Verify that the class loader resolves the name of this
                 * interface to the same Class object.
                 */
                Class<?> interfaceClass = null;
                try {
                    interfaceClass = Class.forName(intf.getName(), false, loader);
                } catch (ClassNotFoundException e) {
                }
                if (interfaceClass != intf) {
                    throw new IllegalArgumentException(
                        intf + " is not visible from class loader");
                }
                /*
                 * Verify that the Class object actually represents an
                 * interface.
                 */
                if (!interfaceClass.isInterface()) {
                    throw new IllegalArgumentException(
                        interfaceClass.getName() + " is not an interface");
                }
                /*
                 * Verify that this interface is not a duplicate.
                 */
                if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
                    throw new IllegalArgumentException(
                        "repeated interface: " + interfaceClass.getName());
                }
            }

            String proxyPkg = null;     // package to define proxy class in
            int accessFlags = Modifier.PUBLIC | Modifier.FINAL;

            /*
             * Record the package of a non-public proxy interface so that the
             * proxy class will be defined in the same package.  Verify that
             * all non-public proxy interfaces are in the same package.
             */
            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) {
                // if no non-public proxy interfaces, use com.sun.proxy package
                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
            }

            /*
             * Choose a name for the proxy class to generate.
             */
            long num = nextUniqueNumber.getAndIncrement();
            String proxyName = proxyPkg + proxyClassNamePrefix + num;

            /*
             * Generate the specified proxy class.
             */
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);
            try {
                return defineClass0(loader, proxyName,
                                    proxyClassFile, 0, proxyClassFile.length);
            } catch (ClassFormatError e) {
                /*
                 * A ClassFormatError here means that (barring bugs in the
                 * proxy class generation code) there was some other
                 * invalid aspect of the arguments supplied to the proxy
                 * class creation (such as virtual machine limitations
                 * exceeded).
                 */
                throw new IllegalArgumentException(e.toString());
            }
        }
    }

apply方法入参:key是类加载器,parameter是代理接口集合;

主要流程:

  1. 加载指定的所有的接口;
  2. 代理类名称拼接("com.sun.proxy.$Proxy" + num),num为递增的序号;
  3. 生成字节码:byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags);
  4. 加载字节码并返回Class对象:defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length)

继续跟进ProxyGenerator类的generateProxyClass方法,源码如下:

源码
   public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
        ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
        final byte[] var4 = var3.generateClassFile();
        if (saveGeneratedFiles) {
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                public Void run() {
                    try {
                        int var1 = var0.lastIndexOf(46);
                        Path var2;
                        if (var1 > 0) {
                            Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));
                            Files.createDirectories(var3);
                            var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");
                        } else {
                            var2 = Paths.get(var0 + ".class");
                        }

                        Files.write(var2, var4, new OpenOption[0]);
                        return null;
                    } catch (IOException var4x) {
                        throw new InternalError("I/O exception saving generated file: " + var4x);
                    }
                }
            });
        }

        return var4;
    }

主要是调用ProxyGeneratorgenerateClassFile()生成class文件;
然后根据saveGeneratedFiles参数确定是否对class文件保存,saveGeneratedFiles结构如下:

`private static final boolean saveGeneratedFiles =(Boolean)AccessController.doPrivileged(newGetBooleanAction("sun.misc.ProxyGenerator.saveGeneratedFiles"));`

默认情况下为false,也就是不保存文件;为了方便了解原理,可以改下配置,如下:

    public static void main(String[] args) {
        System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        HelloService service = (HelloService) new JdkProxyService(new HelloServiceImpl()).getProxy();
        service.say("hello");
        System.out.println(service.getClass());

    }

可以看到在项目空间下自动生成了以下文件:

image.png

$Proxy0.class内容如下:

源码
package com.sun.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import mncode.service.HelloService;

public final class $Proxy0 extends Proxy implements HelloService {
    private static Method m1;
    private static Method m2;
    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 say(String var1) throws  {
        try {
            super.h.invoke(this, m3, 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);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("mncode.service.HelloService").getMethod("say", Class.forName("java.lang.String"));
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

说明:

  • 继承了Proxy类,实现了HelloService接口;
  • 4个方法:equalshashCodetoStringsay
  • 每个方法内部都会调用InvocationHandler对象的invoke方法。

这里衔接之前自定义的invoke方法:

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理开始------------");
        Object result = method.invoke(target, args);
        System.out.println("代理结束------------");
        return result;
    }
应用

CGLIB动态代理

底层使用ASM字节码生成技术来创建代理类,效率很高;目标类不需要实现接口,代理类继承目标类并重写方法;因为使用的继承的方式,所以目标类不能被final修饰,否则报错;目标类中被finalstatic修饰的方法,不会被代理。

示例
public class ProductService {

    public void create() {
        System.out.println("创建商品");
    }
}
public class CglibService implements MethodInterceptor {

    private Object target;

    public CglibService(Object target) {
        this.target = target;
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("代理开始------------");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("代理结束------------");
        return result;
    }

    public Object getProxy() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }
}

测试代码:

 public static void main(String[] args) {
        ProductService service = (ProductService) new CglibService(new ProductService()).getProxy();
        service.create();
        System.out.println(service.getClass());
  }

输出结果:

代理开始------------
创建商品
代理结束------------
class mncode.service.ProductService$$EnhancerByCGLIB$$e184bf19
原理

查看生成的字节码文件,修改测试代码如下:

    static {
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "E:\\myProjects\\design-pattern");
    }

    public static void main(String[] args) {
        ProductService service = (ProductService) new CglibService(new ProductService()).getProxy();
        service.create();
        System.out.println(service.getClass());
    }

运行后,在E:\\myProjects\\design-pattern路径下自动产生以下文件:

image.png

ProductService$$EnhancerByCGLIB$$e184bf19.class内容如下:

源码
package mncode.service;

import java.lang.reflect.Method;
import net.sf.cglib.core.ReflectUtils;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class ProductService$$EnhancerByCGLIB$$e184bf19 extends ProductService implements Factory {
    private boolean CGLIB$BOUND;
    public static Object CGLIB$FACTORY_DATA;
    private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
    private static final Callback[] CGLIB$STATIC_CALLBACKS;
    private MethodInterceptor CGLIB$CALLBACK_0;
    private static Object CGLIB$CALLBACK_FILTER;
    private static final Method CGLIB$create$0$Method;
    private static final MethodProxy CGLIB$create$0$Proxy;
    private static final Object[] CGLIB$emptyArgs;
    private static final Method CGLIB$equals$1$Method;
    private static final MethodProxy CGLIB$equals$1$Proxy;
    private static final Method CGLIB$toString$2$Method;
    private static final MethodProxy CGLIB$toString$2$Proxy;
    private static final Method CGLIB$hashCode$3$Method;
    private static final MethodProxy CGLIB$hashCode$3$Proxy;
    private static final Method CGLIB$clone$4$Method;
    private static final MethodProxy CGLIB$clone$4$Proxy;

    static void CGLIB$STATICHOOK1() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class var0 = Class.forName("mncode.service.ProductService$$EnhancerByCGLIB$$e184bf19");
        Class var1;
        CGLIB$create$0$Method = ReflectUtils.findMethods(new String[]{"create", "()V"}, (var1 = Class.forName("mncode.service.ProductService")).getDeclaredMethods())[0];
        CGLIB$create$0$Proxy = MethodProxy.create(var1, var0, "()V", "create", "CGLIB$create$0");
        Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
        CGLIB$equals$1$Method = var10000[0];
        CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
        CGLIB$toString$2$Method = var10000[1];
        CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
        CGLIB$hashCode$3$Method = var10000[2];
        CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3");
        CGLIB$clone$4$Method = var10000[3];
        CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
    }

    final void CGLIB$create$0() {
        super.create();
    }

    public final void create() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$create$0$Method, CGLIB$emptyArgs, CGLIB$create$0$Proxy);
        } else {
            super.create();
        }
    }

    final boolean CGLIB$equals$1(Object var1) {
        return super.equals(var1);
    }

    public final boolean equals(Object var1) {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            Object var2 = var10000.intercept(this, CGLIB$equals$1$Method, new Object[]{var1}, CGLIB$equals$1$Proxy);
            return var2 == null ? false : (Boolean)var2;
        } else {
            return super.equals(var1);
        }
    }

    final String CGLIB$toString$2() {
        return super.toString();
    }

    public final String toString() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy) : super.toString();
    }

    final int CGLIB$hashCode$3() {
        return super.hashCode();
    }

    public final int hashCode() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            Object var1 = var10000.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);
            return var1 == null ? 0 : ((Number)var1).intValue();
        } else {
            return super.hashCode();
        }
    }

    final Object CGLIB$clone$4() throws CloneNotSupportedException {
        return super.clone();
    }

    protected final Object clone() throws CloneNotSupportedException {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? var10000.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy) : super.clone();
    }

    public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
        String var10000 = var0.toString();
        switch(var10000.hashCode()) {
        case -508378822:
            if (var10000.equals("clone()Ljava/lang/Object;")) {
                return CGLIB$clone$4$Proxy;
            }
            break;
        case 598313209:
            if (var10000.equals("create()V")) {
                return CGLIB$create$0$Proxy;
            }
            break;
        case 1826985398:
            if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                return CGLIB$equals$1$Proxy;
            }
            break;
        case 1913648695:
            if (var10000.equals("toString()Ljava/lang/String;")) {
                return CGLIB$toString$2$Proxy;
            }
            break;
        case 1984935277:
            if (var10000.equals("hashCode()I")) {
                return CGLIB$hashCode$3$Proxy;
            }
        }

        return null;
    }

    public ProductService$$EnhancerByCGLIB$$e184bf19() {
        CGLIB$BIND_CALLBACKS(this);
    }

    public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
        CGLIB$THREAD_CALLBACKS.set(var0);
    }

    public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
        CGLIB$STATIC_CALLBACKS = var0;
    }

    private static final void CGLIB$BIND_CALLBACKS(Object var0) {
        ProductService$$EnhancerByCGLIB$$e184bf19 var1 = (ProductService$$EnhancerByCGLIB$$e184bf19)var0;
        if (!var1.CGLIB$BOUND) {
            var1.CGLIB$BOUND = true;
            Object var10000 = CGLIB$THREAD_CALLBACKS.get();
            if (var10000 == null) {
                var10000 = CGLIB$STATIC_CALLBACKS;
                if (CGLIB$STATIC_CALLBACKS == null) {
                    return;
                }
            }

            var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
        }

    }

    public Object newInstance(Callback[] var1) {
        CGLIB$SET_THREAD_CALLBACKS(var1);
        ProductService$$EnhancerByCGLIB$$e184bf19 var10000 = new ProductService$$EnhancerByCGLIB$$e184bf19();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Callback var1) {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
        ProductService$$EnhancerByCGLIB$$e184bf19 var10000 = new ProductService$$EnhancerByCGLIB$$e184bf19();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
        CGLIB$SET_THREAD_CALLBACKS(var3);
        ProductService$$EnhancerByCGLIB$$e184bf19 var10000 = new ProductService$$EnhancerByCGLIB$$e184bf19;
        switch(var1.length) {
        case 0:
            var10000.<init>();
            CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
            return var10000;
        default:
            throw new IllegalArgumentException("Constructor not found");
        }
    }

    public Callback getCallback(int var1) {
        CGLIB$BIND_CALLBACKS(this);
        MethodInterceptor var10000;
        switch(var1) {
        case 0:
            var10000 = this.CGLIB$CALLBACK_0;
            break;
        default:
            var10000 = null;
        }

        return var10000;
    }

    public void setCallback(int var1, Callback var2) {
        switch(var1) {
        case 0:
            this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
        default:
        }
    }

    public Callback[] getCallbacks() {
        CGLIB$BIND_CALLBACKS(this);
        return new Callback[]{this.CGLIB$CALLBACK_0};
    }

    public void setCallbacks(Callback[] var1) {
        this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
    }

    static {
        CGLIB$STATICHOOK1();
    }
}

说明:

  • 代理类继承了ProductService类,实现了Factory接口;
  • 当调用代理对象的create方法时,会调用intercept方法。

这里衔接之前自定义的intercept方法:

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("代理开始------------");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("代理结束------------");
        return result;
    }

备注:

  • 目标类不能被final修饰,否则会报错,Enhancer类的generateClass中有校检:
        if (TypeUtils.isFinal(sc.getModifiers()))
            throw new IllegalArgumentException("Cannot subclass final class " + sc.getName());
  • 目标类中被finalstatic修饰的方法,不会被代理;
应用

扩展

1、CGlib动态代理中,如何通过代理对象去获取目标对象?

工具类:

    public static Object getTargetObj(Object proxyObj) throws NoSuchFieldException, IllegalAccessException {
        // 代理对象的字段CGLIB$CALLBACK_0(前面有源码)持有CglibService对象的引用
        Field cglib = proxyObj.getClass().getDeclaredField("CGLIB$CALLBACK_0");
        cglib.setAccessible(true);
        // 反射获取CglibService对象
        Object cglibService = cglib.get(proxyObj);
        System.out.println("cglibService的类型:" + cglibService.getClass());
        // CglibService对象的字段target持有目标对象的引用
        Field target = cglibService.getClass().getDeclaredField("target");
        target.setAccessible(true);
        // 反射获取目标对象
        Object targetObj = target.get(cglibService);
        return targetObj;
    }

测试代码:

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        System.out.println("########代理对象测试########");
        // 代理对象
        ProductService proxyObj = (ProductService) new CglibService(new ProductService()).getProxy();
        System.out.println("代理对象的类型:" + proxyObj.getClass());
        // 调用代理对象
        proxyObj.create();
        System.out.println("########目标对象测试########");
        // 目标对象
        ProductService targetObj = (ProductService) getTargetObj(proxyObj);
        System.out.println("目标对象的类型:" + targetObj.getClass());
        // 调用目标对象
        targetObj.create();
    }

输出结果:

########代理对象测试########
代理对象的类型:class mncode.service.ProductService$$EnhancerByCGLIB$$e184bf19
代理开始------------
创建商品
代理结束------------
########目标对象测试########
cglibService的类型:class mncode.service.CglibService
目标对象的类型:class mncode.service.ProductService
创建商品

2、JDK动态代理中,如何通过代理对象去获取目标对象?

工具类:

    public static Object getTargetObj(Object proxyObj) throws NoSuchFieldException, IllegalAccessException {
        // 代理对象的字段h(在父类Proxy中)持有JdkProxyService对象的引用
        Field h = proxyObj.getClass().getSuperclass().getDeclaredField("h");
        h.setAccessible(true);
        // 反射获取JdkProxyService对象
        Object proxyService = h.get(proxyObj);
        System.out.println("proxyService的类型:" + proxyService.getClass());
        // HelloServiceProxy对象的字段target持有目标对象的引用
        Field target = proxyService.getClass().getDeclaredField("target");
        target.setAccessible(true);
        // 反射获取目标对象
        Object targetObj = target.get(proxyService);
        return targetObj;
    }

测试代码:

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        System.out.println("########代理对象测试########");
        // 代理对象
        HelloService proxyObj = (HelloService) new JdkProxyService(new HelloServiceImpl()).getProxy();
        System.out.println("代理对象的类型:" + proxyObj.getClass());
        // 调用代理对象
        proxyObj.say("hello");
        System.out.println("########目标对象测试########");
        // 目标对象
        HelloService targetObj = (HelloService) getTargetObj(proxyObj);
        System.out.println("目标对象的类型:" + targetObj.getClass());
        // 调用目标对象
        targetObj.say("hello");
    }

输出结果:

########代理对象测试########
代理对象的类型:class com.sun.proxy.$Proxy0
代理开始------------
hello
代理结束------------
########目标对象测试########
proxyService的类型:class mncode.service.JdkProxyService
目标对象的类型:class mncode.service.HelloServiceImpl
hello