spring源碼探索(4)-AOP實(shí)現(xiàn)原理

導(dǎo)讀

本篇主要針對(duì)spring aop進(jìn)行源碼級(jí)解說(shuō),如有不不到位的地方敬請(qǐng)指出,多謝……

本文大綱如下

  1. spring aop 使用姿勢(shì)
  2. spring aop 主鏈路概覽
  3. spring aop 相關(guān)概念
  4. spring aop 源碼解讀
    4.1 編程方式解讀
    4.2 配置方式解讀
    4.3 注解方式解讀
  5. spring aop不生效的探索

一、Spring AOP 使用姿勢(shì)

待被加強(qiáng)的目標(biāo)類(lèi)

public interface Sleepable {
    void sleep();

    void sleep2();
}

public class SleepableImpl implements Sleepable {

    @Override
    public void sleep() {
        System.out.println("睡覺(jué)!不休息哪里有力氣學(xué)習(xí)!");

        this.sleep2();
    }

    @Override
    public void sleep2() {
        System.out.println("lalala");
    }

}
<!-- 定義被代理者 -->
<bean id="sleepable" class="com.youzan.study.spring.aop.SleepableImpl"/>

1.1 編程式

Advice

public class SleepAdvice2 implements MethodBeforeAdvice, AfterReturningAdvice {
 
    public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
        System.out.println("睡覺(jué)前要脫衣服!");
    }
 
    public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
        System.out.println("起床后要穿衣服!");
    }
 
}
<!--&lt;!&ndash;&lt;!&ndash;&lt;!&ndash; 定義通知內(nèi)容,也就是切入點(diǎn)執(zhí)行前后需要做的事情 &ndash;&gt;&ndash;&gt;&ndash;&gt;-->
    <bean id="sleepAdvice2" class="com.youzan.study.spring.aop.SleepAdvice2"/>

    <!-- 定義切入點(diǎn)位置 -->
    <bean id="sleepPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
        <property name="pattern" value=".*sleep"/>
    </bean>

    <!-- 使切入點(diǎn)與通知相關(guān)聯(lián),完成切面配置 -->
    <bean id="sleepHelperAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
        <property name="advice" ref="sleepAdvice2"/>
        <property name="pointcut" ref="sleepPointcut"/>
    </bean>

    <!--編程方式啟用 AOP-->
    <bean id="sleepableProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 代理的對(duì)象,有睡覺(jué)能力 -->
        <property name="target" ref="sleepable"/>
        <!-- 使用切面 -->
        <property name="interceptorNames" value="sleepHelperAdvisor"/>
        <!-- 代理接口,睡覺(jué)接口 -->
        <property name="proxyInterfaces" value="com.youzan.study.spring.aop.Sleepable"/>
    </bean>

調(diào)用姿勢(shì)

FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("/"+"配置文件地址");
Sleepable sleepable = (Sleepable)context.getBean("sleepableProxy");
sleepable.sleep();

1.2 配置方式

advice同配置方式一致

<!--&lt;!&ndash;&lt;!&ndash;&lt;!&ndash; 定義通知內(nèi)容,也就是切入點(diǎn)執(zhí)行前后需要做的事情 &ndash;&gt;&ndash;&gt;&ndash;&gt;-->
    <bean id="sleepAdvice2" class="com.youzan.study.spring.aop.SleepAdvice2"/>

    <!-- 定義切入點(diǎn)位置 -->
    <bean id="sleepPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
        <property name="pattern" value=".*sleep"/>
    </bean>

    <!-- 使切入點(diǎn)與通知相關(guān)聯(lián),完成切面配置 -->
    <bean id="sleepHelperAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
        <property name="advice" ref="sleepAdvice2"/>
        <property name="pointcut" ref="sleepPointcut"/>
    </bean>

    <!--配置的形式啟用 AOP-->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />

調(diào)用姿勢(shì)

Sleepable sleepable = (Sleepable)context.getBean("sleepable");
sleepable.sleep();

1.3 注解方式

Advice

@Aspect
public class SleepAdvice{

    public SleepAdvice(){

    }

    @Pointcut("execution(* *.sleep*())")
    public void sleeppoint(){}

    @Before("sleeppoint()")
    public void beforeSleep(){
        System.out.println("睡覺(jué)前要脫衣服!");
    }

    @AfterReturning("sleeppoint()")
    public void afterSleep(){
        System.out.println("睡醒了要穿衣服!");
    }


