Spring源碼解析之基于注解的SpringAOP源碼解析(一)

Spring源碼解析之基于注解的SpringAOP源碼解析(一)

本文分析Spring的AOP模塊的整體流程袱院,分析過程需要使用一個(gè)簡單的demo工程來啟動(dòng)Spring嘁字。

https://github.com/cjinjun/spring-framework-demo

寫一個(gè)簡單的接口和實(shí)現(xiàn)類蒿往,跟IOC源碼解析那幾篇文章用的同一個(gè)工程劣欢,

public interface IOCService {
    public String helloIoc();
}

public class IOCServiceImpl implements IOCService {
    public String helloIoc() {
        return "Hello,IOC";
    }
}

增加bean的配置類棕诵,以及啟動(dòng)AOP

@EnableAspectJAutoProxy
@Configuration
public class AnnotationConfig {
    @Bean
    public IOCService iocService(){
        return new IOCServiceImpl();
    }
}

創(chuàng)建切點(diǎn)

@Aspect
@Component
public class AspectJTest {

    @Pointcut("execution(public * com.jinjun.demo.ioc.service..IOCService.helloIoc(..))")
    public void testAOP(){}

    @Before("testAOP()")
    public void before(){
        System.out.println("before AOP...");
    }

    @After("testAOP()")
    public void after(){
        System.out.println("after AOP...");
    }

    @Around("testAOP()")
    public Object around(ProceedingJoinPoint p){
        System.out.println("around before AOP...");
        Object o = null;
        try {
            o = p.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        System.out.println("around after AOP...");
        return o;
    }
}

啟動(dòng)spring

public class AnnotationIOCDemo {
    public static void main (String args[]){
        ApplicationContext context = new AnnotationConfigApplicationContext("cn.shiyujun.config");
        IOCService iocService=context.getBean(IOCService.class);
        System.out.println(iocService.@EnableAspectJAutoProxy注解());
    }
}

代碼部分到此裁良,然后首先看一下

@EnableAspectJAutoProxy注解

為了開啟AOP功能,使用了一個(gè)@EnableAspectJAutoProxy注解校套,進(jìn)入這個(gè)注解可以查看到這個(gè)注解的2個(gè)屬性价脾,相信大家都已經(jīng)很熟悉了,就不相信的說明了笛匙。除此之外可以看到這個(gè)注解使用@Import注解引入了一個(gè)配置類

@Import注解:可以引入一個(gè)類侨把,將這個(gè)類注入到Spring IOC容器中被當(dāng)前Spring管理

@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
    //proxyTargetClass屬性,默認(rèn)false妹孙,嘗試采用JDK動(dòng)態(tài)代理織入增強(qiáng)(如果當(dāng)前類沒有實(shí)現(xiàn)接口則還是會(huì)使用CGLIB)秋柄;如果設(shè)為true,則強(qiáng)制采用CGLIB動(dòng)態(tài)代理織入增強(qiáng)
    boolean proxyTargetClass() default false;
    //通過aop框架暴露該代理對(duì)象蠢正,aopContext能夠訪問骇笔。為了解決類內(nèi)部方法之間調(diào)用時(shí)無法增強(qiáng)的問題
    boolean exposeProxy() default false;
}

看一下這個(gè)配置類的操作

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    AspectJAutoProxyRegistrar() {
    }

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
               //注冊(cè)一個(gè)AOP代理實(shí)現(xiàn)的Bean,往下看          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);
            }
        }

    }
}

