zl程序教程

您现在的位置是:首页 >  其它

当前栏目

JdkDynamicAopProxy与CglibAopProxy详解

详解
2023-09-27 14:24:00 时间

 https://blog.csdn.net/W85264/article/details/114835055

 

1. Spring AOP设计
2. JdkDynamicAopProxy与CglibAopProxy介绍

3.CgLib实现AOP

4.JdkDynamicAopProxy 拦截器链的获得与递归执行

 

 

要点:cglib和jdk动态代理它们都是通过运行时,动态创建出来的代理对象的class,然后创建出代理对象。

不同点在于:jdk创建出的代理对象是和被代理对象平级的,因为它们都是同一个接口的实现类;cglib创建出来的代理对象是被代理对象的子类(父子关系)

代理方法的不同实现原理:jdk动态代理方法的原理是通过invock方法实现的。代理对象执行任何方法时,都会被 invock方法所拦截,然后都去执行invoke方法;cglib是通过监听执行回调,来达到动态代理方法的

代码块1:createAopProxy() 

 

DefaultAopProxyFactory.class
/**
 * Default {@link AopProxyFactory} implementation, creating either a CGLIB proxy
 * or a JDK dynamic proxy.
 *
 * <p>Creates a CGLIB proxy if one the following is true for a given
 * {@link AdvisedSupport} instance:
 * <ul>
 * <li>the {@code optimize} flag is set
 * <li>the {@code proxyTargetClass} flag is set
 * <li>no proxy interfaces have been specified
 * </ul>
 *
 * <p>In general, specify {@code proxyTargetClass} to enforce a CGLIB proxy,
 * or specify one or more interfaces to use a JDK dynamic proxy.
 *
 */
 //DefaultAopProxyFactory为AopProxyFactory的默认实现类, 它可以创建cglib代理或者jdk代理,
 //创建cglib代理的条件:1、设置optimize这个属性  2、设置proxyTargetClass这个属性 3、被代理对象没有实现接口   
 //(这些设置都是在 第15讲 的图1中的proxyFactoryBean中设置的)
 //通常情况下可以通过proxyTargetClass属性来设置cglib代理或者指定一个或多个接口来使用JDK动态代理。
 
 //总结一句话:根据不同的配置信息,决定返回不同类型的代理(AopProxy)
@SuppressWarnings("serial")
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
 
    @Override
     //AdvisedSupport 是一些配置信息,来自于 第15讲的图1中的proxyFactoryBean
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
             //判断是不是设置了Optimize、isProxyTargetClass属性、没有实现接口,这些判断条件在对上面这个类的介绍信息中有提到
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
                  //获取目标的类对象
            Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: " +
                        "Either an interface or a target is required for proxy creation.");
            }
                   //如果目标类是一个接口,则创建jdk的AopProxy。
                   //这种情况很少,这种情况就是对一个接口进行代理。也就是说被代理对象是一个接口。在配置文件中的体现就是第15讲的图1中的proxyFactoryBean
                   //中的target属性引用的Mytarget的class属性是一个接口
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
                   //创建cblib的AopProxy
                   //很简单,跟JdkDynamicAopProxy的创建差不多,也是调用一个构造方法而已,不多做介绍了
            return new ObjenesisCglibAopProxy(config);
        }
        else {
                  //创建jdk的AopProxy
                  //很简单,调用JdkDynamicAopProxy的构造方法,把配置信息赋值给JdkDynamicAopProxy的一个成员属性
            return new JdkDynamicAopProxy(config);
        }
    }
 
    /**
     * Determine whether the supplied {@link AdvisedSupport} has only the
     * {@link org.springframework.aop.SpringProxy} interface specified
     * (or no proxy interfaces specified at all).
     */
    private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
        Class<?>[] ifcs = config.getProxiedInterfaces();
        return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
    }
 
}

 

代码块2:getProxy()

