Spring源码(14) -- Aop动态代理CglibAopProxy

CglibAopProxy

代码: org.springframework.aop.framework.CglibAopProxy

CglibAopProxy 是 Spring AOP框架的基于CGLIB的AopProxy实现。
此类对象应通过代理工厂获得,由AdvisedSupport对象配置。这个类是Spring的AOP框架的内部,不需要由客户端代码直接使用。
DefaultAopProxyFactory将在必要时自动创建基于CGLIB的代理,例如在代理目标类的情况下。

Enhancer

源码:net.sf.cglib.proxy.Enhancer

Enhancer 是标准Jdk动态代理的替代品,用于生成动态子类以启用方法拦截,还允许代理扩展具体的基类。
Aop Cglib动态代理,会运用到 Enhancer、Callback、CglibAopProxy、MethodInterceptor、MethodProxy 等等。

Callback 接口

源码: org.springframework.cglib.proxy.Callback

被 net.sf.cglib.proxy.Enhancer 类调用的回调接口都会继承 Callback 接口。

public interface Callback {
}

MethodInterceptor

源码:org.springframework.cglib.proxy.MethodInterceptor

MethodInterceptor 继承了 Callback接口。参数包含 对象,方法,上面说过的 MethodProxy 等。
AOP中经常用来实现拦截方法的调用。

public interface MethodInterceptor extends Callback {
    Object intercept(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable;
}

Cglib动态代理示例:

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;

public class CglibProxyDemo {

    public static class Target {
        public void printHello() {
            System.out.println("Hello World");
        }
    }

    public static void main(String[] param) {
        //Enhancer 是标准Jdk动态代理的替代品,用于生成动态子类以启用方法拦截,还允许代理扩展具体的基类。
        Target proxy = (Target) Enhancer.create(Target.class, (MethodInterceptor) (p, method, args, methodProxy) -> {
            System.out.println("before method.");
            
            //以下 p的值是 com.example.demo.sourceCode.cglib.CglibDemo$Target$$EnhancerByCGLIB$$87c3a731@27c60c
            // methodProxy的 fastClassInfo 有 f1为 class com.example.demo.sourceCode.cglib.CglibDemo$Target, 
            // f2为class com.example.demo.sourceCode.cglib.CglibDemo$Target$$EnhancerByCGLIB$$87c3a731
            
            Object result = methodProxy.invokeSuper(p, args);  
            System.out.println("after method.");
            return result;
        });

        proxy.printHello();

    }

}

MethodProxy的 invokeSuper

MethodProxy的作用:当调用被拦截的方法时,Enhancer 生成的类会将此对象传递给已注册的 MethodInterceptor(方法拦截器) 对象。
它既可以用来调用原始方法,也可以在同一类型的不同对象上调用相同的方法。

源码: org.springframework.cglib.proxy.MethodProxy#invokeSuper

  /**
  *  调用指定对象上的原始方法。
  */
    public Object invokeSuper(Object obj, Object[] args) throws Throwable {
        try {
          //实例化成员变量 fastClassInfo,包含了类及方法名称等属性。
            init();
            FastClassInfo fci = fastClassInfo;
            //调用方法
            return fci.f2.invoke(fci.i2, obj, args);
        }
        catch (InvocationTargetException e) {
            throw e.getTargetException();
        }
    }
    
      /*
         *  实例化 fastClassInfo.
         */
        private void init() {
          if (fastClassInfo == null) {
              synchronized (initLock) {
                  if (fastClassInfo == null) {
                      CreateInfo ci = createInfo;
  
                      FastClassInfo fci = new FastClassInfo();
                      fci.f1 = helper(ci, ci.c1);
                      fci.f2 = helper(ci, ci.c2);
                      fci.i1 = fci.f1.getIndex(sig1);
                      fci.i2 = fci.f2.getIndex(sig2);
                      fastClassInfo = fci;
                      createInfo = null;
                  }
            }
        }
    }

CglibAopProxy 生成代理对象

CglibAopProxy 生成代理对象的源码,比较核心。可以重点看看。

源码: org.springframework.aop.framework.CglibAopProxy#getProxy(java.lang.ClassLoader)

    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating CGLIB proxy: target source is " + 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;
            //判断是否为 Cglib动态代理。
            if (ClassUtils.isCglibProxyClass(rootClass)) {
                proxySuperClass = rootClass.getSuperclass();
                Class<?>[] additionalInterfaces = rootClass.getInterfaces();
                for (Class<?> additionalInterface : additionalInterfaces) {
                    this.advised.addInterface(additionalInterface);
                }
            }

            validateClassIfNecessary(proxySuperClass, classLoader);