registerAspectJAnnotationAutoProxyCreatorIfNecessary方法的主要功能是注冊(cè)或者升級(jí)AnnotationAwareAspectJAutoProxyCreator類机隙,這個(gè)類在AOP中非常的重要蜘拉,它的主要功能就是根據(jù)@Point注解定義的切點(diǎn)來自動(dòng)代理與表達(dá)式匹配的類。下面看一個(gè)這個(gè)實(shí)現(xiàn)的邏輯

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); //如果已存在這個(gè)bean
        if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
            BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
            //判斷優(yōu)先級(jí)有鹿,如果優(yōu)先級(jí)較高則替換原先的bean
            if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
                int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
                int requiredPriority = findPriorityForClass(cls);
                if (currentPriority < requiredPriority) {
                    apcDefinition.setBeanClassName(cls.getName());
                }
            }

            return null;
        } else {
            //注冊(cè)AnnotationAwareAspectJAutoProxyCreator到容器中旭旭,此類負(fù)責(zé)基于注解的AOP動(dòng)態(tài)代理實(shí)現(xiàn)
            RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
            beanDefinition.setSource(source);
            beanDefinition.getPropertyValues().add("order", -2147483648);
            beanDefinition.setRole(2);
            registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
            return beanDefinition;
        }
    }

注冊(cè)的AnnotationAwareAspectJAutoProxyCreator這個(gè)類間接實(shí)現(xiàn)了BeanPostProcessor接口。還記得我們之前在對(duì)SpringIOC的源碼進(jìn)行解析時(shí)提到過葱跋,Spring在實(shí)例化Bean的前后會(huì)分別調(diào)用方法postProcessBeforeInstantiation和postProcessAfterInstantiation而AOP的整體邏輯就是通過這兩個(gè)方法來實(shí)現(xiàn)的

postProcessBeforeInstantiation

首先看一下這個(gè)postProcessBeforeInstantiation方法持寄,它是在bean實(shí)例化之前調(diào)用的,主要是針對(duì)切面類娱俺。這個(gè)方法不在AnnotationAwareAspectJAutoProxyCreator這個(gè)類中稍味,而是在其父類AbstractAutoProxyCreator中

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

    if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
      if (this.advisedBeans.containsKey(cacheKey)) {
        return null;
      }
            //加載所有增強(qiáng)
      if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return null;
      }
    }

    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;
  }

加載增強(qiáng)

上方代碼中最重要的一個(gè)方法就是shouldSkip方法了,被AspectJAwareAdvisorAutoProxyCreator所重載

protected boolean shouldSkip(Class<?> beanClass, String beanName) {
  
    //查找所有標(biāo)識(shí)了@Aspect注解的類荠卷,這里是重點(diǎn)模庐,接著往下看
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    for (Advisor advisor : candidateAdvisors) {
        if (advisor instanceof AspectJPointcutAdvisor) {
            if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
                return true;
            }
        }
    }
    return super.shouldSkip(beanClass, beanName);
    }


    protected List<Advisor> findCandidateAdvisors() {
        return this.advisorRetrievalHelper.findAdvisorBeans();
    }
    
    protected List<Advisor> findCandidateAdvisors() {
        List<Advisor> advisors = super.findCandidateAdvisors();
        //buildAspectJAdvisors是重點(diǎn)
           advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        return advisors;
    }