ProxyFactoryBean.class
/**
     * Return the proxy object to expose.
     * <p>The default implementation uses a {@code getProxy} call with
     * the factory's bean class loader. Can be overridden to specify a
     * custom class loader.
     * @param aopProxy the prepared AopProxy instance to get the proxy from
     * @return the proxy object to expose
     * @see AopProxy#getProxy(ClassLoader)
     */
  //返回要公开的代理对象,默认实现使用getProxy()调用工厂的bean类加载器。可以重写以指定自定义类装入器。
  //通过准备好的AopProxy实例,来获取代理返回要公开的代理对象
    protected Object getProxy(AopProxy aopProxy) {
             //this.proxyClassLoader:  当前ProxyFactoryBean的类加载器
             //通过AopProxy的getProxy()方法就可以创建不同的代理对象了(因为AopProxy有不同的类型)
             //见 内部代码块1、内部代码块2
        return aopProxy.getProxy(this.proxyClassLoader);
    }
 
 内部代码块1: getProxy()
 JdkDynamicAopProxy.class
  @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isTraceEnabled()) {
            logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
        }
          //获取代理对象的接口
        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
          //查找定义好的eqauls()和hashCode()方法,因为动态代理对eqauls()和hashCode()的处理跟其他地方有点不一样,想深入研究可以自行百度
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
          //通过调用Proxy的newProxyInstance()方法创建代理对象(这里其实就是调用了,jdk的动态代理的方法,换句话说,java自带的jdk原生的动态代理就是这样)
          //你会发现,jdk动态代理的第三个参数InvocationHandler变成了this,所以可以看出JdkDynamicAopProxy就是InvocationHandler的一个实现类。所以
          //JdkDynamicAopProxy中一定实现了invoke()方法。因为代理对象本身并没有实现方法的代码,所有的方法的执行都是通过invoke()方法实现的。
          //JdkDynamicAopProxy中的invoke()方法详细,见 第17讲->代码块1
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }
 
 内部代码块2: getProxy()
 CglibAopProxy.class
 @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isTraceEnabled()) {
            logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
        }
 
        try {
            Class<?> rootClass = this.advised.getTargetClass();
            Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
 
            Class<?> proxySuperClass = rootClass;
            if (ClassUtils.isCglibProxyClass(rootClass)) {
                proxySuperClass = rootClass.getSuperclass();
                Class<?>[] additionalInterfaces = rootClass.getInterfaces();
                for (Class<?> additionalInterface : additionalInterfaces) {
                    this.advised.addInterface(additionalInterface);
                }
            }
 
            // Validate the class, writing log messages as necessary.
            validateClassIfNecessary(proxySuperClass, classLoader);
 
            // Configure CGLIB Enhancer...
                   //这个是cglib里面的一个对象
            Enhancer enhancer = createEnhancer();
            if (classLoader != null) {
                enhancer.setClassLoader(classLoader);
                if (classLoader instanceof SmartClassLoader &&
                        ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                    enhancer.setUseCache(false);
                }
            }
                   //给cglib的Enhancer对象设值(就像jdk动态代理时,做一些准备工作设置值一样)
            enhancer.setSuperclass(proxySuperClass);
            enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
            enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
            enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
                    //获取回调(这个好像很重要,cglib对目标对象方法的代理就是通过这些回调来完成的。jdk对目标对象方法的代理是通过invoke()方法实现的)
            Callback[] callbacks = getCallbacks(rootClass);
            Class<?>[] types = new Class<?>[callbacks.length];
            for (int x = 0; x < types.length; x++) {
                types[x] = callbacks[x].getClass();
            }
            // fixedInterceptorMap only populated at this point, after getCallbacks call above
            enhancer.setCallbackFilter(new ProxyCallbackFilter(
                    this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
            enhancer.setCallbackTypes(types);
 
            // Generate the proxy class and create a proxy instance.
                   //这个方法内部会通过调用Enhancer的create()方法来创建代理对象
            return createProxyClassAndInstance(enhancer, callbacks);
        }
        catch (CodeGenerationException | IllegalArgumentException ex) {
            throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
                    ": Common causes of this problem include using a final class or a non-visible class",
                    ex);
        }
        catch (Throwable ex) {
            // TargetSource.getTarget() failed
            throw new AopConfigException("Unexpected AOP exception", ex);
        }
    }