    @Around("sleeppoint()")
    public void aroundLala(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("快點(diǎn)睡覺(jué)?。?!");
        pjp.proceed();
        System.out.println("睡著了?。?!");
    }

}
<!--注解的形式啟用 AOP-->
    <aop:aspectj-autoproxy proxy-target-class="false"/>
     <!--&lt;!&ndash;定義通知內(nèi)容,也就是切入點(diǎn)執(zhí)行前后需要做的事情&ndash;&gt;-->
    <bean id="sleepAdvice" class="com.youzan.study.spring.aop.SleepAdvice"/>

這里先留一個(gè)問(wèn)題,針對(duì)注解方式,我們的輸出文本順序是什么?本文結(jié)束的時(shí)候有答案,讀者可先自己嘗試思考一下。

調(diào)用姿勢(shì)和配置的方式一樣

二、Spring AOP主鏈路概覽

主要鏈路

注解方式和配置方式屬于同類(lèi),基于BeanPostProcessor,在被加強(qiáng)類(lèi)完成實(shí)例化之后通過(guò)BeanPostProcessor進(jìn)行加強(qiáng)。

DefaultAdvisorAutoProxyCreator 和 AnnotationAwareAspectJAutoProxyCreator 都屬于BeanPostProcessor,我們看下他們的類(lèi)圖

aop BeanPostProcessor類(lèi)圖

三、核心概念

pointCut
切入點(diǎn),對(duì)什么進(jìn)行加強(qiáng)

advice
如何增強(qiáng),是具體的增強(qiáng)動(dòng)作

advisor
通知器,集成 pointCut和advice

spring aop主要有兩種實(shí)現(xiàn)方式,一種是jdk的動(dòng)態(tài)代理,另一種是基于cglib。

四、源碼解讀

4.1 編程方式

  1. 容器啟動(dòng)的時(shí)候,會(huì)將ProxyFactoryBean的實(shí)例創(chuàng)建完畢

  2. 獲取代理對(duì)象
    當(dāng)我們調(diào)用的時(shí)候

Sleepable sleepable = (Sleepable)context.getBean("sleepableProxy");

spring容器判斷ProxyFactoryBean是否創(chuàng)建完畢,如果創(chuàng)建完畢判斷是否是FacotryBean類(lèi)型,如果是的話(huà)調(diào)用 ProxyFactoryBean.getObject(),這塊可以參考IOC容器部分內(nèi)容,本章節(jié)不細(xì)講

下面看下ProxyFactoryBean如何getObject()

//ProxyFactoryBean
public Object getObject() throws BeansException {
    //初始化Advisor chain
    initializeAdvisorChain();
    if (isSingleton()) {
        //獲取或創(chuàng)建proxy 代理對(duì)象
        return getSingletonInstance();
    }
    else {
        if (this.targetName == null) {
            logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
                    "Enable prototype proxies by setting the 'targetName' property.");
        }
        return newPrototypeInstance();
    }
}
  1. Advisor chain初始化
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
    //是否已初始化
    if (this.advisorChainInitialized) {
        return;
    }

    //interceptorNames 就是spring里配置的advisor
    if (!ObjectUtils.isEmpty(this.interceptorNames)) {
        //省略部分代碼

        // Materialize interceptor chain from bean names.
        for (String name : this.interceptorNames) {
            //省略部分代碼

            else {
                // If we get here, we need to add a named interceptor.
                // We must check if it's a singleton or prototype.
                Object advice;
                if (this.singleton || this.beanFactory.isSingleton(name)) {
                    //從spring容器獲取 advisor對(duì)象
                    advice = this.beanFactory.getBean(name);
                }
                else {
                    // 非單例場(chǎng)景下創(chuàng)建 advisor對(duì)象
                    advice = new PrototypePlaceholderAdvisor(name);
                }

                //將advisor加入鏈中
                addAdvisorOnChainCreation(advice, name);
            }
        }
    }

    this.advisorChainInitialized = true;
}

調(diào)用鏈路
|--ProxyFactoryBean.initializeAdvisorChain
|----ProxyFactoryBean.addAdvisorOnChainCreation
|------AdvisedSupport.addAdvisor
|--------AdvisedSupport.addAdvisorInternal