public List<Advisor> buildAspectJAdvisors() {
//所有Aspect類的名稱集合
    List<String> aspectNames = this.aspectBeanNames;
    if (aspectNames == null) {
        synchronized (this) {
            aspectNames = this.aspectBeanNames;
            //這個(gè)雙重檢查是不是在學(xué)習(xí)安全的單例模式的時(shí)候見過
            if (aspectNames == null) {
                List<Advisor> advisors = new LinkedList<Advisor>();
                aspectNames = new LinkedList<String>();
                //獲取所有Bean名稱
                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                        this.beanFactory, Object.class, true, false);
                for (String beanName : beanNames) {
                    //判斷是否符合條件,比如說有時(shí)會(huì)排除一些類油宜,不讓這些類注入進(jìn)Spring
                    if (!isEligibleBean(beanName)) {
                        continue;
                    }
           
                    Class<?> beanType = this.beanFactory.getType(beanName);
                    if (beanType == null) {
                        continue;
                    }
                    //判斷Bean的Class上是否標(biāo)識(shí)@Aspect注解
                    if (this.advisorFactory.isAspect(beanType)) {
                        aspectNames.add(beanName);
                        AspectMetadata amd = new AspectMetadata(beanType, beanName);
                        if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                            MetadataAwareAspectInstanceFactory factory =
                                    new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                            //下一步說掂碱,重點(diǎn)的重點(diǎn)
                            List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                            if (this.beanFactory.isSingleton(beanName)) {
                                //將解析的Bean名稱及類上的增強(qiáng)緩存起來,每個(gè)Bean只解析一次
                                this.advisorsCache.put(beanName, classAdvisors);
                            }
                            else {
                                this.aspectFactoryCache.put(beanName, factory);
                            }
                            advisors.addAll(classAdvisors);
                        }
                        else {
                            if (this.beanFactory.isSingleton(beanName)) {
                                throw new IllegalArgumentException("Bean with name '" + beanName +
                                        "' is a singleton, but aspect instantiation model is not singleton");
                            }
                            MetadataAwareAspectInstanceFactory factory =
                                    new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                            this.aspectFactoryCache.put(beanName, factory);
                            advisors.addAll(this.advisorFactory.getAdvisors(factory));
                        }
                    }
                }

                this.aspectBeanNames = aspectNames;
                return advisors;
            }
        }
    }

    if (aspectNames.isEmpty()) {
        return Collections.emptyList();
    }
    List<Advisor> advisors = new LinkedList<Advisor>();
    for (String aspectName : aspectNames) {
        //從緩存中獲取當(dāng)前Bean的切面實(shí)例,如果不為空慎冤,則指明當(dāng)前Bean的Class標(biāo)識(shí)了@Aspect疼燥,且有切面方法
        List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
        if (cachedAdvisors != null) {
            advisors.addAll(cachedAdvisors);
        }
        else {
            MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
            advisors.addAll(this.advisorFactory.getAdvisors(factory));
        }
    }
    return advisors;
}

生成增強(qiáng)

advisorFactory.getAdvisors方法會(huì)從@Aspect標(biāo)識(shí)的類上獲取@Before,@Pointcut等注解的信息及其標(biāo)識(shí)的方法的信息蚁堤,生成增強(qiáng)

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
    Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
    //校驗(yàn)類的合法性相關(guān)
    validate(aspectClass);

    MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
            new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

    List<Advisor> advisors = new LinkedList<Advisor>();
    //獲取這個(gè)類所有的增強(qiáng)方法
    for (Method method : getAdvisorMethods(aspectClass)) {
        //生成增強(qiáng)實(shí)例
        Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }

    if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
        Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
        advisors.add(0, instantiationAdvisor);
    }

    for (Field field : aspectClass.getDeclaredFields()) {
        Advisor advisor = getDeclareParentsAdvisor(field);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }

    return advisors;
}

//獲取類的的方法
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
    final List<Method> methods = new LinkedList<Method>();
    ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
        @Override
        public void doWith(Method method) throws IllegalArgumentException {
                //在@Aspect標(biāo)識(shí)的類內(nèi)部排除@Pointcut標(biāo)識(shí)之外的所有方法醉者,得到的方法集合包括繼承自父類的方法,包括繼承自O(shè)bject的方法
            if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
                methods.add(method);
            }
        }
    });
    //對(duì)得到的所有方法排序,
    //如果方法標(biāo)識(shí)了切面注解撬即,則按@Around, @Before, @After, @AfterReturning, @AfterThrowing的順序排序
    //如果沒有標(biāo)識(shí)這些注解立磁,則按方法名稱的字符串排序,
    //有注解的方法排在無注解的方法之前
    //最后的排序應(yīng)該是這樣的Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class。搞莺。息罗。
    Collections.sort(methods, METHOD_COMPARATOR);
    return methods;
}

