Spring AOP 機(jī)制解讀

Spring AOP 機(jī)制源碼解讀

導(dǎo)讀

  • AOP是Spring框架面向切面的編程思想,AOP采用一種稱(chēng)為“橫切”的技術(shù),將涉及多業(yè)務(wù)流程的通用功能抽取并單獨(dú)封裝,形成獨(dú)立的切面,在合適的時(shí)機(jī)將這些切面橫向切入到業(yè)務(wù)流程指定的位置中。
  • 本文不會(huì)講解Spring切面的使用方法以及Spring切面的定義,但會(huì)通過(guò)一個(gè)示例引入話(huà)題。
  • 本文設(shè)計(jì)內(nèi)容主要說(shuō)明Spring內(nèi)部如何幫我們做切面處理,Spring是如何實(shí)現(xiàn)切面的,雖然Spring切面的底層實(shí)現(xiàn)還是基于動(dòng)態(tài)代理,但是本文并不會(huì)講解動(dòng)態(tài)代理,如果讀者不太了解動(dòng)態(tài)代理,還需先連接器原理后再進(jìn)行本文的解讀,本文解讀需要一定的基礎(chǔ):如Spring bean的加載機(jī)制,Spring注解功能,Spring后置處理器,Spring BeanFactory。

一 示例引入

1.1 目標(biāo)方法

下面是測(cè)試所用的目標(biāo)方法,使用如下一個(gè)打印方法進(jìn)行測(cè)試:
方法很簡(jiǎn)單,參入兩個(gè)int類(lèi)型的輸入?yún)?shù),打印入?yún)ⅲ祷貎蓚€(gè)參數(shù)的除;
我們的需求是:在目標(biāo)方法運(yùn)行的時(shí)候進(jìn)行日志輸出(方法運(yùn)行前,方法運(yùn)行結(jié)束,或者方法運(yùn)行出現(xiàn)異常的時(shí)候,...)

public class MainPrint {

    public int print(int i, int j) {
        System.out.println("i = " + i + ", j = " + j);
        return i / j;
    }
}

1.2 定義切換類(lèi)

定義切面如下所示:

  • 通過(guò)注解@Aspect告知Spring 該類(lèi)是一個(gè)切面類(lèi)。
  • 定義前置增加(@Before):logStart:在目標(biāo)方法(div)運(yùn)行之前運(yùn)行
  • 定義后置通知(@After):logEnd:在目標(biāo)方法(div)運(yùn)行結(jié)束之后運(yùn)行(無(wú)論方法正常結(jié)束還是異常結(jié)束)
  • 返回通知(@AfterReturning):logReturn:在目標(biāo)方法(div)正常返回之后運(yùn)行
  • 異常通知(@AfterThrowing):logException:在目標(biāo)方法(div)出現(xiàn)異常以后運(yùn)行
  • 環(huán)繞通知(@Around):動(dòng)態(tài)代理,手動(dòng)推進(jìn)目標(biāo)方法運(yùn)行(joinPoint.procced());
@Aspect
public class LogsAspects {

    /**
     * 定義切入點(diǎn)
     */
    @Pointcut("execution(public int org.mzw.spring.annotation.aop.MainPrint.*(..))")
    public void pointCut(){};


    @Before("pointCut()")
    public void logStart(JoinPoint joinPoint){
        Object[] args = joinPoint.getArgs();
        System.out.println(""+joinPoint.getSignature().getName()+"運(yùn)行。。。@Before:參數(shù)列表是:{"+Arrays.asList(args)+"}");
    }

    @After("org.mzw.spring.annotation.aop.LogsAspects.pointCut()")
    public void logEnd(JoinPoint joinPoint){
        System.out.println(""+joinPoint.getSignature().getName()+"結(jié)束。。。@After");
    }

    /**
     * 獲取返回值
     * 注意:JoinPoint一定要出現(xiàn)在參數(shù)表的第一位
     */
    @AfterReturning(value="pointCut()",returning="result")
    public void logReturn(JoinPoint joinPoint,Object result){
        System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:運(yùn)行結(jié)果:{"+result+"}");
    }

    @AfterThrowing(value="pointCut()",throwing="exception")
    public void logException(JoinPoint joinPoint,Exception exception){
        System.out.println(""+joinPoint.getSignature().getName()+"異常。。。異常信息:{"+exception+"}");
    }
}

1.3 基于注解配置

  • @EnableAspectJAutoProxy 通過(guò)添加該注解告知Spring啟動(dòng)AspectJAutoProxy 開(kāi)啟基于注解的aop模式
@EnableAspectJAutoProxy
@Configuration
public class ConfigOfAOP {

    //業(yè)務(wù)邏輯類(lèi)加入容器中
    @Bean
    public MainPrint calculator(){
        return new MainPrint();
    }

