一、JDK
Jdk动态代理,拿到目标类所继承的接口,生成代理类,并且代理类也会实现和目标类一样的接口。
二、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。只要生成过代理类都会被缓存,所以这个方法才是检测一个类是否是代理类的唯一标准。