調(diào)用生成增強(qiáng)實(shí)例的方法

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
        int declarationOrderInAspect, String aspectName) {
    //再次校驗(yàn)類的合法性
    validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
    //切點(diǎn)表達(dá)式的包裝類里面包含這些東西:execution(public * cn.shiyujun.service.IOCService.hollo(..))
    AspectJExpressionPointcut expressionPointcut = getPointcut(
            candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
    if (expressionPointcut == null) {
        return null;
    }
    //根據(jù)方法、切點(diǎn)才沧、AOP實(shí)例工廠迈喉、類名、序號(hào)生成切面實(shí)例温圆,詳細(xì)代碼往下看
    return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
            this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
    //查詢方法上的切面注解挨摸,根據(jù)注解生成相應(yīng)類型的AspectJAnnotation,在調(diào)用AspectJAnnotation的構(gòu)造函數(shù)的同時(shí)
    //根據(jù)注解value或pointcut屬性得到切點(diǎn)表達(dá)式,有argNames則設(shè)置參數(shù)名稱
    AspectJAnnotation<?> aspectJAnnotation =
            AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    //過濾那些不含@Before, @Around, @After, @AfterReturning, @AfterThrowing注解的方法
    if (aspectJAnnotation == null) {
        return null;
    }
    //生成帶表達(dá)式的切面切入點(diǎn)岁歉,設(shè)置其切入點(diǎn)表達(dá)式
    AspectJExpressionPointcut ajexp =
            new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
    ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
    ajexp.setBeanFactory(this.beanFactory);
    return ajexp;
}

InstantiationModelAwarePointcutAdvisorImpl的構(gòu)造方法

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
      Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
      MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

    this.declaredPointcut = declaredPointcut;
    this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
    this.methodName = aspectJAdviceMethod.getName();
    this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
    this.aspectJAdviceMethod = aspectJAdviceMethod;
    this.aspectJAdvisorFactory = aspectJAdvisorFactory;
    this.aspectInstanceFactory = aspectInstanceFactory;
    this.declarationOrder = declarationOrder;
    this.aspectName = aspectName;

    if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
      Pointcut preInstantiationPointcut = Pointcuts.union(
          aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);

      this.pointcut = new PerTargetInstantiationModelPointcut(
          this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
      this.lazy = true;
    }
    else {
      this.pointcut = this.declaredPointcut;
      this.lazy = false;
            //重點(diǎn)在這里
      this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
    }
  }
    
    private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
    //再往下看
    Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
        this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
    return (advice != null ? advice : EMPTY_ADVICE);
  }

生產(chǎn)增強(qiáng)

public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {

    public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
            MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

        Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
        //又是一次校驗(yàn)
        validate(candidateAspectClass);

        AspectJAnnotation<?> aspectJAnnotation =
                AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
        if (aspectJAnnotation == null) {
            return null;
        }

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

        if (logger.isDebugEnabled()) {
            logger.debug("Found AspectJ method: " + candidateAdviceMethod);
        }

        AbstractAspectJAdvice springAdvice;
        //根據(jù)注解類型生成不同的通知實(shí)例
        switch (aspectJAnnotation.getAnnotationType()) {
            case AtBefore:
                springAdvice = new AspectJMethodBeforeAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            case AtAfter:
                springAdvice = new AspectJAfterAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            case AtAfterReturning:
                springAdvice = new AspectJAfterReturningAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
                if (StringUtils.hasText(afterReturningAnnotation.returning())) {
                    springAdvice.setReturningName(afterReturningAnnotation.returning());
                }
                break;
            case AtAfterThrowing:
                springAdvice = new AspectJAfterThrowingAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
                if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
                    springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
                }
                break;
            case AtAround:
                springAdvice = new AspectJAroundAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            case AtPointcut:
                if (logger.isDebugEnabled()) {
                    logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
                }
                return null;
            default:
                throw new UnsupportedOperationException(
                        "Unsupported advice type on method: " + candidateAdviceMethod);
        }

        //設(shè)置通知方法所屬的類
        springAdvice.setAspectName(aspectName);
        //設(shè)置通知的序號(hào),同一個(gè)類中有多個(gè)切面注解標(biāo)識(shí)的方法時(shí),按上方說的排序規(guī)則來排序忽媒,
        //其序號(hào)就是此方法在列表中的序號(hào)蟹漓,第一個(gè)就是0
        springAdvice.setDeclarationOrder(declarationOrder);
        //獲取通知方法的所有參數(shù)
        String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
        //將通知方法上的參數(shù)設(shè)置到通知中
        if (argNames != null) {
            springAdvice.setArgumentNamesFromStringArray(argNames);
        }
        //計(jì)算參數(shù)綁定工作,此方法詳解請(qǐng)接著往下看
        springAdvice.calculateArgumentBindings();
        return springAdvice;
    }
}