最后會(huì)把a(bǔ)dvisor加入到 ProxyFactoryBean的 advisors (父類(lèi)AdvisedSupport的屬性 )里面,advisor的順序由用戶(hù)在spring里的配置決定。

  1. 創(chuàng)建Proxy對(duì)象

調(diào)用鏈路
|--ProxyFactoryBean.getObject
|----ProxyFactoryBean.getSingletonInstance
|------ProxyFactoryBean.createAopProxy
|--------ProxyCreatorSupport.createAopProxy
|----------DefaultAopProxyFactory.createAopProxy
|------ProxyFactoryBean.getProxy
|--------JdkDynamicAopProxy.getProxy (或CglibAopProxy)

如何決策使用jdk還是cglib?

//DefaultAopProxyFactory
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    //根據(jù) proxytargetclass或者 optimize 的配置,或者是否有接口來(lái)決策使用jdk動(dòng)態(tài)代理或者cglib
    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()) {
            return new JdkDynamicAopProxy(config);
        }
        return CglibProxyFactory.createCglibProxy(config);
    }
    else {
        return new JdkDynamicAopProxy(config);
    }
}
<!--編程方式啟用 AOP-->
<bean id="sleepableProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    <!-- 代理的對(duì)象,有睡覺(jué)能力 -->
    <property name="target" ref="sleepable"/>
    <!-- 使用切面 -->
    <property name="interceptorNames" value="sleepHelperAdvisor"/>
    <!-- 代理接口,睡覺(jué)接口 -->
    <property name="proxyInterfaces" value="com.youzan.study.spring.aop.Sleepable"/>
    <!--指定使用cglib-->
    <property name="optimize" value="true" />
</bean>

proxy對(duì)象的創(chuàng)建和調(diào)用,放到下面公共部分解讀

4.2 配置方式

相對(duì)于編程式的區(qū)別,就是不需要特意指定advisor和待加強(qiáng)對(duì)象之前的關(guān)系。

該方式的使用需要配置一個(gè)BeanPostProcessor即DefaultAdvisorAutoProxyCreator,當(dāng)待加強(qiáng)類(lèi)Bean實(shí)例化后會(huì)進(jìn)行BeanPostProcessor的加強(qiáng)。

  1. 加強(qiáng)的入口
    AbstractAutowireCapableBeanFactory#initializeBean
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    //省略部分代碼

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        //BeanPostProcessor 加強(qiáng)
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null),
                beanName, "Invocation of init method failed", ex);
    }

    if (mbd == null || !mbd.isSynthetic()) {
        //BeanPostProcessor 加強(qiáng),DefaultAdvisorAutoProxyCreator在這里開(kāi)始介入
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}
  1. 獲取加強(qiáng)proxy鏈路

|--AbstractAutowireCapableBeanFactory.
applyBeanPostProcessorsAfterInitialization
|----AbstractAutoProxyCreator.postProcessAfterInitialization
|------AbstractAutoProxyCreator.wrapIfNecessary
|--------AbstractAutoProxyCreator.getAdvicesAndAdvisorsForBean
|--------AbstractAutoProxyCreator.createProxy
|----------ProxyFactory.getProxy
|------------DefaultAopProxyFactory.createAopProxy
|--------------JdkDynamicAopProxy.getProxy (或CglibAopProxy)

AbstractAutoProxyCreator.getAdvicesAndAdvisorsForBean 如何尋找待加強(qiáng)類(lèi)對(duì)應(yīng)的advisors呢?

//AbstractAdvisorAutoProxyCreator
protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) {
    //獲取當(dāng)前容器所有的advisors,根據(jù)Advisor接口類(lèi)型進(jìn)行查找
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    //獲取適合當(dāng)前容器的advisors
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        //對(duì)advisor進(jìn)行排序
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}
  1. advisor的排序,為什么要排序呢?如果待加強(qiáng)類(lèi)適配的不僅僅一個(gè)advisor,那么誰(shuí)先誰(shuí)后呢?這基于OrderComparator進(jìn)行排序,而它的實(shí)現(xiàn)邏輯也是基于advisor的order來(lái)的。
public int compare(Object o1, Object o2) {
    boolean p1 = (o1 instanceof PriorityOrdered);
    boolean p2 = (o2 instanceof PriorityOrdered);
    if (p1 && !p2) {
        return -1;
    }
    else if (p2 && !p1) {
        return 1;
    }

    // Direct evaluation instead of Integer.compareTo to avoid unnecessary object creation.
    int i1 = getOrder(o1);
    int i2 = getOrder(o2);
    return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
}
  1. 查找匹配的advisors
