Cglib代理和JDK代理原理的区别

一、JDK

Jdk动态代理,拿到目标类所实现的接口(目标类必须有实现接口),生成代理类,并且代理类也会实现和目标类一样的接口。

Cglib代理和JDK代理原理的区别_第1张图片

二、Cglib

Cglib代理功能更强,无论目标类是否实现了接口都可以代理,他是基于继承的方式来代理目标类,如果目标类也实现了接口,代理类也会实现一次

public Object getProxy(@Nullable ClassLoader classLoader) {
		Class<?> rootClass = this.advised.getTargetClass();//目标类
        Class<?> proxySuperClass = rootClass;
       
        if (rootClass.getName().contains("$$")) { //如果目标类也是一个代理类,那么就拿到这个代理类的父类,因为这个代理类的父类,才是我们真正要代理的目标类。然后继承他
            proxySuperClass = rootClass.getSuperclass();
            Class<?>[] additionalInterfaces = rootClass.getInterfaces();//如果目标类是一个代理类,那么这个代理实现的接口,也就是新的代理类要实现的接口。
            this.advised.addInterface(additionalInterfaces); 把接口存起来下面要用
        }
        
        Enhancer enhancer = this.createEnhancer();
        enhancer.setSuperclass(proxySuperClass);  //设置代理的父类,可能是目标类的类型,可能是目标类的父类。
        enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));  //设置新的代理类要实现的接口。
        //必实现的接口SpringProxy,如果是切面还会实现Advised
        
        enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
        enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
        Callback[] callbacks = this.getCallbacks(rootClass);
        Class<?>[] types = new Class[callbacks.length];
        。。。。。
}

三、如何选择

那么在Spring创建代理对象的时候是选择Cglib还是Jdk有一段代码

//判断是否是接口或者是否是代理类
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
    new JdkDynamicAopProxy(config)
} else {
    new ObjenesisCglibAopProxy(config)
}

public static boolean isProxyClass(Class<?> cl) {
    return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);
}

Proxy.class.isAssignableFrom(cl)就是判断cl所表示的类是不是SpringProxy或者SpringProxy的子类。因为所有的代理类都会继承SpringProxy,所以这个条件必须满足。满足这个条件也不能保证就是代理类,因为可能存在人为地编写一个类继承SpringProxy。proxyClassCache.containsValue(cl)这个方法是检查缓存中是否存在这个Class实例cl。只要生成过代理类都会被缓存,所以这个方法才是检测一个类是否是代理类的唯一标准。

你可能感兴趣的:(spring,java,开发语言)