Back to Javatutorial

SpringAop(五):Cglib代理

docs/Spring全家桶/Spring源码分析/SpringAOP/SpringAop(五):cglib代理.md

1.0.013.9 KB
Original Source

һƪ spring jdK ̬ spring cglib

1. cglib

jdk Ȼṩ˶̬Ƕ̬һ㣺ûʵֽӿڣ޷ jdk ̬Ϊ˽㣬spring cglib

cglib ײǻ asm ģҲֱӲֽ룬൱ڶ asm һװֱӲ룬Ҫ java ָֽļܽУֽɬѶһ㲻ֱӲ cglib װֽIJͱü򵥶ˣ**¶ʹ cglib װõķֽ**

spring cglib λ spring-core ģ飺

asm cglib ˵

/**
 * Spring's repackaging of
 * ASM 7.0
 * (with Spring-specific patches; for internal use only).
 *
 * <p>This repackaging technique avoids any potential conflicts with
 * dependencies on ASM at the application level or from third-party
 * libraries and frameworks.
 *
 * <p>As this repackaging happens at the class file level, sources
 * and javadocs are not available here.
 */
 package org.springframework.asm;

עһ䣺Spring's repackaging of ASM 7.0 spring asm7.0 ´.

/**
 * Spring's repackaging of
 * CGLIB 3.3
 * (with Spring-specific patches; for internal use only).
 *
 * <p>This repackaging technique avoids any potential conflicts with
 * dependencies on CGLIB at the application level or from third-party
 * libraries and frameworks.
 *
 * <p>As this repackaging happens at the class file level, sources
 * and javadocs are not available here.
 */
package org.springframework.cglib;

עһ䣺Spring's repackaging of CGLIB 3.3 spring CGLIB 3.3 ´.

ν´أ⣬ǽ asm7.0 CGLIB 3.3 ԴĸƵ spring Ŀ¡ spring û gradle ļ asm cglib ൱ jar ĿֱĿԴ룡

2. cglib ʾ

ʽʼ֮ǰ cglib νеġ

׼һࣺ

package org.springframework.learn.demo04;

public class CglibProxyService {
    public void hello01() {
        System.out.println("hello01");
    }
}

׼һ MethodInterceptor jdk ̬е InvocationHandler

package org.springframework.learn.demo04;

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

import java.lang.reflect.Method;

public class MyMethodInterceptor implements MethodInterceptor {

    /** Ŀ */
    private Object target;

    public MyMethodInterceptor(Object target){
        this.target = target;
    }

    @Override
    public Object intercept(Object proxyObj, Method method, Object[] objects, 
                MethodProxy proxy) throws Throwable {
        System.out.println("ִзΪ:" + method.getName());
        return proxy.invoke(target, objects);
    }
}

package org.springframework.learn.demo04;

import org.springframework.cglib.proxy.Enhancer;

/**
 * 
 *
 * @author fangchengyan
 * @date 2020-11-01 9:23 
 */
public class Demo04Main {

    public static void main(String[] args) {
        CglibProxyService target = new CglibProxyService();
        MyMethodInterceptor interceptor = new MyMethodInterceptor(target);

        Enhancer enhancer = new Enhancer();
        // ø
        enhancer.setSuperclass(CglibProxyService.class);
        // callbackcallbackṩ MyMethodInterceptor
        enhancer.setCallback(interceptor);
        // ʹ enhancer 
        CglibProxyService proxy = (CglibProxyService)enhancer.create();
        proxy.hello01();
    }
}

У£

ִзΪ:hello01
hello01

Կ MyMethodInterceptor#intercept ִĿķ

ͬ jdk ̬ȽϺ󣬷ߴ߶ƣ

  • InvocationHandler InvocationHandlerߴʽһ

  • Ĵһʹ Enhangcer д󴴽һʹ÷װõķж󴴽

Ӵ󴴽Կ cglib ɶʱõIJ϶࣬ܽϷḻ

Enhangcer δԼ org.springframework.asm org.springframework.cglib µĴ룬Щ cglib ݣͲˡ

3. spring cglib

spring δģ

CglibAopProxy#getProxy(java.lang.ClassLoader)