//AbstractAdvisorAutoProxyCreator
protected List<Advisor> findAdvisorsThatCanApply(
            List<Advisor> candidateAdvisors, Class beanClass, String beanName) {

    ProxyCreationContext.setCurrentProxiedBeanName(beanName);
    try {
        //尋找匹配當(dāng)前類(lèi)的advisor
        return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    }
    finally {
        ProxyCreationContext.setCurrentProxiedBeanName(null);
    }
}

//真正的匹配邏輯 在 AopUtils
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
        Assert.notNull(pc, "Pointcut must not be null");
    //判斷類(lèi)是否匹配
    if (!pc.getClassFilter().matches(targetClass)) {
        return false;
    }

    //獲取pointcut 的方法匹配器
    MethodMatcher methodMatcher = pc.getMethodMatcher();
    IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
    if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
        introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
    }

    Set<Class> classes = new LinkedHashSet<Class>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
    classes.add(targetClass);
    for (Class<?> clazz : classes) {
        //讀取待加強(qiáng)類(lèi)所有的方法,查看是否有匹配上的
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            if ((introductionAwareMethodMatcher != null &&
                    introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
                    methodMatcher.matches(method, targetClass)) {
                return true;
            }
        }
    }

    return false;
}

如果沒(méi)有找到匹配的advisor,那么認(rèn)為該類(lèi)不需要加強(qiáng),直接返回原生的bean實(shí)例,反之走創(chuàng)建proxy的鏈路。

//AbstractAutoProxyCreator
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (beanName != null && this.targetSourcedBeans.containsKey(beanName)) {
        return bean;
    }
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }

    //判斷如果是advisor或者advice類(lèi)就加入到advisedBeans中,value=false,表示這些bean不需要進(jìn)行proxy后續(xù)邏輯
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    //查找是否有匹配的advisor
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        //創(chuàng)建 proxy對(duì)象
        Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }


    //標(biāo)記該類(lèi)不需要加強(qiáng),并返回普通的bean實(shí)例
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

4.3 注解方式

注解方式相比前兩種方式更為輕量,注解方式和配置方式相比編程方式對(duì)待加強(qiáng)類(lèi)零侵入、零耦合。

注解方式原理與配置方式類(lèi)似,都是基于BeanPostProcessor進(jìn)行bean實(shí)例加強(qiáng)。但是不同的是注解方式由spring aop模塊自動(dòng)向容器加入AnnotationAwareAspectJAutoProxyCreator BeanPostProcessor ,另外advisor也是程序基于代碼注解自動(dòng)提取和組裝。

使用注解

<aop:aspectj-autoproxy proxy-target-class="false"/>

相比<bean>標(biāo)簽,對(duì)應(yīng)的解析類(lèi)也是不一樣的。spring aop模塊下的spring.handlers 里指定 解析類(lèi) AopNamespaceHandler

//AopNamespaceHandler
public void init() {
    // In 2.0 XSD as well as in 2.1 XSD.
    registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
    registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
    registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

    // Only in 2.0 XSD: moved to context namespace as of 2.1
    registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}

我們使用的 aspectj-autoproxy剛好對(duì)應(yīng) AspectJAutoProxyBeanDefinitionParser。

容器注冊(cè)AnnotationAwareAspectJAutoProxyCreator BeanPostProcessor

//AspectJAutoProxyBeanDefinitionParser
public BeanDefinition parse(Element element, ParserContext parserContext) {
    //注冊(cè) AspectJAnnotationAutoProxyCreator
    AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
    //如果有子節(jié)點(diǎn)進(jìn)行子節(jié)點(diǎn)處理,暫未用到,暫時(shí)忽略
    extendBeanDefinition(element, parserContext);
    return null;
}

//AopNamespaceUtils
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            ParserContext parserContext, Element sourceElement) {

    //生成AspectJAnnotationAutoProxyCreator 的beanDefinition信息并注冊(cè)到容器中,
    //name=org.springframework.aop.config.internalAutoProxyCreator
    BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            parserContext.getRegistry(), parserContext.extractSource(sourceElement));

    //對(duì) aspectj-autoproxy 的屬性進(jìn)行組裝,比如proxy-target-class
    useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
    registerComponentIfNecessary(beanDefinition, parserContext);
}

