Spring CGLIB如何动态代理

1,004 阅读6分钟

前言

在《Spring getBean是如何解决循环依赖和多次动态代理》里提到了AbstractAutoProxyCreator作为一个自动代理类,其wrapIfNecessary起到了主要作用,现在我们来了解一下这部分是如何工作的,切入问题的代码依然跟上文的代码差不多,以@Transactional为自动代理的入口

AbstractAutoProxyCreator

wrapIfNecessary

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    // 如果是已经被代理过的bean,自然不需要再次代理
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    // 如果是基础类bean(即Advice,Advisors等),或者循环依赖等导致shouldSkip的,不进行代理
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
    // Create proxy if we have advice.
    // getAdvicesAndAdvisorsForBean会找出容器里所有的Advisor,并判断能否应用于该Bean
    // 在本例中由于添加了@Transactional注释,所以会返回BeanFactoryTransactionAttributeSourceAdvisor
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // createProxy就是根据Advisor为当前bean进行代理,返回一个代理bean,生成动态代理最核心的部分
        Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

createProxy

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
                            @Nullable Object[] specificInterceptors, TargetSource targetSource) {
    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }
    // 注意点,每一个代理bean都会有一个与其对应的ProxyFactory,里面包含了创建proxy的很多关键信息
    // 包括proxyTargetClass,exposeProxy,advisors,targetSource等,也是后续代理的基础
    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);
    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }
    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    proxyFactory.addAdvisors(advisors);
    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);
    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }
    return proxyFactory.getProxy(getProxyClassLoader());
}

DefaultAopProxyFactory

上文的proxyFactory.getProxy(getProxyClassLoader()),默认DefaultAopProxyFactory会选择一种AopProxy作为后续代理的基础,众所周知就是JDK代理或者CGLIB,

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    // 如果配置了optimize或者proxyTargetClass
    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.");
        }
        // 同时如果targetClass是接口的话,会走JDK代理
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            return new JdkDynamicAopProxy(config);
        }
        // 否则走CGLIB代理,注意这里将整个config(代理的上下文)送进了AopProxy
        return new ObjenesisCglibAopProxy(config);
    }
    // 很多情况下如果不设置proxyTargetClass,都会优先走JDK代理
    else {
        return new JdkDynamicAopProxy(config);
    }
}

CglibAopProxy

