Spring AOP的實現研究

1. 背景

在前文Spring IOC容器建立bean過程淺析已經介紹了Spring IOC建立初始化bean的大體過程。如今對Spring的AOP實現機制進行研究分析。html

2. 名詞與概念

名詞 概念
Advice 通知,在鏈接點的處理邏輯
Advisor Advisor能夠簡單理解爲Advice+PointCut
Interceptor 攔截器
Aspect 切面

3. 代理類建立的入口--AbstractAutoProxyCreator

AbstractAutoProxyCreator是Spring AOP實現的一個很重要的抽象類。下面是它的繼承層次。
java

咱們能夠注意到,它實際上是一個BeanPostProcessor。咱們須要重點關注的方法是其中的wrapIfNecessary方法,能夠說這是Spring實現Bean代理的核心方法。
wrapIfNecessary在兩處會被調用,一處是getEarlyBeanReference,另外一處是postProcessAfterInitialization。spring

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    // 判斷是否不該該代理這個bean。
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    /*
     * 判斷是不是一些InfrastructureClass或者是否應該跳過這個bean。
     * 所謂InfrastructureClass就是指Advice/PointCut/Advisor等接口的實現類。
     * shouldSkip默認實現爲返回false,因爲是protected方法,子類能夠覆蓋。
     */
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // 獲取這個bean的advice。
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 建立代理。
        Object proxy = createProxy(
                bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

    // 這個bean不須要被代理。
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

protected Object createProxy(
        Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }

    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);
    for (Advisor advisor : advisors) {
        proxyFactory.addAdvisor(advisor);
    }

    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }

    return proxyFactory.getProxy(getProxyClassLoader());
}

4. 代理類建立的實現

從上面的createProxy方法中,咱們能夠看到,最終Spring是經過ProxyFactory#getProxy的調用來獲取最終的代理bean的。

下面就來看一下這其中的過程。app

public Object getProxy(ClassLoader classLoader) {
    return createAopProxy().getProxy(classLoader);
}

/**
 * 該方法是ProxyCreatorSupport(ProxyFactory的基類)的保護方法。
 */
protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
        activate();
    }

    return getAopProxyFactory().createAopProxy(this);
}

DefaultAopProxyFactory是AopProxyFactory接口的默認實現,下面來看一下其中createAopProxy方法的實現。Spring就是在這裏判斷是使用JDK動態代理仍是cglib代理的。ide

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    /*
     * 這裏是Spring判斷是用JDK動態代理仍是Cglib代理的依據。
     * 1. optimize開關被設置爲true。此開關默認爲false。
     * 2. proxyTargetClass開關爲true。
     * 3. 沒有用戶代理接口。所謂用戶代理接口就是指非Spring生成的代理。
     *
     * 知足上述三點任意一點就會根據代理類自己
     */
    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自己是個接口或者targetClass是JDK Proxy生成的,則使用JDK動態代理。
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            return new JdkDynamicAopProxy(config);
        }
        // 不然使用Cglib代理。
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        // 使用JDK動態代理。
        return new JdkDynamicAopProxy(config);
    }
}

4.1 JDK動態代理--JdkDynamicAopProxy的源碼分析