            // 创建 enhancer, 配置CGLIB增强器。
            Enhancer enhancer = createEnhancer();
            if (classLoader != null) {
                enhancer.setClassLoader(classLoader);
                if (classLoader instanceof SmartClassLoader &&
                        ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                    enhancer.setUseCache(false);
                }
            }
            enhancer.setSuperclass(proxySuperClass);
            enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
            enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
            enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

            //获取  Callback数组。
            Callback[] callbacks = getCallbacks(rootClass);
            Class<?>[] types = new Class<?>[callbacks.length];
            for (int x = 0; x < types.length; x++) {
                types[x] = callbacks[x].getClass();
            }
           
            enhancer.setCallbackFilter(new ProxyCallbackFilter(
                    this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
            //设置回调数组的Class类型
            enhancer.setCallbackTypes(types);

            // 生成代理类并创建代理实例。
            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) {
            //AOP异常
            throw new AopConfigException("Unexpected AOP exception", ex);
        }
    }
    
    
    protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
          enhancer.setInterceptDuringConstruction(false);
          //enhancer 设置回调数组 callbacks
          enhancer.setCallbacks(callbacks);
          //创建代理对象
          return (this.constructorArgs != null && this.constructorArgTypes != null ?
                  enhancer.create(this.constructorArgTypes, this.constructorArgs) :
                  enhancer.create());
    }

CglibAopProxy.DynamicAdvisedInterceptor

DynamicAdvisedInterceptor 是 CglibAopProxy的内部类。
通用AOP回调。当目标是动态的或代理未冻结时使用。

在 AOP 进行前置/后置通知,需要在目标方法在前后处理逻辑时,就会调用 CglibAopProxy.DynamicAdvisedInterceptor 的 intercept 方法。

源码: org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept

    private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

        private final AdvisedSupport advised;

        public DynamicAdvisedInterceptor(AdvisedSupport advised) {
            this.advised = advised;
        }

        @Override
        @Nullable
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            Object oldProxy = null;
            boolean setProxyContext = false;
            Object target = null;
            TargetSource targetSource = this.advised.getTargetSource();
            try {
                if (this.advised.exposeProxy) {
                    oldProxy = AopContext.setCurrentProxy(proxy);
                    setProxyContext = true;
                }
                // 获取目标对象
                target = targetSource.getTarget();
                Class<?> targetClass = (target != null ? target.getClass() : null);
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                Object retVal;


                if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
                    Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                    retVal = methodProxy.invoke(target, argsToUse);
                }
                else {
                    // 核心方法,重点看看。 创建一个方法调用
                    retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
                }
                // 返回值
                retVal = processReturnType(proxy, target, method, retVal);
                return retVal;
            }
            finally {
                if (target != null && !targetSource.isStatic()) {
                    targetSource.releaseTarget(target);
                }
                if (setProxyContext) {
                    AopContext.setCurrentProxy(oldProxy);
                }
            }
        }
}

CglibMethodInvocation

CglibMethodInvocation 是 CglibAopProxy 的内部类。

CglibMethodInvocation 是 使用AOP代理的AOP方法调用的实现。

在需要调用 代理对象,进行方法调用时,就会使用 CglibMethodInvocation。

源码: org.springframework.aop.framework.CglibAopProxy.CglibMethodInvocation#CglibMethodInvocation

    private static class CglibMethodInvocation extends ReflectiveMethodInvocation {

        private final MethodProxy methodProxy;

        private final boolean publicMethod;

        public CglibMethodInvocation(Object proxy, @Nullable Object target, Method method,
                Object[] arguments, @Nullable Class<?> targetClass,
                List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {

            super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
            this.methodProxy = methodProxy;
            this.publicMethod = Modifier.isPublic(method.getModifiers());
        }

 
        @Override
        protected Object invokeJoinpoint() throws Throwable {
            if (this.publicMethod) {
                return this.methodProxy.invoke(this.target, this.arguments);
            }
            else {
                return super.invokeJoinpoint();
            }
        }
    }

ProxyMethodInvocation

代码:org.springframework.aop.ProxyMethodInvocation

允许访问方法调用所使用的代理。

public interface ProxyMethodInvocation extends MethodInvocation {

    /**
     * 返回此方法调用所通过的代理。
     */
    Object getProxy();

    /**
     * 创建此对象的克隆。
     */
    MethodInvocation invocableClone();

    /**
     * 创建此对象的克隆。
     */
    MethodInvocation invocableClone(Object... arguments);

    /**
     * 设置此链中任何 Advice 中后续调用时使用的参数。
     */
    void setArguments(Object... arguments);

    /**
     * 将具有给定值的指定用户属性添加到此调用中。
     */
    void setUserAttribute(String key, @Nullable Object value);

    /**
     * 返回指定用户属性的值。
     */
    @Nullable
    Object getUserAttribute(String key);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值