public Object getProxy(@Nullable ClassLoader classLoader) {
    try {
        Class<?> rootClass = this.advised.getTargetClass();
        Assert.state(rootClass != null, "...");

        Class<?> proxySuperClass = rootClass;
        if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
            proxySuperClass = rootClass.getSuperclass();
            Class<?>[] additionalInterfaces = rootClass.getInterfaces();
            for (Class<?> additionalInterface : additionalInterfaces) {
                this.advised.addInterface(additionalInterface);
            }
        }

        // Ŀм飬Ҫ
        // 1\. Ŀ귽ʹfinalΣ
        // 2\. Ŀ귽private͵ģ
        // 3\. Ŀ귽ǰȨ޵ģ
        // κһǰͲܱʱ÷ͻᱻԹ
        validateClassIfNecessary(proxySuperClass, classLoader);

        Enhancer enhancer = createEnhancer();
        if (classLoader != null) {
            enhancer.setClassLoader(classLoader);
            if (classLoader instanceof SmartClassLoader &&
                    ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                enhancer.setUseCache(false);
            }
        }
        // SuperclassҪ
        enhancer.setSuperclass(proxySuperClass);
        // AopProxyUtils.completeProxiedInterfaces()ҪĿΪҪɵĴ
        // SpringProxyAdvisedDecoratingProxyҪʵֵĽӿڡӿڵ£
        // 1\. SpringProxyһսӿڣڱǵǰɵĴSpringɵĴࣻ
        // 2\. AdvisedSpringɴʹõԶڸýӿУ
        //    AdvisorAdviceԣ
        // 3\. DecoratingProxyýӿڻȡǰĿClass͡
        enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
        enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
        enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(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();
        }
        // ôиҪʹõ߼ProxyCallbackFilter.accept()
        // ֵһһӦCallbackи߼±꣬Ҳ˵CallbackFilter
        // ָ˴иҪʹCallbackеĸļ߼
        enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(),
                this.fixedInterceptorMap, this.fixedInterceptorOffset));
        enhancer.setCallbackTypes(types);

        // ɴ
        return createProxyClassAndInstance(enhancer, callbacks);
    }
    catch (...) {
        ...
    }
}

ϴ Enhancer ԣ classLoader``superclass``callbackFilter ȣ createProxyClassAndInstance(xxx)

ObjenesisCglibAopProxy#createProxyClassAndInstance

protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
    // 
    Class<?> proxyClass = enhancer.createClass();
    Object proxyInstance = null;

    // ݴ࣬ʹ÷ɶ
    if (objenesis.isWorthTrying()) {
        try {
            proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
        }
        catch (Throwable ex) {
            ...
        }
    }

    if (proxyInstance == null) {
        try {
            Constructor<?> ctor = (this.constructorArgs != null ?
                    proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
                    proxyClass.getDeclaredConstructor());
            ReflectionUtils.makeAccessible(ctor);
            proxyInstance = (this.constructorArgs != null ?
                    ctor.newInstance(this.constructorArgs) : ctor.newInstance());
        }
        catch (Throwable ex) {
            throw new AopConfigException(...);
        }
    }
    // callback
    // ˶ callback ʱͨ CallbackFilter ȷʹĸ callback
    ((Factory) proxyInstance).setCallbacks(callbacks);
    return proxyInstance;
}

ͨڵڶֵ demo04 ֪cglib ִУᾭ MethodInterceptor#intercept õģҲ Enhancer callback ԣ˽ callback Ļȡشλ CglibAopProxy#getCallbacks

CglibAopProxy#getCallbacks