接著在容器啟動(dòng)的過(guò)程中 registerBeanPostProcessors() 進(jìn)行實(shí)例化。

提取advisors
獲取加強(qiáng)proxy鏈路和配置方式一致,不同的在于注解方式獲取advisors是代碼自動(dòng)提取的,AnnotationAwareAspectJAutoProxyCreator把AbstractAdvisorAutoProxyCreator的findCandidateAdvisors覆蓋了,有了自己的實(shí)現(xiàn)邏輯

//AnnotationAwareAspectJAutoProxyCreator
protected List<Advisor> findCandidateAdvisors() {
    //調(diào)用父類(lèi)的方法,檢索容器中所有的advisor
    List<Advisor> advisors = super.findCandidateAdvisors();
    //構(gòu)建加AspectJ注解的advisor
    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    return advisors;
}

根據(jù)加@Aspect注解的bean生成advisors的調(diào)用鏈路

|--BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors
|----ReflectiveAspectJAdvisorFactory.getAdvisors
|------ReflectiveAspectJAdvisorFactory.getAdvisor
|--------new InstantiationModelAwarePointcutAdvisorImpl()
|----------InstantiationModelAwarePointcutAdvisorImpl.instantiateAdvice
|------------ReflectiveAspectJAdvisorFactory.getAdvice

//BeanFactoryAspectJAdvisorsBuilder
public List<Advisor> buildAspectJAdvisors() {
        List<String> aspectNames = null;

    //省略一大段代碼,代碼篇幅較長(zhǎng),可以認(rèn)為 它把spring容器中的bean都拿了出來(lái),
    //然后判斷是否添加了 @Aspect 注解

    //根據(jù)提取出來(lái)的 @Aspect 進(jìn)行進(jìn)一步的組裝,獲取到具體的Advisor并添加到 advisors中返回
    List<Advisor> advisors = new LinkedList<Advisor>();
    for (String aspectName : aspectNames) {
        //從緩存中讀取已經(jīng)生成的 advisors
        List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
        if (cachedAdvisors != null) {
            advisors.addAll(cachedAdvisors);
        }
        else {
            MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
            //具體生成advisors 的邏輯
            advisors.addAll(this.advisorFactory.getAdvisors(factory));
        }
    }
    return advisors;
}
//ReflectiveAspectJAdvisorFactory
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) {
    final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass();
    final String aspectName = maaif.getAspectMetadata().getAspectName();
    validate(aspectClass);
    final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
            new LazySingletonAspectInstanceFactoryDecorator(maaif);

    final List<Advisor> advisors = new LinkedList<Advisor>();

    //getAdvisorMethods(aspectClass) 會(huì)找到所有加注解的方法
    for (Method method : getAdvisorMethods(aspectClass)) {
        Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }

    // 省略部分代碼,平時(shí)沒(méi)有用到這些場(chǎng)景,這里就不解讀了

    return advisors;
}

getAdvisorMethods方法,會(huì)把所有帶有注解的方法給提取出來(lái),提取后會(huì)對(duì)方法進(jìn)行排序,因?yàn)樵诤竺嬖O(shè)置advice order的時(shí)候有一個(gè)聲明順序,會(huì)起到一定的優(yōu)先級(jí)影響。

//ReflectiveAspectJAdvisorFactory
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
    final List<Method> methods = new LinkedList<Method>();
    ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
        public void doWith(Method method) throws IllegalArgumentException {
            // Exclude pointcuts
            if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
                methods.add(method);
            }
        }
    });
    //對(duì)方法進(jìn)行排序
    Collections.sort(methods, METHOD_COMPARATOR);
    return methods;
}

方法的排序規(guī)則

Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class

按照上面的注解順序進(jìn)行排序,如果不屬于上面的注解類(lèi)型,排序統(tǒng)一為方法總數(shù)量。

ReflectiveAspectJAdvisorFactory.getAdvisor

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif,
            int declarationOrderInAspect, String aspectName) {

    validate(aif.getAspectMetadata().getAspectClass());

    //提取 pointcut,如果為空則返回null
    AspectJExpressionPointcut ajexp =
            getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass());
    if (ajexp == null) {
        return null;
    }

    //生成InstantiationModelAwarePointcutAdvisorImpl advisor, 
    //advice=aif(可以認(rèn)為是當(dāng)前加了@Aspect的advice類(lèi)), pointcut 就是根據(jù)注解提取出來(lái)的
    return new InstantiationModelAwarePointcutAdvisorImpl(
            this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName);
}