public Object getProxy(ClassLoader classLoader) {
    if (logger.isDebugEnabled()) {
        logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
    }
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

能夠看到本質上JdkDynamicAopProxy對於AopProxy的getProxy方法的實現本質上是調用咱們熟悉的Proxy.newProxyInstance來生成代理bean。
而JdkDynamicAopProxy自己也實現了InvocationHandler接口。下面就來看下它對InvocationHandler#invoke的實現。源碼分析

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    MethodInvocation invocation;
    Object oldProxy = null;
    boolean setProxyContext = false;

    TargetSource targetSource = this.advised.targetSource;
    Class<?> targetClass = null;
    Object target = null;

    try {
        if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
            // 方法爲equals且代理bean自己沒有實現equals方法。
            return equals(args[0]);
        }
        else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
            // 方法爲hashCode且代理bean自己沒有實現hashCode方法。
            return hashCode();
        }
        else if (method.getDeclaringClass() == DecoratingProxy.class) {
            return AopProxyUtils.ultimateTargetClass(this.advised);
        }
        else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                method.getDeclaringClass().isAssignableFrom(Advised.class)) {
            return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
        }

        Object retVal;

        if (this.advised.exposeProxy) {
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }

        target = targetSource.getTarget();
        if (target != null) {
            targetClass = target.getClass();
        }

        // 獲取該方法對應的攔截器鏈。
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

        // 若是沒有任何攔截器,則經過反射調用對應方法。
        if (chain.isEmpty()) {
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
        }
        else {
            // 建立方法調用鏈。
            invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            // 調用方法聯。
            retVal = invocation.proceed();
        }

        
        Class<?> returnType = method.getReturnType();
        // 若是返回的是this,則判斷是否須要把retVal設置爲代理對象。
        if (retVal != null && retVal == target &&
                returnType != Object.class && returnType.isInstance(proxy) &&
                !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
            retVal = proxy;
        }
        else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
            throw new AopInvocationException(
                    "Null return value from advice does not match primitive return type for: " + method);
        }
        return retVal;
    }
    finally {
        if (target != null && !targetSource.isStatic()) {
            targetSource.releaseTarget(target);
        }
        if (setProxyContext) {
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}

4.2 cglib代理--CglibAopProxy的源碼分析

Spring對於cglib建立代理,內部默認使用ObjenesisCglibAopProxy來建立代理bean,它是CglibAopProxy的子類,而且重寫了createProxyClassAndInstance方法。Objenesis是一個類庫,能夠繞過構造器建立對象。
cglib使用Enhancer來生成代理類,生成的類實質上是被代理類的子類。更多關於Enhancer的信息,能夠參考個人博文cglib之Enhancerpost

public Object getProxy(ClassLoader classLoader) {
    if (logger.isDebugEnabled()) {
        logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
    }

    try {
        // advised其實就是建立CglibAopProxy的時候構造參數中傳遞的config配置。
        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);
            }
        }

        validateClassIfNecessary(proxySuperClass, classLoader);

        Enhancer enhancer = createEnhancer();
        if (classLoader != null) {
            enhancer.setClassLoader(classLoader);
            if (classLoader instanceof SmartClassLoader &&
                    ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                enhancer.setUseCache(false);
                    }
        }
        // 配置enhancer如代理接口,回調等。
        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();
        }
        
        // callbackFilter的做用主要是創建了method與callback編號的映射。
        enhancer.setCallbackFilter(new ProxyCallbackFilter(
                    this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
        enhancer.setCallbackTypes(types);

        // 生成代理的class以及代理bean實例。
        return createProxyClassAndInstance(enhancer, callbacks);
    }
    catch (CodeGenerationException ex) {
        throw new AopConfigException("Could not generate CGLIB subclass of class [" +
                this.advised.getTargetClass() + "]: " +
                "Common causes of this problem include using a final class or a non-visible class",
                ex);
    }
    catch (IllegalArgumentException ex) {
        throw new AopConfigException("Could not generate CGLIB subclass of class [" +
                this.advised.getTargetClass() + "]: " +
                "Common causes of this problem include using a final class or a non-visible class",
                ex);
    }
    catch (Exception ex) {
        throw new AopConfigException("Unexpected AOP exception", ex);
    }
}

4.2.1 CglibAopProxy生成callbacks

在CglibAopProxy內部定義了一組常量用於表示生成的callback索引。優化

  • AOP_PROXY = 0
    通常的aop調用
  • INVOKE_TARGET = 1
    直接調用目標方法
  • NO_OVERRIDE = 2
    不能覆蓋的方法,好比finalize方法。
  • DISPATCH_TARGET = 3
    直接對原來的bean進行方法調用。
  • DISPATCH_ADVISED = 4
    對Advised接口方法有效
  • INVOKE_EQUALS = 5
    對equals方法攔截
  • INVOKE_HASHCODE = 6
    對hashCode方法攔截