private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
    boolean exposeProxy = this.advised.isExposeProxy();
    boolean isFrozen = this.advised.isFrozen();
    boolean isStatic = this.advised.getTargetSource().isStatic();

    // ûԶĴ߼callbackУ @Before@Around@After淽
    // DynamicAdvisedInterceptorе
    Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

    Callback targetInterceptor;
    // жҪ¶ǣʹAopContextýõThreadLocal
    // ûͨAopContextȡĿ
    if (exposeProxy) {
        // жϱĶǷǾ̬ģǾ̬ģĿ󻺴ÿζʹøö󼴿ɣ
        // ĿǶ̬ģDynamicUnadvisedExposedInterceptorÿζһµ
        // Ŀ֯Ĵ߼
        targetInterceptor = (isStatic ?
                new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
                new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
    }
    else {
        // ΨһǷʹAopContext¶ɵĴ
        targetInterceptor = (isStatic ?
                new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
                new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
    }

    // ǰCallbackڲñķ
    Callback targetDispatcher = (isStatic ?
            new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());

    // ȡcallbackװΪһ
    Callback[] mainCallbacks = new Callback[] {
            // ûԼ
            aopInterceptor,  // for normal advice
            // Ƿ¶
            targetInterceptor,  // invoke target without considering advice, if optimized
            // κβ
            new SerializableNoOp(),  // no override for methods mapped to this
            // ڴ洢Advisedķַ
            targetDispatcher, this.advisedDispatcher,
            // equalsõ
            new EqualsInterceptor(this.advised),
            // hashcodeõ
            new HashCodeInterceptor(this.advised)
    };

    Callback[] callbacks;

    // ĿǾ̬ģ߼ĵǹ̶ģĿл
    if (isStatic && isFrozen) {
        Method[] methods = rootClass.getMethods();
        Callback[] fixedCallbacks = new Callback[methods.length];
        this.fixedInterceptorMap = new HashMap<>(methods.length);

        for (int x = 0; x < methods.length; x++) {
            Method method = methods[x];
            // ȡĿ߼
            List<Object> chain = this.advised
                    .getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
            fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
                    chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
            // Եл
            this.fixedInterceptorMap.put(method, x);
        }

        // ɵľ̬Callback
        callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
        System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
        System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
        // fixedInterceptorOffset¼˵ǰ̬ĵ߼ʼλã
        // ¼ôںʹCallbackFilterʱǾ̬ĵ
        // ֱͨòȡӦĵֱԹǰĶ̬
        this.fixedInterceptorOffset = mainCallbacks.length;
    }
    else {
        callbacks = mainCallbacks;
    }
    return callbacks;
}

ϴȽϳҪþǻȡ callbackȻ spring ṩڶ callbackԶ֪ͨص callback ֻһ DynamicAdvisedInterceptor callback CglibAopProxy.DynamicAdvisedInterceptor#intercept УڴеԶִ֪ͨеġ

һǵõ cglib Ĵ󣬽淽ִеġ

4. cglib 淽ִ

cglib 淽ִ CglibAopProxy.DynamicAdvisedInterceptor#intercept

CglibAopProxy.DynamicAdvisedInterceptor#intercept

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) 
        throws Throwable {
    Object oldProxy = null;
    boolean setProxyContext = false;
    Object target = null;
    // ͨTargetSourceȡĿ
    TargetSource targetSource = this.advised.getTargetSource();
    try {
        // жҪ¶򽫵ǰõThreadLocal
        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 {
            // 裺
            // 1\. ִnew CglibMethodInvocation()
            // 2\. ִCglibMethodInvocation#proceed
            retVal = new CglibMethodInvocation(proxy, target, method, args, 
                    targetClass, chain, methodProxy).proceed();
        }
        // ԷֵдֵǵǰĿôɵĴ󷵻أ
        // ֵΪգҷֵǷvoidĻͣ׳쳣
        // ϣֱӽɵķֵ
        retVal = processReturnType(proxy, target, method, retVal);
        return retVal;
    }
    finally {
        if (target != null && !targetSource.isStatic()) {
            targetSource.releaseTarget(target);
        }
        if (setProxyContext) {
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}

ִ new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed()ȥ

CglibAopProxy.CglibMethodInvocation#proceed

public Object proceed() throws Throwable {
    try {
        return super.proceed();
    }
    catch (...) {
        ....
    }
}

ֱӵõǸķCglibAopProxy.CglibMethodInvocation ĸ˭أһȥ־Ȼ ReflectiveMethodInvocation``super.proceed() õ ReflectiveMethodInvocation#proceed

һ ƪУǾϸ ReflectiveMethodInvocation#proceed ĵụ̀ڣ cglib ִеҲͬĴ룬һִй̾Ͳظˡ

һͼ˵ִ֪ͨй̣

յִ˳

5. ܽ

ķ cglib ִйִ̣λ CglibAopProxy.DynamicAdvisedInterceptor#interceptյõ ReflectiveMethodInvocation#proceed jdk ִ̬ͬ


ԭӣhttps://my.oschina.net/funcy/blog/4696655 ߸ˮƽд֮ӭָԭףҵתϵ߻Ȩҵתע