校驗(yàn)方法參數(shù)并綁定

public synchronized final void calculateArgumentBindings() {
    if (this.argumentsIntrospected || this.parameterTypes.length == 0) {
        return;
    }

    int numUnboundArgs = this.parameterTypes.length;
    Class<?>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
    //切面注解標(biāo)識(shí)的方法第一個(gè)參數(shù)要求是JoinPoint,或StaticPart,若是@Around注解則也可以是ProceedingJoinPoint
    if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0])) {
        numUnboundArgs--;
    }
    else if (maybeBindJoinPointStaticPart(parameterTypes[0])) {
        numUnboundArgs--;
    }

    if (numUnboundArgs > 0) {
    //綁定屬性
        bindArgumentsByName(numUnboundArgs);
    }

    this.argumentsIntrospected = true;
}
private void bindArgumentsByName(int numArgumentsExpectingToBind) {
    if (this.argumentNames == null) { //獲取方法參數(shù)的名稱
        this.argumentNames = createParameterNameDiscoverer().getParameterNames(this.aspectJAdviceMethod);
    }
    if (this.argumentNames != null) {
        // 往下看
        bindExplicitArguments(numArgumentsExpectingToBind);
    }
    else {
        throw new IllegalStateException("Advice method [" + this.aspectJAdviceMethod.getName() + "] " +
                "requires " + numArgumentsExpectingToBind + " arguments to be bound by name, but " +
                "the argument names were not specified and could not be discovered.");
    }
}

private void bindExplicitArguments(int numArgumentsLeftToBind) {
    //此屬性用來存儲(chǔ)方法未綁定的參數(shù)名稱万牺,及參數(shù)的序號(hào)
    this.argumentBindings = new HashMap<String, Integer>();

    int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterTypes().length;
    if (this.argumentNames.length != numExpectedArgumentNames) {
        throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames +
                " arguments to bind by name in advice, but actually found " +
                this.argumentNames.length + " arguments.");
    }

    // So we match in number...,argumentIndexOffset代表第一個(gè)未綁定參數(shù)的順序 
    int argumentIndexOffset = this.parameterTypes.length - numArgumentsLeftToBind;
    for (int i = argumentIndexOffset; i < this.argumentNames.length; i++) {
        //存儲(chǔ)未綁定的參數(shù)名稱及其順序的映射關(guān)系
        this.argumentBindings.put(this.argumentNames[i], i);
    }

    // Check that returning and throwing were in the argument names list if
    // specified, and find the discovered argument types.
    //如果是@AfterReturning注解的returningName 有值蛛碌,驗(yàn)證寥殖,解析宙暇,同時(shí)得到定義返回值的類型
    if (this.returningName != null) {
        if (!this.argumentBindings.containsKey(this.returningName)) {
            throw new IllegalStateException("Returning argument name '" + this.returningName +
                    "' was not bound in advice arguments");
        }
        else {
            Integer index = this.argumentBindings.get(this.returningName);
            this.discoveredReturningType = this.aspectJAdviceMethod.getParameterTypes()[index];
            this.discoveredReturningGenericType = this.aspectJAdviceMethod.getGenericParameterTypes()[index];
        }
    }
    //如果是@AfterThrowing注解的throwingName 有值,驗(yàn)證备绽,解析券坞,同時(shí)得到拋出異常的類型
    if (this.throwingName != null) {
        if (!this.argumentBindings.containsKey(this.throwingName)) {
            throw new IllegalStateException("Throwing argument name '" + this.throwingName +
                    "' was not bound in advice arguments");
        }
        else {
            Integer index = this.argumentBindings.get(this.throwingName);
            this.discoveredThrowingType = this.aspectJAdviceMethod.getParameterTypes()[index];
        }
    }

    // configure the pointcut expression accordingly.
    configurePointcutParameters(argumentIndexOffset);
}