    //切面類(lèi)加入到容器中
    @Bean
    public LogsAspects logsAspects(){
        return new LogsAspects();
    }
}

1.4 Main 啟動(dòng)容器

private static void starterSpringOfAop(Class<?>... clazz) {
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(clazz);
    MainPrint bean = applicationContext.getBean(MainPrint.class);
    int print = bean.print(2, 4);
    System.out.println(print);
}

輸出結(jié)果:

print運(yùn)行。。。@Before:參數(shù)列表是:{[2, 4]}
i = 2, j = 4
print結(jié)束。。。@After
print正常返回。。。@AfterReturning:運(yùn)行結(jié)果:{0}
0

實(shí)例很簡(jiǎn)單,接下類(lèi)看看這簡(jiǎn)單的背后Spring是如何處理的。
在上面示例中,@Aspect告知Spring這是一個(gè)切面邏輯,只有另一處代碼我們需要關(guān)注,那就是@EnableAspectJAutoProxy 該注解告知Spring 開(kāi)啟切面功能。
所以我們需要重點(diǎn)關(guān)注下@EnableAspectJAutoProxy到底做了哪些騷操作

二 AOP代理創(chuàng)建源碼解讀

開(kāi)啟基于注解的aop模式;@EnableAspectJAutoProxy
了解Spring IOC的可以知道,Spring在啟動(dòng)的時(shí)候會(huì)注冊(cè)一些Bean,不同的Bean在不同的時(shí)機(jī)做不同的事情,所以我們也效仿這個(gè)模板去分析下Spring的AOP原理(容器中注冊(cè)了什么組件,這個(gè)組件什么時(shí)候工作,這個(gè)組件的功能是什么?)

2.1 EnableAspectJAutoProxy

2.1.1 @EnableAspectJAutoProxy 是什么?

我們?cè)赟pring的配置類(lèi)上添加了這一注解@EnableAspectJAutoProxy ,所以我們先分析下這個(gè)注解到底是做什么的?
下面是EnableAspectJAutoProxy的源碼:這個(gè)是一個(gè)注解組件,除了注解常用的幾個(gè)用于注解的注解之外我們會(huì)發(fā)現(xiàn)一個(gè)特殊的注解@Import(AspectJAutoProxyRegistrar.class)

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

    /**
     * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
     * to standard Java interface-based proxies. The default is {@code false}.
     */
    boolean proxyTargetClass() default false;

    /**
     * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
     * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
     * Off by default, i.e. no guarantees that {@code AopContext} access will work.
     * @since 4.3.1
     */
    boolean exposeProxy() default false;
}

@Import 該組件可以向容器中注冊(cè)Bean,

  • {@link Configuration},
  • {@link ImportSelector},
  • {@link ImportBeanDefinitionRegistrar} * or regular component classes to import.

我們看到AspectJAutoProxyRegistrar 應(yīng)該是一個(gè)BeanDefinitionRegistrar, 給容器中導(dǎo)入AspectJAutoProxyRegistrar

2.1.2 AspectJAutoProxyRegistrar.class

利用AspectJAutoProxyRegistrar自定義給容器中注冊(cè)bean;BeanDefinetion
源碼如下:

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * Register, escalate, and configure the AspectJ auto proxy creator based on the value
     * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
     * {@code @Configuration} class.
     */
    @Override
    public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

        AnnotationAttributes enableAspectJAutoProxy =
                AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy != null) {
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }

}

2.1.3 registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
查看方法最終是給容器中注冊(cè)一個(gè)AnnotationAwareAspectJAutoProxyCreator.class

