动态代理:基于反射和基于继承的方式

本文详细介绍了Java动态代理的两种实现方式:JDK动态代理和CGLIB动态代理。JDK动态代理要求目标对象实现至少一个接口,而CGLIB则能在没有接口的情况下通过生成目标对象的子类来实现代理。文中深入源码,讲解了CGLIB动态代理的创建过程,包括Enhancer、MethodInterceptor和代理类生成的细节。
摘要由CSDN通过智能技术生成


代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上, 增强额外的功能操作,即扩展目标对象的功能.

这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法.

代理模式的关键点是:代理对象与目标对象.代理对象是对目标对象的扩展,并会调用目标对象.

https://www.cnblogs.com/qlqwjy/p/7550609.html

1、jdk的动态代理

​ 动态代理与静态代理的区别此处不再赘述,大家可以看马老师的设计模式视频,我们主要讲一下动态代理的实现原理,说明白原理的话肯定是要看源码了,大家不要慌,干就完了!!!

JDK的Proxy方式实现的动态代理 目标对象必须有接口 没有接口不能实现jdk版动态代理.

https://www.cnblogs.com/qlqwjy/p/7151748.html

​ 其实在使用动态代理的时候最最核心的就是Proxy.newProxyInstance(loader, interfaces, h);废话不多说,直接干源码。

动态代理的样例代码:

Calculator.java

package com.lw;

public interface Calculator {
   

    public int add(int i, int j);

    public int sub(int i, int j);

    public int mult(int i, int j);

    public int div(int i, int j);
}

MyCalculator.java

package com.lw;

public class MyCalculator implements Calculator {
   
    public int add(int i, int j) {
   
        int result = i + j;
        return result;
    }

    public int sub(int i, int j) {
   
        int result = i - j;
        return result;
    }

    public int mult(int i, int j) {
   
        int result = i * j;
        return result;
    }

    public int div(int i, int j) {
   
        int result = i / j;
        return result;
    }
}

CalculatorProxy.java

package com.lw;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class CalculatorProxy {
   
    public static Calculator getProxy(final Calculator calculator){
   
        ClassLoader loader = calculator.getClass().getClassLoader();
        Class<?>[] interfaces = calculator.getClass().getInterfaces();
        InvocationHandler h = new InvocationHandler() {
   
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   
                Object result = null;
                try {
   
                    result = method.invoke(calculator, args);
                } catch (Exception e) {
   
                } finally {
   
                }
                return result;
            }
        };
        Object proxy = Proxy.newProxyInstance(loader, interfaces, h);
        return (Calculator) proxy;
    }
}

Test.java

package com.lw;

public class Test {
   
    public static void main(String[] args) {
   
        Calculator proxy = CalculatorProxy.getProxy(new MyCalculator());
        proxy.add(1,1);
        System.out.println(proxy.getClass());
    }
}

动态代理的源码:

Proxy.java的newProxyInstance方法:

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

        /*
         * Look up or generate the designated proxy class.
         * 生成接口的代理类的字节码文件
         */
        Class<?> cl = getProxyClass0(loader, intfs);

        /*
         * Invoke its constructor with the designated invocation handler.
         * 使用自定义的InvocationHandler作为参数,调用构造函数获取代理类对象实例
         */
        try {
   
            if (sm != null) {
   
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }
			//获取代理对象的构造方法
            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;
                    }
                });
            }
            //生成代理类的实例并把InvocationHandlerImpl的实例传给构造方法
            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);
        }
    }

getProxyClass0(ClassLoader loader,Class<?>… interfaces)

    private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
   
        //限定代理的接口不能超过65535个
        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
        // 如果缓存中已经存在相应接口的代理类,直接返回,否则,使用ProxyClassFactory创建代理类
        return proxyClassCache.get(loader, interfaces);
    }

    /**
     * a cache of proxy classes
     */
    private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

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

在此方法中会调用suppier.get方法,suppier就是Factory,此类定义在WeakCache内部

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

            // put into reverseMap
            reverseMap.put(cacheValue, Boolean.TRUE);

            // try replacing us with CacheValue (this should always succeed)
            if (!valuesMap.replace(subKey, this, cacheValue)) {
   
                throw new AssertionError("Should not reach here");
            }

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

发现在此方法中调用了valueFactory.apply(key, parameter)方法,此对象其实就是Proxy中的ProxyClassFactory,会调用其apply方法

 		// prefix for all proxy class names
		//代理类的前缀
        private static final String proxyClassNamePrefix = "$Proxy";

        // next number to use for generation of unique proxy class names
		//生成代理类名称的计数器
        private static final AtomicLong nextUniqueNumber = new AtomicLong(); 
@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);
                
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值