getAdvice的邏輯

//ReflectiveAspectJAdvisorFactory
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp,
            MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) {

    Class<?> candidateAspectClass = aif.getAspectMetadata().getAspectClass();
    validate(candidateAspectClass);

    //獲取當(dāng)前方法注解
    AspectJAnnotation<?> aspectJAnnotation =
            AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    if (aspectJAnnotation == null) {
        return null;
    }

    // Check 是否是 AspectJ-annotated class
    if (!isAspect(candidateAspectClass)) {
        throw new AopConfigException("Advice must be declared inside an aspect type: " +
                "Offending method '" + candidateAdviceMethod + "' in class [" +
                candidateAspectClass.getName() + "]");
    }

    //省略部分代碼

    AbstractAspectJAdvice springAdvice;

    //不同的注解類(lèi)型,不同的advice
    switch (aspectJAnnotation.getAnnotationType()) {
        case AtBefore:
            springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif);
            break;
        case AtAfter:
            springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif);
            break;
        case AtAfterReturning:
            springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif);
            //省略部分代碼
            break;
        case AtAfterThrowing:
            springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif);
            AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
            //省略部分代碼
            break;
        case AtAround:
            springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif);
            break;
        case AtPointcut:
            if (logger.isDebugEnabled()) {
                logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
            }
            return null;
        default:
            throw new UnsupportedOperationException(
                    "Unsupported advice type on method " + candidateAdviceMethod);
    }

    // Now to configure the advice...
    springAdvice.setAspectName(aspectName);

    //設(shè)置advice的 聲明順序,當(dāng)advice order 順序一樣的時(shí)候,該排序會(huì)有一定的影響
    springAdvice.setDeclarationOrder(declarationOrderInAspect);
    String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
    if (argNames != null) {
        springAdvice.setArgumentNamesFromStringArray(argNames);
    }
    springAdvice.calculateArgumentBindings();
    return springAdvice;
}

幾個(gè)advice類(lèi)型的類(lèi)圖我們看下


advice類(lèi)圖

Advisor 優(yōu)先級(jí)
Advisor的優(yōu)先級(jí)邏輯,配置方式和注解方式一致。

我們的advisor已經(jīng)生成完畢,advisor的優(yōu)先級(jí)排序邏輯入口在AspectJAwareAdvisorAutoProxyCreator.sortAdvisors。

Advisor排序鏈路
|--AspectJAwareAdvisorAutoProxyCreator.sortAdvisors
|----PartialOrder.sort
|------PartialOrder.addNewPartialComparable
|--------PartialOrder.addDirectedLinks
|----------AspectJPrecedenceComparator.compare
|------------AspectJPrecedenceComparator.comparePrecedenceWithinAspect

排序中最為關(guān)鍵的點(diǎn)
PartialOrder.addNewPartialComparable 這一步,將待排序的對(duì)象包裝成PartialOrder.SortObject對(duì)象,這個(gè)對(duì)象有三個(gè)屬性

//advisor holder
PartialComparable object;
//比當(dāng)前advisor order 小的Advisors
List<SortObject> smallerObjects = new LinkedList<SortObject>();
//比當(dāng)前advisor order 大的Advisors
List<SortObject> biggerObjects = new LinkedList<SortObject>();

PartialOrder.sort就是針對(duì)上面處理之后的SortObjects進(jìn)行排序。

排序規(guī)則首先獲取Advisor的order,小的優(yōu)先級(jí)最高,如果order一樣則取 declareOrder也就前面說(shuō)的聲明順序,這里需要注意的是,聲明順序并發(fā)是和我們代碼里的屬性一致,它是經(jīng)過(guò)排序的,排序邏輯向上可以找下。

當(dāng)Advisor的order一樣后,排序會(huì)進(jìn)入到下面的邏輯
AspectJPrecedenceComparator.comparePrecedenceWithinAspect