private void configurePointcutParameters(int argumentIndexOffset) {
    int numParametersToRemove = argumentIndexOffset;
    if (this.returningName != null) {
        numParametersToRemove++;
    }
    if (this.throwingName != null) {
        numParametersToRemove++;
    }
    String[] pointcutParameterNames = new String[this.argumentNames.length - numParametersToRemove];
    Class<?>[] pointcutParameterTypes = new Class<?>[pointcutParameterNames.length];
    Class<?>[] methodParameterTypes = this.aspectJAdviceMethod.getParameterTypes();

    int index = 0;
    for (int i = 0; i < this.argumentNames.length; i++) {
        if (i < argumentIndexOffset) {
            continue;
        }
        if (this.argumentNames[i].equals(this.returningName) ||
            this.argumentNames[i].equals(this.throwingName)) {
            continue;
        }
        pointcutParameterNames[index] = this.argumentNames[i];
        pointcutParameterTypes[index] = methodParameterTypes[i];
        index++;
    }
    //剩余的未綁定的參數(shù)會(huì)賦值給AspectJExpressionPointcut(表達(dá)式形式的切入點(diǎn))的屬性,以備后續(xù)使用
    this.pointcut.setParameterNames(pointcutParameterNames);
    this.pointcut.setParameterTypes(pointcutParameterTypes);
}

篇幅原因肺素,本文到此結(jié)束恨锚,期待下集,下集主要說明postProcessAfterInitialization 及Aop 剩下的實(shí)現(xiàn)邏輯

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末倍靡,一起剝皮案震驚了整個(gè)濱河市猴伶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌塌西,老刑警劉巖他挎,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異雨让,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)忿等,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門栖忠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事庵寞±晗啵” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵捐川,是天一觀的道長脓鹃。 經(jīng)常有香客問我,道長古沥,這世上最難降的妖魔是什么瘸右? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮岩齿,結(jié)果婚禮上太颤,老公的妹妹穿的比我還像新娘。我一直安慰自己盹沈,他們只是感情好龄章,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著乞封,像睡著了一般做裙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上肃晚,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天锚贱,我揣著相機(jī)與錄音,去河邊找鬼陷揪。 笑死惋鸥,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的悍缠。 我是一名探鬼主播卦绣,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼飞蚓!你這毒婦竟也來了滤港?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤趴拧,失蹤者是張志新(化名)和其女友劉穎溅漾,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體著榴,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡添履,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了脑又。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片暮胧。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡锐借,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出往衷,到底是詐尸還是另有隱情钞翔,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布席舍,位于F島的核電站布轿,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏来颤。R本人自食惡果不足惜汰扭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望脚曾。 院中可真熱鬧东且,春花似錦、人聲如沸本讥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拷沸。三九已至色查,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間撞芍,已是汗流浹背秧了。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留序无,地道東北人验毡。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像帝嗡,于是被迫代替她去往敵國和親晶通。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容