接下來就看一下這些callback生成的具體源碼實現。ui

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

    // 對於AOP方法的調用,使用DynamicAdvisedInterceptor攔截器。
    Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

    /*
     * 不須要加強,但可能會返回this的方法:
     * 若是targetSource是靜態的話(每次getTarget都是同一個對象),使用StaticUnadvisedExposedInterceptor
     * 不然使用DynamicUnadvisedExposedInterceptor。
     *
     */
    Callback targetInterceptor;
    if (exposeProxy) {
        targetInterceptor = isStatic ?
            new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
            new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
    }
    /*
     * 這裏的分支邏輯與上面相同,只不過exposeProxy爲false的狀況下不會設置AopContext中的currentProxy。
     */
    else {
        targetInterceptor = isStatic ?
            new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
            new DynamicUnadvisedInterceptor(this.advised.getTargetSource());
    }

    Callback targetDispatcher = isStatic ?
        new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();

    Callback[] mainCallbacks = new Callback[] {
            // AOP攔截器。
            aopInterceptor,
            targetInterceptor, 
            new SerializableNoOp(), 
            targetDispatcher, this.advisedDispatcher,
            new EqualsInterceptor(this.advised),
            new HashCodeInterceptor(this.advised)
    };

    Callback[] callbacks;

   /*
     * 若是targetSource爲靜態而且配置已經凍結(advice不會改變),能夠封裝到FixedChainStaticTargetInterceptor來攔截調用方法。
     * 其實FixedChainStaticTargetInterceptor裏的邏輯就至關於對固定的target每次建立CglibMethodInvocation來實現aop攔截。
     */
    if (isStatic && isFrozen) {
        Method[] methods = rootClass.getMethods();
        Callback[] fixedCallbacks = new Callback[methods.length];
        this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length);

        for (int x = 0; x < methods.length; x++) {
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
            fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
                    chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
            this.fixedInterceptorMap.put(methods[x].toString(), x);
        }

        // 把mainCallbacks和fixedCallbacks拼起來。
        callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
        System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
        System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
        this.fixedInterceptorOffset = mainCallbacks.length;
    }
    else {
        callbacks = mainCallbacks;
    }
    return callbacks;
}

4.2.2 CglibAopProxy的CallbackFilter

咱們這裏主要看ProxyCallbackFilter#accept方法的源碼實現。this

public int accept(Method method) {
    // finalize方法使用SerializableNoOp
    if (AopUtils.isFinalizeMethod(method)) {
        logger.debug("Found finalize() method - using NO_OVERRIDE");
        return NO_OVERRIDE;
    }
    if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
            method.getDeclaringClass().isAssignableFrom(Advised.class)) {
        if (logger.isDebugEnabled()) {
            logger.debug("Method is declared on Advised interface: " + method);
        }
        return DISPATCH_ADVISED;
    }
    // equals方法使用EqualsInterceptor。
    if (AopUtils.isEqualsMethod(method)) {
        logger.debug("Found 'equals' method: " + method);
        return INVOKE_EQUALS;
    }
    // hashCode方法使用HashCodeInterceptor。
    if (AopUtils.isHashCodeMethod(method)) {
        logger.debug("Found 'hashCode' method: " + method);
        return INVOKE_HASHCODE;
    }
    Class<?> targetClass = this.advised.getTargetClass();
    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) {
        // 有advice,配置沒有凍結,且須要暴露proxy,使用DynamicAdvisedInterceptor。
        if (exposeProxy) {
            if (logger.isDebugEnabled()) {
                logger.debug("Must expose proxy on advised method: " + method);
            }
            return AOP_PROXY;
        }
        String key = method.toString();
        // 若是知足優化條件(targetSource靜態且配置凍結),則嘗試使用fixedInterceptor。
        if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Method has advice and optimisations are enabled: " + method);
            }
            // 從fixedInterceptorMap中拿到編號加上偏移量便可。
            int index = this.fixedInterceptorMap.get(key);
            return (index + this.fixedInterceptorOffset);
        }
        else {
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to apply any optimisations to advised method: " + method);
            }
            return AOP_PROXY;
        }
    }
    else {
        /*
         * 若是須要暴露proxy或者targetSource非靜態,則使用的callback多是下面三種之一。
         * StaticUnadvisedExposedInterceptor
         * DynamicUnadvisedExposedInterceptor
         * DynamicUnadvisedInterceptor
         */
        if (exposeProxy || !isStatic) {
            return INVOKE_TARGET;
        }
        Class<?> returnType = method.getReturnType();
        // 返回的類型與targetClass一致(有可能返回this),使用StaticUnadvisedInterceptor。
        if (targetClass == returnType) {
            if (logger.isDebugEnabled()) {
                logger.debug("Method " + method +
                        "has return type same as target type (may return this) - using INVOKE_TARGET");
            }
            return INVOKE_TARGET;
        }
        // 返回類型爲基本類型或者targetClass不兼容於返回類型(不可能返回this),使用StaticDispatcher。
        else if (returnType.isPrimitive() || !returnType.isAssignableFrom(targetClass)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Method " + method +
                        " has return type that ensures this cannot be returned- using DISPATCH_TARGET");
            }
            return DISPATCH_TARGET;
        }
        else {
            // 這種狀況targetClass是返回類型的子類(可能返回this),使用StaticUnadvisedInterceptor。
            if (logger.isDebugEnabled()) {
                logger.debug("Method " + method +
                        "has return type that is assignable from the target type (may return this) - " +
                        "using INVOKE_TARGET");
            }
            return INVOKE_TARGET;
        }
    }
}

