关于动态代理模式

为什么JDK的动态代理只能实现接口的代理?

我们通过JDK动态代理生成的代理对象的类型实际是$Proxy0(这个名字后面的0是编号,有多个代理类会一次递增)类,该类继承了Proxy类,所以只能对接口进行代理。Java的继承机制注定了这些动态代理类们无法实现对类的动态代理。

public final class $Proxy0 extends Proxy

动态代理底层实现原理?

Proxy.newInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h
);
(其中,所有对动态代理对象的方法调用都会被转向到InvocationHandler接口的实现上)
通过该方法,我们生成代理对象。
看下该方法源码:

public static Object newProxyInstance(ClassLoader loader,  
                                      Class<?>[] interfaces,  
                                      InvocationHandler h)  
        throws IllegalArgumentException{  
        if (h == null) {  
            throw new NullPointerException();  
        }  
        final Class<?>[] intfs = interfaces.clone();  
        final SecurityManager sm = System.getSecurityManager();  
        if (sm != null) {  
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);  
        }  
        /*查找(缓存中查找,如果没有就生成)或生成指定的代理类*/  
        Class<?> cl = getProxyClass0(loader, intfs);  
        /*用指定的调用处理程序调用它的构造函数.*/  
        try {  
            //获得类的构造函数  
            final Constructor<?> cons =cl.getConstructor(constructorParams);  
            final InvocationHandler ih = h;  
            if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {  
              //当需要代理的类实现了一个非public的接口时,因为这样的接口需要特殊的权限,因此调用doPrivilege(native 修饰的方法)创建代理实例。  
                return AccessController.doPrivileged(newPrivilegedAction<Object>() {  
                    public Object run() {  
                        return newInstance(cons,ih);  
                    }  
                });  
            } else {  
                return newInstance(cons,ih);  
            }  
        } catch (NoSuchMethodException e) {  
            throw new InternalError(e.toString());  
        }  
}  

可以看到,获得代理类的代码是

Class<?> cl = getProxyClass0(loader,intfs);

并由此获得代理类的构造函数

Constructor<?> cons =cl.getConstructor(constructorParams);  

生成代理类的实例返回给该方法的调用者。

return newInstance(cons,ih);  
/*
底层获得代理类的过程大致是:
1.创建代理类的源码;
2.对源码进行编译成字节码;
3.将字节码加载到内存;
4.实例化代理类对象并返回给调用者;
*/

jdk为我们的生成了一个叫$Proxy0(这个名字后面的0是编号,有多个代理类会一次递增)的代理类,这个类文件是放在内存中的,我们在创建代理对象时,就是通过反射获得这个类的构造方法,然后创建的代理实例。
我们可以把nvocationHandler看做一个中介类,中介类持有一个被代理对象(真实对象),在invoke方法中调用了被代理对象的相应方法。通过聚合方式持有被代理对象的引用,把外部对invoke的调用最终都转为对被代理对象的调用。
代理类调用自己方法时,通过自身持有的中介类对象来调用中介类对象的invoke方法,从而达到代理执行被代理对象的方法。也就是说,动态代理通过中介类实现了具体的代理功能。
参考文章:java动态代理实现与原理详细分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值