@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
        BeanDefinitionRegistry registry, @Nullable Object source) {
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

2.1.4 @EnableAspectJAutoProxy 注解小結(jié)

  • @EnableAspectJAutoProxy :利用@Import 給容器中導(dǎo)入AspectJAutoProxyRegistrar;
  • 利用AspectJAutoProxyRegistrar自定義給容器中注冊(cè)bean;AnnotationAwareAspectJAutoProxyCreator

所以@EnableAspectJAutoProxy 注解的功能最終就是給Spring Ioc容器中注冊(cè)了一個(gè)Bean:AnnotationAwareAspectJAutoProxyCreator

2.2 AnnotationAwareAspectJAutoProxyCreator

我們先分析下AnnotationAwareAspectJAutoProxyCreator 這是一個(gè)什么組件,看下該類(lèi)的繼承關(guān)系:如下圖(簡(jiǎn)化后的:排除一些無(wú)關(guān)此話(huà)題的依賴(lài)樹(shù)):

AnnotationAwareAspectJAutoProxyCreator 2.png

上圖中關(guān)注標(biāo)紅的組件:

  • implements SmartInstantiationAwareBeanPostProcessor 后置處理器
  • BeanFactoryAware 自動(dòng)裝配BeanFactory

知道了這個(gè)組件是一個(gè)什么東西后我們就可以分析它具體做什么事情?

  1. 關(guān)注后置處理器,在bean初始化完成前后做事情?
  2. 裝配BeanFactory

這里暫時(shí)不說(shuō)SpringIOC是如何加載AnnotationAwareAspectJAutoProxyCreator的邏輯,這里暫時(shí)只分析AnnotationAwareAspectJAutoProxyCreator的作用,后續(xù)有機(jī)會(huì)再針對(duì)Spring加載AnnotationAwareAspectJAutoProxyCreator進(jìn)行說(shuō)明。

2.2.1 AbstractAutoProxyCreator

在該AnnotationAwareAspectJAutoProxyCreator組件的超類(lèi)AbstractAutoProxyCreator 中顯示的裝配了BeanFactory

@Override
public void setBeanFactory(BeanFactory beanFactory) {
    this.beanFactory = beanFactory;
}

同時(shí)在該AbstractAutoProxyCreator組件中實(shí)現(xiàn)了后置處理器的邏輯
此處需要特殊說(shuō)明下:

  • 一般我們實(shí)現(xiàn)BeanPostProcess 實(shí)現(xiàn)的方法是postProcessBeforeInitialization/postProcessAfterInitialization,該方法是Bean在調(diào)用初始化方法前后被調(diào)用,
  • 而此處我們實(shí)現(xiàn)InstantiationAwareBeanPostProcessor的方法是postProcessBeforeInstantiation/postProcessAfterInstantiation 該方法是在Bean實(shí)例化的前后進(jìn)行調(diào)用;

補(bǔ)充說(shuō)明:AbstractAutoProxyCreator實(shí)現(xiàn)了InstantiationAwareBeanPostProcessor 所以AnnotationAwareAspectJAutoProxyCreator組件的作用是在每個(gè)Bean創(chuàng)建之前調(diào)用postProcessBeforeInstantiation()

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    Object cacheKey = getCacheKey(beanClass, beanName);

    if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
        if (this.advisedBeans.containsKey(cacheKey)) {
            return null;
        }
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }
    // Create proxy here if we have a custom TargetSource.
    // Suppresses unnecessary default instantiation of the target bean:
    // The TargetSource will handle target instances in a custom fashion.
    TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
    if (targetSource != null) {
        if (StringUtils.hasLength(beanName)) {
            this.targetSourcedBeans.add(beanName);
        }
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
        Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

    return null;
}

/**
 * Create a proxy with the configured interceptors if the bean is
 * identified as one to proxy by the subclass.
 * @see #getAdvicesAndAdvisorsForBean
 */
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}   

2.2.2 方法 postProcessBeforeInstantiation

該方法一直跳過(guò),所以此處不進(jìn)行分析

// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
    if (StringUtils.hasLength(beanName)) {
        this.targetSourcedBeans.add(beanName);
    }
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
    Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
    this.proxyTypes.put(cacheKey, proxy.getClass());
    return proxy;
}

2.2.3 postProcessAfterInitialization

  • 嘗試從緩存中獲取bean名稱(chēng)
  • 是否是早期代理引用
  • 如果不是則進(jìn)行增強(qiáng)嘗試
/**
 * Create a proxy with the configured interceptors if the bean is
 * identified as one to proxy by the subclass.
 * @see #getAdvicesAndAdvisorsForBean
 */
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

關(guān)注該方法wrapIfNecessary 見(jiàn)名知意: 如果需要?jiǎng)t進(jìn)行增強(qiáng),

2.2.3 wrapIfNecessary

getAdvicesAndAdvisorsForBean.jpg
  • 判斷當(dāng)前bean是否在advisedBeans中(保存了所有需要增強(qiáng)bean)
  • 判斷當(dāng)前bean是否是基礎(chǔ)類(lèi)型的Advice、Pointcut、Advisor、AopInfrastructureBean, 或者是否是切面(@Aspect)
  • 是否需要跳過(guò)
    • 獲取候選的增強(qiáng)器(切面里面的通知方法)【List<Advisor> candidateAdvisors】每一個(gè)封裝的通知方法的增強(qiáng)器是 InstantiationModelAwarePointcutAdvisor;判斷每一個(gè)增強(qiáng)器是否是 AspectJPointcutAdvisor 類(lèi)型的;返回true
    • 永遠(yuǎn)返回false
  • 創(chuàng)建代理對(duì)象
  • 放入緩存
  • 返回代理對(duì)象
/**
 * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
 * @param bean the raw bean instance
 * @param beanName the name of the bean
 * @param cacheKey the cache key for metadata access
 * @return a proxy wrapping the bean, or the raw bean instance as-is
 */
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // Create proxy if we have 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;
    }

    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}
    