private int comparePrecedenceWithinAspect(Advisor advisor1, Advisor advisor2) {
    
    //兩個(gè)Advisor 是否其中一個(gè)或者全部都是 after類(lèi)型的Advisor
    boolean oneOrOtherIsAfterAdvice =
            (AspectJAopUtils.isAfterAdvice(advisor1) || AspectJAopUtils.isAfterAdvice(advisor2));        
    int adviceDeclarationOrderDelta = getAspectDeclarationOrder(advisor1) - getAspectDeclarationOrder(advisor2);

    if (oneOrOtherIsAfterAdvice) {
        //如果其中一個(gè)或者全部是 after類(lèi)型的,先聲明的優(yōu)先級(jí)反而低
        if (adviceDeclarationOrderDelta < 0) {
            return LOWER_PRECEDENCE;
        }
        else if (adviceDeclarationOrderDelta == 0) {
            return SAME_PRECEDENCE;
        }
        else {
            return HIGHER_PRECEDENCE;
        }
    }
    else {
        //如果不是after類(lèi)型的,哪個(gè)方法先聲明則擁有更高的優(yōu)先級(jí)。
        if (adviceDeclarationOrderDelta < 0) {
            return HIGHER_PRECEDENCE;
        }
        else if (adviceDeclarationOrderDelta == 0) {
            return SAME_PRECEDENCE;
        }
        else {
            return LOWER_PRECEDENCE;
        }
    }
}

4.4 proxy調(diào)用解讀

本小節(jié),三種aop使用方式的proxy創(chuàng)建和調(diào)用邏輯相同,所以放到一起進(jìn)行講解

創(chuàng)建proxy創(chuàng)建

//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);
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);

    //原聲帶jdk創(chuàng)建proxy的api調(diào)用
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

使用的是原生的jdk 動(dòng)態(tài)代理api

proxy方法調(diào)用
當(dāng)我們獲得到proxy之后,然后調(diào)用業(yè)務(wù)方法的時(shí)候,執(zhí)行鏈路最終到了 proxy的invoke方法。

調(diào)用鏈路
|--JdkDynamicAopProxy.invoke
|----AdvisedSupport.getInterceptorsAndDynamicInterceptionAdvice
|------DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice
|--------MethodBeforeAdviceAdapter.getInterceptor
|--------AfterReturningAdviceAdapter.getInterceptor
|----ReflectiveMethodInvocation.proceed
|------MethodBeforeAdviceInterceptor.invoke
|------AfterReturningAdviceInterceptor.invoke

JdkDynamicAopProxy.invoke方法

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 {
        //省略部分代碼

        //獲取當(dāng)前執(zhí)行對(duì)象匹配的advice chain
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

        
        
        if (chain.isEmpty()) {
            //如果chain為空,直接執(zhí)行targetd fangf 
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
        }
        else {
            // We need to create a method invocation...
            invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            //開(kāi)始執(zhí)行邏輯,并返回結(jié)果
            retVal = invocation.proceed();
        }

        //省略部分代碼

        return retVal;
    }
    finally {
        if (target != null && !targetSource.isStatic()) {
            // Must have come from TargetSource.
            targetSource.releaseTarget(target);
        }
        if (setProxyContext) {
            // Restore old proxy.
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}

獲取當(dāng)前方法的advice鏈,邏輯入口
AdvisedSupport.getInterceptorsAndDynamicInterceptionAdvice
具體實(shí)現(xiàn)在DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
            Advised config, Method method, Class targetClass) {

    List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
    boolean hasIntroductions = hasMatchingIntroductions(config, targetClass);
    AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

    //循環(huán)當(dāng)前targetClass的advisors
    for (Advisor advisor : config.getAdvisors()) {
        if (advisor instanceof PointcutAdvisor) {
            //獲取當(dāng)前advisor的pointcut
            PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
            if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {

                //根據(jù)advisor獲取interceptors
                MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();

                //判斷當(dāng)前方法是否匹配當(dāng)前advisor的pointcut
                if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) {
                    if (mm.isRuntime()) {
                        for (MethodInterceptor interceptor : interceptors) {
                            interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                        }
                    }
                    else {
                        //將當(dāng)前advisor對(duì)應(yīng)interceptors 加入到 interceptorList
                        interceptorList.addAll(Arrays.asList(interceptors));
                    }
                }
            }
        }else if (advisor instanceof IntroductionAdvisor) {
            IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
            if (config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) {
                Interceptor[] interceptors = registry.getInterceptors(advisor);
                interceptorList.addAll(Arrays.asList(interceptors));
            }
        }
        else {
            //如果不是上述兩種類(lèi)型,則作為Interceptor 直接加入 比如 ExposeInvocationInterceptor
            Interceptor[] interceptors = registry.getInterceptors(advisor);
            interceptorList.addAll(Arrays.asList(interceptors));
        }
    }
    return interceptorList;
}