4.2.3 CglibAopProxy的AOP方法攔截器--DynamicAdvisedInterceptor

在spring中經過cglib建立的代理中,對於須要加強的方法設置的callback爲DynamicAdvisedInterceptor,它實現了cglib的MethodInterceptor。

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

    private final AdvisedSupport advised;

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

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Object oldProxy = null;
        boolean setProxyContext = false;
        Class<?> targetClass = null;
        Object target = null;
        try {
            if (this.advised.exposeProxy) {
                // Make invocation available if necessary.
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }
            // 拿出原始bean對象。
            target = getTarget();
            if (target != null) {
                targetClass = target.getClass();
            }

            // 根據method和class從配置中獲取加強。
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
            Object retVal;
            // 若是沒有加強而且方法爲public,則直接調用。
            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) {
                releaseTarget(target);
            }
            if (setProxyContext) {
                // Restore old proxy.
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }

    @Override
    public boolean equals(Object other) {
        return (this == other ||
                (other instanceof DynamicAdvisedInterceptor &&
                 this.advised.equals(((DynamicAdvisedInterceptor) other).advised)));
    }

    @Override
    public int hashCode() {
        return this.advised.hashCode();
    }

    protected Object getTarget() throws Exception {
        return this.advised.getTargetSource().getTarget();
    }

    protected void releaseTarget(Object target) throws Exception {
        this.advised.getTargetSource().releaseTarget(target);
    }
}

4.3 ReflectiveMethodInvocation#proceed

這裏來看一下方法攔截器的具體實現。這個類特別重要,它是JDK動態代理和cglib代理底層都會用到的類,也就是做用在方法上的加強鏈的本質。

public Object proceed() throws Throwable {
    //  邊界判斷,若是攔截器都調用完畢了就調用鏈接點方法。
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        return invokeJoinpoint();
    }

    // 迭代攔截器聯獲取當前的攔截器。
    Object interceptorOrInterceptionAdvice =
        this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
        InterceptorAndDynamicMethodMatcher dm =
            (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
        // 判斷是否和當前的切點匹配。
        if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
            return dm.interceptor.invoke(this);
        }
        else {
            // 若是不匹配的話,就遞歸調用proceed。
            return proceed();
        }
    }
    else {
        // 若是是一個MethodInterceptor的話則直接調用。
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}

5. 思考

爲何cglib建立的代理方法內部互相調用不會進入代理

這是個很常見的問題,好比會有疑問爲何一個非事務方法調用事務方法沒有進入事務等等。下面經過源碼來分析緣由。

經過查看源碼能夠看到,Spring的cglib的AOP不管方法是否有加強,本質上都是對target進行調用。這裏的target對於通常的AOP一般都是來源於

AbstractAutoProxyCreator#wrapIfNecessary中經過SingletonTargetSource包裝的入參bean,而不是cglib中實際生成的proxy對象。也就是說極可能target就是一個很樸素的bean。那麼進入到這樣一個bean中的方法天然不會再觸發cglib代理的callback攔截了。

其實能夠將代理看做是一個外殼,在方法被調用的時候會被攔截進入到殼子中寫好的邏輯,可是方法體自己已經脫離了外殼層,是在本體中運行的。

攔截器的順序問題

這個問題也是常常會困擾的問題,就是關於那些各類aop切方法,到底哪一個會先切,哪一個後切。
AbstractAutoProxyCreator#wrapIfNecessary中getAdvicesAndAdvisorsForBean用來抓取advice和advisor。
咱們以AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean的實現爲例:

注意到這其中是有排序的邏輯的,以AspectJAwareAdvisorAutoProxyCreator#sortAdvisors爲例能夠看到用的comparator是內置的默認比較器AspectJPrecedenceComparator。

不妨再看一下AspectJPrecedenceComparator的比較策略:

能夠看到會先使用內部的AnnotationAwareOrderComparator來比較,若是優先級相同,則再調用comparePrecedenceWithinAspect進行比較。
AnnotationAwareOrderComparator繼承自OrderComparator, 在OrderComparator中的判斷順序邏輯是若是任一對象是PriorityOrder接口的子類型,則具備更高優先級。不然調用getOrder方法比較。

注意,上面的排序規則只是影響了各advice的調用順序,並不表明咱們關注的aop實際邏輯的調用順序,好比AspectJAfterAdvice#invoke也是先對methodInvocation調用proceed再處理自己的後置邏輯。

相關文章
相關標籤/搜索