本文主要以CGLIB为例,因此走的是CglibAopProxy,注意在上文中的构造方法,将整个config(代理的上下文)送进了AopProxy

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
    // 省略...
    // Enhancer是CGLIB代理增强的主要部分
    // Configure CGLIB Enhancer...
    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 ClassLoaderAwareGeneratorStrategy(classLoader));
    // callback是CGLIB代理增强的实现部分,此处Spring总共返回了7个callback
    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
    // ProxyCallbackFilter分别描述了7个callback的调用时机
    enhancer.setCallbackFilter(new CglibAopProxy.ProxyCallbackFilter(
        this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
    enhancer.setCallbackTypes(types);
    // Generate the proxy class and create a proxy instance.
    return createProxyClassAndInstance(enhancer, callbacks);
    // 省略...
}

这里7个callback分别是:

  1. aop interceptor, DynamicAdvisedInterceptor
  2. target interceptor, StaticUnadvisedInterceptor
  3. no-op, SerializableNoOp
  4. target dispatcher, StaticDispatcher
  5. advised dispatcher, AdvisedDispatcher
  6. EqualsInterceptor
  7. HashCodeInterceptor

开发者比较关注的是事务代理增强,即aop interceptor, DynamicAdvisedInterceptor

其余一些callback的使用后续再补充

ProxyCallbackFilter.accept()

ProxyCallbackFilter.accept()详细描述了每个callback的调用时机和调用方式

@Override
public int accept(Method method) {
    // final方式CGLIB无能为力,直接使用原本对象
    if (AopUtils.isFinalizeMethod(method)) {
        logger.trace("Found finalize() method - using NO_OVERRIDE");
        return NO_OVERRIDE;
    }
    // 直接寻找Advisor本身
    if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
            method.getDeclaringClass().isAssignableFrom(Advised.class)) {
        if (logger.isTraceEnabled()) {
            logger.trace("Method is declared on Advised interface: " + method);
        }
        return DISPATCH_ADVISED;
    }
    // We must always proxy equals, to direct calls to this.
    // 代理equals
    if (AopUtils.isEqualsMethod(method)) {
        if (logger.isTraceEnabled()) {
            logger.trace("Found 'equals' method: " + method);
        }
        return INVOKE_EQUALS;
    }
    // We must always calculate hashCode based on the proxy.
    // 代理hashcode方法
    if (AopUtils.isHashCodeMethod(method)) {
        if (logger.isTraceEnabled()) {
            logger.trace("Found 'hashCode' method: " + method);
        }
        return INVOKE_HASHCODE;
    }
    Class<?> targetClass = this.advised.getTargetClass();
    // Proxy is not yet available, but that shouldn't matter.
    // 获取代理链,还记得怎么获取吗?就是之前的config里配置了Advisor
    List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    boolean haveAdvice = !chain.isEmpty();
    boolean exposeProxy = this.advised.isExposeProxy();
    boolean isStatic = this.advised.getTargetSource().isStatic();
    boolean isFrozen = this.advised.isFrozen();
    if (haveAdvice || !isFrozen) {
        // If exposing the proxy, then AOP_PROXY must be used.
        if (exposeProxy) {
            if (logger.isTraceEnabled()) {
                logger.trace("Must expose proxy on advised method: " + method);
            }
            return AOP_PROXY;
        }
        Method key = method;
        // Check to see if we have fixed interceptor to serve this method.
        // Else use the AOP_PROXY.
        if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) {
            if (logger.isTraceEnabled()) {
                logger.trace("Method has advice and optimizations are enabled: " + method);
            }
            // We know that we are optimizing so we can use the FixedStaticChainInterceptors.
            int index = this.fixedInterceptorMap.get(key);
            return (index + this.fixedInterceptorOffset);
        }
        else {
            if (logger.isTraceEnabled()) {
                logger.trace("Unable to apply any optimizations to advised method: " + method);
            }
            // 代理我们常见的事务方法
            return AOP_PROXY;
        }
    }
    else {
        // See if the return type of the method is outside the class hierarchy of the target type.
        // If so we know it never needs to have return type massage and can use a dispatcher.
        // If the proxy is being exposed, then must use the interceptor the correct one is already
        // configured. If the target is not static, then we cannot use a dispatcher because the
        // target needs to be explicitly released after the invocation.
        if (exposeProxy || !isStatic) {
            return INVOKE_TARGET;
        }
        Class<?> returnType = method.getReturnType();
        if (targetClass != null && returnType.isAssignableFrom(targetClass)) {
            if (logger.isTraceEnabled()) {
                logger.trace("Method return type is assignable from target type and " +
                        "may therefore return 'this' - using INVOKE_TARGET: " + method);
            }
            return INVOKE_TARGET;
        }
        else {
            if (logger.isTraceEnabled()) {
                logger.trace("Method return type ensures 'this' cannot be returned - " +
                        "using DISPATCH_TARGET: " + method);
            }
            return DISPATCH_TARGET;
        }
    }
}

DynamicAdvisedInterceptor.intercept()

第一个callback DynamicAdvisedInterceptor是CGLIB动态代理的逻辑部分

@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) {
            // Make invocation available if necessary.
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }
        // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
        target = targetSource.getTarget();
        Class<?> targetClass = (target != null ? target.getClass() : null);
        // 动态代理使用责任链的形式,将要增强的部分组成一条chain
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
        Object retVal;
        // Check whether we only have one InvokerInterceptor: that is,
        // no real advice, but just reflective invocation of the target.
        if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
            // We can skip creating a MethodInvocation: just invoke the target directly.
            // Note that the final invoker must be an InvokerInterceptor, so we know
            // it does nothing but a reflective operation on the target, and no hot
            // swapping or fancy proxying.
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            retVal = methodProxy.invoke(target, argsToUse);
        }
        else {
            // We need to create a method invocation...
            // 调起proceed方法即调起整条代理责任链
            retVal = new CglibAopProxy.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) {
            // Restore old proxy.
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}

代理责任链的实现部分

@Override
@Nullable
public Object proceed() throws Throwable {
    // We start with an index of -1 and increment early.
    // 每次调用节点都会将游标向前推进一步
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        // 调起原对象自身的方法,即所有前置通知已经跑过了,待原对象方法返回后,会执行后置通知,类似Struts2那种责任链
        return invokeJoinpoint();
    }
    Object interceptorOrInterceptionAdvice =
            this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
        // Evaluate dynamic method matcher here: static part will already have
        // been evaluated and found to match.
        InterceptorAndDynamicMethodMatcher dm =
                (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
        Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
        if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
            return dm.interceptor.invoke(this);
        }
        else {
            // Dynamic matching failed.
            // Skip this interceptor and invoke the next in the chain.
            // 跳过当前节点并调用责任链的下一节点
            return proceed();
        }
    }
    else {
        // It's an interceptor, so we just invoke it: The pointcut will have
        // been evaluated statically before this object was constructed.
        // 调用责任链的当前节点,注意将this传进去,后续的节点都能通过this.proceed()继续调起下一节点
        // 也是责任链设计模式的关键特征
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}