如何根據(jù)advisor獲取interceptors ?

//DefaultAdvisorAdapterRegistry
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
    List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
    Advice advice = advisor.getAdvice();
    if (advice instanceof MethodInterceptor) {
        interceptors.add((MethodInterceptor) advice);
    }
    for (AdvisorAdapter adapter : this.adapters) {
        if (adapter.supportsAdvice(advice)) {
            interceptors.add(adapter.getInterceptor(advisor));
        }
    }
    if (interceptors.isEmpty()) {
        throw new UnknownAdviceTypeException(advisor.getAdvice());
    }
    return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
}

adapters 在DefaultAdvisorAdapterRegistry實(shí)例化的時(shí)候完成裝配

public DefaultAdvisorAdapterRegistry() {
    registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
    registerAdvisorAdapter(new AfterReturningAdviceAdapter());
    registerAdvisorAdapter(new ThrowsAdviceAdapter());
}

這些adapters判斷是否支持當(dāng)前advisor的advice,我們以MethodBeforeAdviceAdapter 為例

public boolean supportsAdvice(Advice advice) {
    return (advice instanceof MethodBeforeAdvice);
}

getInterceptor邏輯

public MethodInterceptor getInterceptor(Advisor advisor) {
    MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
    return new MethodBeforeAdviceInterceptor(advice);
}

現(xiàn)在我們獲取到了當(dāng)前方法匹配的MethodInterceptor,最后也就是 MethodInterceptor chain。接下來(lái)看下具體的執(zhí)行邏輯ReflectiveMethodInvocation.proceed()

public Object proceed() throws Throwable {
    //interceptors chain執(zhí)行完畢,則開(kāi)始執(zhí)行target的method
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        return invokeJoinpoint();
    }

    //MethodInterceptor chain每執(zhí)行一個(gè),currentInterceptorIndex + 1
    Object interceptorOrInterceptionAdvice =
            this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
        //省略代碼,本篇使用的樣例,不會(huì)走到該邏輯
    }
    else {
        // 按照 MethodInterceptor chain執(zhí)行邏輯
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}

jdk的動(dòng)態(tài)代理就介紹到這了,cglib方式的先不介紹了,當(dāng)然本篇也并非面面俱到,如果有朋友對(duì)本篇沒(méi)有提及部分感興趣的話(huà),可以按照這個(gè)思路自己探索一番。
有興趣的朋友可以自行研究下,這里就不介紹了。

五、Spring AOP 不生效的探索

在使用spring aop的時(shí)候,可能我們會(huì)時(shí)不時(shí)的出現(xiàn)aop不生效的問(wèn)題,最常見(jiàn)的莫過(guò)于spring的事務(wù),為什么有時(shí)候不生效呢?


代理類(lèi)結(jié)構(gòu)內(nèi)視圖

通過(guò)上面的幾個(gè)章節(jié),這個(gè)圖大家不難理解,
前提
我們有 method A 和 methodB的兩個(gè)切面
case1:調(diào)用 C.A, 方法A切面生效
case2: 調(diào)用C.B, 方法B切面生效
case3: 調(diào)用C.A, C.A調(diào)用C.B,方法A切面生效, 方法B切面失效。
通過(guò)圖中表述,當(dāng)方法A切面生效的時(shí)候,調(diào)用到 目標(biāo)類(lèi)C的B方法,這時(shí)候調(diào)用B的對(duì)象是目標(biāo)類(lèi)C而非 代理對(duì)象,所以對(duì)方法B的加強(qiáng)會(huì)不起作用


文章開(kāi)頭的問(wèn)題答案如下:

輸出內(nèi)容
快點(diǎn)睡覺(jué)!??!
睡覺(jué)前要脫衣服!
睡覺(jué)!不休息哪里有力氣學(xué)習(xí)!
lalala
睡著了?。?!
睡醒了要穿衣服!


系列文章
spring源碼探索(0)-IOC容器-架構(gòu)設(shè)計(jì)
spring源碼探索(1)-IOC容器-Resource
spring源碼探索(2)-IOC容器-BeanDefinition加載與注冊(cè)
spring源碼探索(3)-IOC容器-Bean的一生
spring源碼探索(4)-AOP實(shí)現(xiàn)原理

最后編輯于
?著作權(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)容