美文网首页
Spring源码解析之基于注解的SpringAOP源码解析(一)

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

作者: 程序员_进军SJF | 来源:发表于2020-03-31 11:12 被阅读0次
    Spring源码解析之基于注解的SpringAOP源码解析(一)

    本文分析Spring的AOP模块的整体流程,分析过程需要使用一个简单的demo工程来启动Spring。

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

    写一个简单的接口和实现类,跟IOC源码解析那几篇文章用的同一个工程,

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

    增加bean的配置类,以及启动AOP

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

    创建切点

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

    启动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功能,使用了一个@EnableAspectJAutoProxy注解,进入这个注解可以查看到这个注解的2个属性,相信大家都已经很熟悉了,就不相信的说明了。除此之外可以看到这个注解使用@Import注解引入了一个配置类

    @Import注解:可以引入一个类,将这个类注入到Spring IOC容器中被当前Spring管理

    @Import(AspectJAutoProxyRegistrar.class)
    public @interface EnableAspectJAutoProxy {
        //proxyTargetClass属性,默认false,尝试采用JDK动态代理织入增强(如果当前类没有实现接口则还是会使用CGLIB);如果设为true,则强制采用CGLIB动态代理织入增强
        boolean proxyTargetClass() default false;
        //通过aop框架暴露该代理对象,aopContext能够访问。为了解决类内部方法之间调用时无法增强的问题
        boolean exposeProxy() default false;
    }
    

    看一下这个配置类的操作

    class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
        AspectJAutoProxyRegistrar() {
        }
    
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
                   //注册一个AOP代理实现的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方法的主要功能是注册或者升级AnnotationAwareAspectJAutoProxyCreator类,这个类在AOP中非常的重要,它的主要功能就是根据@Point注解定义的切点来自动代理与表达式匹配的类。下面看一个这个实现的逻辑

    private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
            Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); //如果已存在这个bean
            if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
                BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
                //判断优先级,如果优先级较高则替换原先的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 {
                //注册AnnotationAwareAspectJAutoProxyCreator到容器中,此类负责基于注解的AOP动态代理实现
                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;
            }
        }
    

    注册的AnnotationAwareAspectJAutoProxyCreator这个类间接实现了BeanPostProcessor接口。还记得我们之前在对SpringIOC的源码进行解析时提到过,Spring在实例化Bean的前后会分别调用方法postProcessBeforeInstantiation和postProcessAfterInstantiation而AOP的整体逻辑就是通过这两个方法来实现的

    postProcessBeforeInstantiation

    首先看一下这个postProcessBeforeInstantiation方法,它是在bean实例化之前调用的,主要是针对切面类。这个方法不在AnnotationAwareAspectJAutoProxyCreator这个类中,而是在其父类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;
          }
                //加载所有增强
          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;
      }
    

    加载增强

    上方代码中最重要的一个方法就是shouldSkip方法了,被AspectJAwareAdvisorAutoProxyCreator所重载

    protected boolean shouldSkip(Class<?> beanClass, String beanName) {
      
        //查找所有标识了@Aspect注解的类,这里是重点,接着往下看
        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是重点
               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;
                //这个双重检查是不是在学习安全的单例模式的时候见过
                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) {
                        //判断是否符合条件,比如说有时会排除一些类,不让这些类注入进Spring
                        if (!isEligibleBean(beanName)) {
                            continue;
                        }
               
                        Class<?> beanType = this.beanFactory.getType(beanName);
                        if (beanType == null) {
                            continue;
                        }
                        //判断Bean的Class上是否标识@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);
                                //下一步说,重点的重点
                                List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                                if (this.beanFactory.isSingleton(beanName)) {
                                    //将解析的Bean名称及类上的增强缓存起来,每个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) {
            //从缓存中获取当前Bean的切面实例,如果不为空,则指明当前Bean的Class标识了@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;
    }
    

    生成增强

    advisorFactory.getAdvisors方法会从@Aspect标识的类上获取@Before,@Pointcut等注解的信息及其标识的方法的信息,生成增强

    public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
        Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
        String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
        //校验类的合法性相关
        validate(aspectClass);
    
        MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
                new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
    
        List<Advisor> advisors = new LinkedList<Advisor>();
        //获取这个类所有的增强方法
        for (Method method : getAdvisorMethods(aspectClass)) {
            //生成增强实例
            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标识的类内部排除@Pointcut标识之外的所有方法,得到的方法集合包括继承自父类的方法,包括继承自Object的方法
                if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
                    methods.add(method);
                }
            }
        });
        //对得到的所有方法排序,
        //如果方法标识了切面注解,则按@Around, @Before, @After, @AfterReturning, @AfterThrowing的顺序排序
        //如果没有标识这些注解,则按方法名称的字符串排序,
        //有注解的方法排在无注解的方法之前
        //最后的排序应该是这样的Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class。。。
        Collections.sort(methods, METHOD_COMPARATOR);
        return methods;
    }
    

    调用生成增强实例的方法

    public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
            int declarationOrderInAspect, String aspectName) {
        //再次校验类的合法性
        validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
        //切点表达式的包装类里面包含这些东西:execution(public * cn.shiyujun.service.IOCService.hollo(..))
        AspectJExpressionPointcut expressionPointcut = getPointcut(
                candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
        if (expressionPointcut == null) {
            return null;
        }
        //根据方法、切点、AOP实例工厂、类名、序号生成切面实例,详细代码往下看
        return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
                this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
    }
    
    private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
        //查询方法上的切面注解,根据注解生成相应类型的AspectJAnnotation,在调用AspectJAnnotation的构造函数的同时
        //根据注解value或pointcut属性得到切点表达式,有argNames则设置参数名称
        AspectJAnnotation<?> aspectJAnnotation =
                AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
        //过滤那些不含@Before, @Around, @After, @AfterReturning, @AfterThrowing注解的方法
        if (aspectJAnnotation == null) {
            return null;
        }
        //生成带表达式的切面切入点,设置其切入点表达式
        AspectJExpressionPointcut ajexp =
                new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
        ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
        ajexp.setBeanFactory(this.beanFactory);
        return ajexp;
    }
    

    InstantiationModelAwarePointcutAdvisorImpl的构造方法

    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;
                //重点在这里
          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);
      }
    

    生产增强

    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();
            //又是一次校验
            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;
            //根据注解类型生成不同的通知实例
            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);
            }
    
            //设置通知方法所属的类
            springAdvice.setAspectName(aspectName);
            //设置通知的序号,同一个类中有多个切面注解标识的方法时,按上方说的排序规则来排序,
            //其序号就是此方法在列表中的序号,第一个就是0
            springAdvice.setDeclarationOrder(declarationOrder);
            //获取通知方法的所有参数
            String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
            //将通知方法上的参数设置到通知中
            if (argNames != null) {
                springAdvice.setArgumentNamesFromStringArray(argNames);
            }
            //计算参数绑定工作,此方法详解请接着往下看
            springAdvice.calculateArgumentBindings();
            return springAdvice;
        }
    }
    

    校验方法参数并绑定

    public synchronized final void calculateArgumentBindings() {
        if (this.argumentsIntrospected || this.parameterTypes.length == 0) {
            return;
        }
    
        int numUnboundArgs = this.parameterTypes.length;
        Class<?>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
        //切面注解标识的方法第一个参数要求是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) { //获取方法参数的名称
            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) {
        //此属性用来存储方法未绑定的参数名称,及参数的序号
        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代表第一个未绑定参数的顺序 
        int argumentIndexOffset = this.parameterTypes.length - numArgumentsLeftToBind;
        for (int i = argumentIndexOffset; i < this.argumentNames.length; i++) {
            //存储未绑定的参数名称及其顺序的映射关系
            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 有值,验证,解析,同时得到定义返回值的类型
        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 有值,验证,解析,同时得到抛出异常的类型
        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++;
        }
        //剩余的未绑定的参数会赋值给AspectJExpressionPointcut(表达式形式的切入点)的属性,以备后续使用
        this.pointcut.setParameterNames(pointcutParameterNames);
        this.pointcut.setParameterTypes(pointcutParameterTypes);
    }
    

    篇幅原因,本文到此结束,期待下集,下集主要说明postProcessAfterInitialization 及Aop 剩下的实现逻辑

    相关文章

      网友评论

          本文标题:Spring源码解析之基于注解的SpringAOP源码解析(一)

          本文链接:https://www.haomeiwen.com/subject/jlfwuhtx.html