createProxy 創(chuàng)建代理對(duì)象

下面是createProxy 調(diào)用鏈

return proxyFactory.getProxy(getProxyClassLoader());
  • getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
    return createAopProxy().getProxy(classLoader);
}
  • createAopProxy
protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
        activate();
    }
    return getAopProxyFactory().createAopProxy(this);
}
  • getAopProxyFactory().createAopProxy
    DefaultAopProxyFactory#createAopProxy
    這里判斷使用哪種進(jìn)行代理
  • 如果目標(biāo)對(duì)象實(shí)現(xiàn)接口,使用JDK動(dòng)態(tài)代理技術(shù) -> new JdkDynamicAopProxy(config);
  • 如果目標(biāo)對(duì)象沒(méi)有實(shí)現(xiàn)接口,則使用cglib動(dòng)態(tài)代理技術(shù) -> new ObjenesisCglibAopProxy(config);
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    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.");
        }
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            return new JdkDynamicAopProxy(config);
        }
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        return new JdkDynamicAopProxy(config);
    }
}

然后調(diào)用具體實(shí)現(xiàn)的代理工廠的getProxy 創(chuàng)建代理,
下面是CglibAopProxy的getProxy方法實(shí)現(xiàn):

@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...
        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[] 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.
        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);
    }
}

返回代理對(duì)象

createProxy.jpg

到此代理對(duì)象創(chuàng)建完畢!

AOP 代理方法執(zhí)行邏輯源碼解析

代碼中我們獲取代理對(duì)象,并執(zhí)行目標(biāo)方法
bean.print(2, 4);

private static void starterSpringOfAop(Class<?>... clazz) {
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(clazz);
    MainPrint bean = applicationContext.getBean(MainPrint.class);
    int print = bean.print(2, 4);
    System.out.println(print);
}

這里我們斷點(diǎn)打在bean.print(2, 4); 觀察下

intercept.jpg

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);
        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...
            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) {
            // Restore old proxy.
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}   

2.3.1 核心代碼CglibMethodInvocation.proceed

// We need to create a method invocation... 
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
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);

    // Only use method proxy for public methods not derived from java.lang.Object
    this.methodProxy = (Modifier.isPublic(method.getModifiers()) &&
            method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&
            !AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method) ?
            methodProxy : null);
}

2.3.2 proceed

執(zhí)行步驟:

  1. 容器中保存了組件的代理對(duì)象(cglib增強(qiáng)后的對(duì)象),這個(gè)對(duì)象里面保存了詳細(xì)信息(比如增強(qiáng)器,目標(biāo)對(duì)象,xxx);
  2. 根據(jù)ProxyFactory對(duì)象獲取將要執(zhí)行的目標(biāo)方法攔截器鏈;
    List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
  • List<Object> interceptorList保存所有攔截器 : 一個(gè)默認(rèn)的ExposeInvocationInterceptor 和 4個(gè)增強(qiáng)器;
  • 遍歷所有的增強(qiáng)器,將其轉(zhuǎn)為Interceptor;registry.getInterceptors(advisor);
  • 將增強(qiáng)器轉(zhuǎn)為L(zhǎng)ist<MethodInterceptor>;如果是MethodInterceptor,直接加入到集合中,如果不是,使用AdvisorAdapter將增強(qiáng)器轉(zhuǎn)為MethodInterceptor;轉(zhuǎn)換完成返回MethodInterceptor數(shù)組;
  1. 如果沒(méi)有攔截器鏈,直接執(zhí)行目標(biāo)方法;攔截器鏈(每一個(gè)通知方法又被包裝為方法攔截器,利用MethodInterceptor機(jī)制)
  2. 如果有攔截器鏈,把需要執(zhí)行的目標(biāo)對(duì)象,目標(biāo)方法,攔截器鏈等信息傳入創(chuàng)建一個(gè) CglibMethodInvocation 對(duì)象,并調(diào)用 Object retVal = mi.proceed();
  3. 攔截器鏈的觸發(fā)過(guò)程; 如果沒(méi)有攔截器執(zhí)行執(zhí)行目標(biāo)方法,或者攔截器的索引和攔截器數(shù)組-1大小一樣(指定到了最后一個(gè)攔截器)執(zhí)行目標(biāo)方法;鏈?zhǔn)将@取每一個(gè)攔截器,攔截器執(zhí)行invoke方法,每一個(gè)攔截器等待下一個(gè)攔截器執(zhí)行完成返回以后再來(lái)執(zhí)行;攔截器鏈的機(jī)制,保證通知方法與目標(biāo)方法的執(zhí)行順序;
public Object proceed() throws Throwable {
        //  We start with an index of -1 and increment early.
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            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.
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容