Spring AOP源码2:查找增强器

本文深入解析了Spring AOP中代理的创建过程,从`postProcessAfterInitialization`方法开始,详细介绍了如何判断和封装bean是否需要代理,以及如何找到和应用合适的Advisor。重点讲解了`findCandidateAdvisors`、`buildAspectJAdvisors`方法,分析了如何从BeanFactory中获取Advisor,并解析`@Aspect`注解的方法,生成对应的增强器。最后,通过`canApply`方法确定Advisor是否能应用于目标bean的方法上。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考文章:

《Spring AOP源码学习:创建 AOP 代理》

《Spring Aop 之 Advisor 解析》

《Spring Aop 原理之 Advisor 过滤》

前文:

《Spring AOP源码:开启注解读取》

目录

一、postProcessAfterInitialization 

        1、postProcessAfterInitialization 

         2、wrapIfNecessary

        3、findEligibleAdvisors

        4、findEligibleAdvisors

二、findCandidateAdvisors

        1、findCandidateAdvisors

        2、findAdvisorBeans

        3、buildAspectJAdvisors

        1、手动获取

        2、从缓存中获取

        4、getAdvisors

        5、getAdvisor

        6、getPointcut

        7、findAspectJAnnotationOnMethod

        8、InstantiationModelAwarePointcutAdvisorImpl

        9、instantiateAdvice

三、findAdvisorsThatCanApply

        1、findAdvisorsThatCanApply

         2、canApply


写在开头:本文为个人学习笔记,内容比较随意,夹杂个人理解,如有错误,欢迎指正。

        在前文中,我们注册了代理类的自动创建类AnnotationAwareAspectJAutoProxyCreator,该类继承了BeanPostProcessor 接口,在AbstractAutoProxyCreator类中重写了postProcessAfterInitialization方法,进而实现了对正在创建中的bean实例的代理。

一、postProcessAfterInitialization 

        1、postProcessAfterInitialization 

        根据我们之前介绍的bean的生命周期可以得知,每一个bean 在初始化后都会去调用所有 BeanPostProcessor 的 postProcessAfterInitialization 方法。重写了的方法会判断该类是否不在缓存中,如不在则进行判断是否需要代理。之前我们介绍了三层缓存,该类重写了getEarlyBeanReference方法,因此可能存在已经被代理了的类。

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean != null) {
        // 如果是普通bean,则返回beanName,如果是FactoryBean,则返回加上前缀&的&beanName
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        // 判断当前bean是否需要被代理,如果需要则进行封装(earlyProxyReferences中缓存的是已经创建好的代理对象)
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

         getCacheKey用来获取bean的原始类型,如果是普通bean,则返回beanName,如果是FactoryBean,则返回加上前缀&的&beanName。

	protected Object getCacheKey(Class<?> beanClass, String beanName) {
		if (StringUtils.hasLength(beanName)) {
			return (FactoryBean.class.isAssignableFrom(beanClass) ?
					BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
		}
		else {
			return beanClass;
		}
	}

         2、wrapIfNecessary

        我们可以确认,wrapIfNecessary方法就是创建代理类的核心方法。该方法中,我们依然时先检查缓存,确认缓存中没有,且不是aop的基础类,才会接着往下走。

        首先会获取当前bean的Advices和Advisors,如果不为空,则调用createProxy方法去创建代理对象,加入缓存后将其返回给Spring容器。

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    // 1.判断当前bean是否在targetSourcedBeans缓存中存在(已经处理过),如果存在,则直接返回当前bean
    if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    // 2.在advisedBeans缓存中存在,并且value为false,则代表无需处理
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    // 3.bean的类是aop基础设施类 || bean应该跳过,则标记为无需处理,并返回
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
 
    // Create proxy if we have advice.
    // 4.获取当前bean的Advices和Advisors
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    // 5.如果存在增强器则创建代理
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 5.1 创建代理对象:这边SingletonTargetSource的target属性存放的就是我们原来的bean实例(也就是被代理对象),
        // 用于最后增加逻辑执行完毕后,通过反射执行我们真正的方法时使用(method.invoke(bean, args))
        Object proxy = createProxy(
                bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        // 5.2 创建完代理后,将cacheKey -> 代理类的class放到缓存
        this.proxyTypes.put(cacheKey, proxy.getClass());
        // 返回代理对象
        return proxy;
    }
    // 6.标记为无需处理
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

        3、findEligibleAdvisors

        findEligibleAdvisors方法是真正的增强器查找方法,其内部实现了查询所有的增强器,然后再过滤出适用于当前bean上的,并将其返回。

@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
    // 1.找到符合条件的Advisor
    List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
    if (advisors.isEmpty()) {
        // 2.如果没有符合条件的Advisor,则返回null
        return DO_NOT_PROXY;
    }
    return advisors.toArray();
}

        4、findEligibleAdvisors

        这里接着上文,findEligibleAdvisors方法做了四件事:

        (1)调用findCandidateAdvisors找出所有的Advisor.

        (2)筛选第一步中获得到Advisor,找出适用于当前bean的。

        (3)提供一个hook(钩子)方法,供子类实现用以拓展相关功能。

        (4)将符合条件的Advisor进行排序。

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 1.查找所有的候选Advisor
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 2.从所有候选的Advisor中找出符合条件的
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    // 3.扩展方法,留个子类实现
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        // 4.对符合条件的Advisor进行排序
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

二、findCandidateAdvisors

        1、findCandidateAdvisors

        findCandidateAdvisors方法调用父类的findCandidateAdvisors找出所有继承了advisor接口的实现类,然后调用aspectJAdvisorsBuilder.buildAspectJAdvisors()方法将使用了@Aspect注解的类构建成advisor,合并后返回。

// AnnotationAwareAspectJAutoProxyCreator.java
@Override
protected List<Advisor> findCandidateAdvisors() {
    // 1.走父类AbstractAdvisorAutoProxyCreator实现的findCandidateAdvisors
    List<Advisor> advisors = super.findCandidateAdvisors();
    // 2.为bean工厂中的所有AspectJ注解类中的方法构建advisor
    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    return advisors;
}

// AbstractAdvisorAutoProxyCreator.java
protected List<Advisor> findCandidateAdvisors() {
	return this.advisorRetrievalHelper.findAdvisorBeans();
}

        2、findAdvisorBeans

        上文中的findCandidateAdvisors最后会溯源到BeanFactoryAdvisorRetrievalHelper类的findAdvisorBeans()方法。

        这里 findAdvisorBeans() 方法不难理解:

        (1)尝试从缓存中获取class类型为Advisor的bean的beanName没有则调用BeanFactoryUtils工具类的beanNamesForTypeIncludingAncestors方法根据类型查找beanName。

        (2)遍历所有的advisorNames,筛选出符合要求的,跳过正在创建的,然后使用getBean获取对应beanName的实例。

public List<Advisor> findAdvisorBeans() {
    // 1.确认advisor的beanName列表,优先从缓存中拿
    String[] advisorNames = null;
    synchronized (this) {
        advisorNames = this.cachedAdvisorBeanNames;
        if (advisorNames == null) {
            //  1.1 如果缓存为空,则获取class类型为Advisor的所有bean名称
            advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                    this.beanFactory, Advisor.class, true, false);
            this.cachedAdvisorBeanNames = advisorNames;
        }
    }
    if (advisorNames.length == 0) {
        return new LinkedList<Advisor>();
    }
 
    // 2.遍历处理advisorNames
    List<Advisor> advisors = new LinkedList<Advisor>();
    for (String name : advisorNames) {
        // isEligibleBean()是提供的一个hook方法,用于子类对Advisor进行过滤,这里默认返回值都是true
        if (isEligibleBean(name)) {
            // 2.1 跳过当前正在创建的advisor
            if (this.beanFactory.isCurrentlyInCreation(name)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Skipping currently created advisor '" + name + "'");
                }
            } else {
                try {
                    // 2.2 通过beanName获取对应的bean对象,并添加到advisors
                    advisors.add(this.beanFactory.getBean(name, Advisor.class));
                } catch (BeanCreationException ex) {
                    Throwable rootCause = ex.getMostSpecificCause();
                    if (rootCause instanceof BeanCurrentlyInCreationException) {
                        BeanCreationException bce = (BeanCreationException) rootCause;
                        if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {
                            if (logger.isDebugEnabled()) {
                                logger.debug("Skipping advisor '" + name +
                                        "' with dependency on currently created bean: " + ex.getMessage());
                            }
                            // Ignore: indicates a reference back to the bean we're trying to advise.
                            // We want to find advisors other than the currently created bean itself.
                            continue;
                        }
                    }
                    throw ex;
                }
            }
        }
    }
    // 3.返回符合条件的advisor列表
    return advisors;
}

        3、buildAspectJAdvisors

        调用BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors()实现,该方法内容较多,我按照大的模块分成两部分。

public List<Advisor> buildAspectJAdvisors() {
    1、缓存为空,手动获取所有的beanName并过滤和封装所需增强器
    2、缓存不为空,则从缓存中获取出增强器
}

        1、手动获取

    List<String> aspectNames = this.aspectBeanNames;
    // (1)试从缓存中获取aspectNames,若没有则手动获取
    if (aspectNames == null) {
        synchronized (this) {
            aspectNames = this.aspectBeanNames;
            if (aspectNames == null) {
                List<Advisor> advisors = new LinkedList<Advisor>();
                aspectNames = new LinkedList<String>();
                // (1.1)调用beanNamesForTypeIncludingAncestors方法获取到所有的bean
                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                        this.beanFactory, Object.class, true, false);
                // (1.2)遍历所有的beanName,判断该bean是否为子类定制的需要过滤的bean
                for (String beanName : beanNames) {
                    if (!isEligibleBean(beanName)) {
                        continue;
                    }
                    //(1.3)获取当前遍历的bean的Class类型,并判断当前bean是否使用了@Aspect注解进行标注
                    Class<?> beanType = this.beanFactory.getType(beanName);
                    if (beanType == null) {
                        continue;
                    }
                    if (this.advisorFactory.isAspect(beanType)) {
                        // 将存在Aspect注解的beanName添加到aspectNames列表
                        aspectNames.add(beanName);
                        //(1.4)将该beanName加入到aspectNames缓存中,并新建元数据。元数据里包含了该bean的一些属性。
                        AspectMetadata amd = new AspectMetadata(beanType, beanName);
                        //(1.5)判断@Aspect注解中标注的是否为singleton类型,默认的切面类都是singleton类型
                        if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                            // (1.6)使用BeanFactory和beanName创建一个BeanFactoryAspectInstanceFactory,主要用来创建切面对象实例
                            MetadataAwareAspectInstanceFactory factory =
                                    new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                            //(1.7)通过封装的factory获取其Advice,如@Before,@After等等,并将这些Advice都解析并且封装为一个个的Advisor
                            List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                            (1.8)如果切面类是singleton类型,则将解析得到的Advisor进行缓存,如果不是单例,则将factory放到缓存,以便再次获取时可以通过factory来解析
                            if (this.beanFactory.isSingleton(beanName)) {
                                this.advisorsCache.put(beanName, classAdvisors);
                            } else {      
                                this.aspectFactoryCache.put(beanName, factory);
                            }
                            advisors.addAll(classAdvisors);
                        } else {
                            //(1.9)如果@Aspect注解标注的beanName的Bean是单例,但切面实例化模型不是单例,则抛异常。
                            if (this.beanFactory.isSingleton(beanName)) {
                                throw new IllegalArgumentException("Bean with name '" + beanName +
                                        "' is a singleton, but aspect instantiation model is not singleton");
                            }
							// (1.10)将当前BeanFactory和切面bean封装为一个多例类型的Factory,同时对当前bean和factory进行缓存
                            MetadataAwareAspectInstanceFactory factory =
                                    new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                            this.aspectFactoryCache.put(beanName, factory);
                            advisors.addAll(this.advisorFactory.getAdvisors(factory));
                        }
                    }
                }
                //(1.11)将解析出来的切面beanName放到缓存aspectBeanNames,并返回
                this.aspectBeanNames = aspectNames;
                return advisors;
            }
        }
    }

        2、从缓存中获取

    // 如果aspectNames不为null,则代表已经解析过了,则无需再次解析
    if (aspectNames.isEmpty()) {
        return Collections.emptyList();
    }

    List<Advisor> advisors = new LinkedList<Advisor>();
    for (String aspectName : aspectNames) {
        // 根据aspectName从缓存中获取Advisor集合
        List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
        if (cachedAdvisors != null) {
            // 根据上面的解析,可以知道advisorsCache存的是已经解析好的Advisor,直接添加到结果即可
            advisors.addAll(cachedAdvisors);
        } else {
            // 如果不存在于advisorsCache缓存,则代表存在于aspectFactoryCache中,
            // 从aspectFactoryCache中拿到缓存的factory,然后解析出Advisor,添加到结果中
            MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
            advisors.addAll(this.advisorFactory.getAdvisors(factory));
        }
    }
    // 返回增强器
    return advisors;

        整理一下就是容器首先会过滤得到 BeanFactory 中所有标注有 @Aspect 的类,然后对该注解参数进行解析,判断其环绕的目标 bean 是单例的还是多例的。如果是单例的,则直接缓存封装后的Advisor到 advisorsCache 中;如果是多例的,则将生成 Advisor 的 factory 进行缓存,以便每次获取时都通过 factory 获取一个新的 Advisor。

        4、getAdvisors

        遍历当前切面类所有的方法,包括父类和父接口的方法,找到其中没有使用 @Pointcut 注解标注的方法,然后对找到的方法进行遍历,将其封装为一个 Advisor。

@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
    // 这边可以通过之前组装的元数据AspectMetadata属性获取当前切面类的Class类型
    Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    // 获取当前处理的切面类的名字
    String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
    // 校验切面类
    validate(aspectClass);
 
    // 将当前aspectInstanceFactory进行封装,这里LazySingletonAspectInstanceFactoryDecorator
    // 使用装饰器模式,主要是对获取到的切面实例进行了缓存,保证每次获取到的都是同一个切面实例
    MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
            new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
 
    List<Advisor> advisors = new LinkedList<Advisor>();
    // 获取所有的没有使用@Pointcut注解标注的方法,然后对其进行遍历
    for (Method method : getAdvisorMethods(aspectClass)) {
        // 判断当前方法是否标注有@Before,@After或@Around等注解,如果标注了,则将其封装为一个Advisor
        Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
        if (advisor != null) {
            // 如果增强器不为空,则添加到advisors
            advisors.add(advisor);
        }
    }
 
    // If it's a per target aspect, emit the dummy instantiating aspect.
    if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
        // 如果Advisor不为空,并且是需要延迟初始化的bean,则在第0位位置添加一个同步实例化增强器(用以保证增强使用之前的实例化)
        Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
        advisors.add(0, instantiationAdvisor);
    }
 

    // 判断属性上是否包含有@DeclareParents注解标注的需要新添加的属性,如果有,则将其封装为一个Advisor
    for (Field field : aspectClass.getDeclaredFields()) {
        Advisor advisor = getDeclareParentsAdvisor(field);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }
 
    return advisors;
}

         getAdvisorMethods用来查找切面类上的方法,但会跳过pointcuts。

	private List<Method> getAdvisorMethods(Class<?> aspectClass) {
		final List<Method> methods = new ArrayList<Method>();
		ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
			@Override
			public void doWith(Method method) throws IllegalArgumentException {
				// Exclude pointcuts
				if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
					methods.add(method);
				}
			}
		});
		Collections.sort(methods, METHOD_COMPARATOR);
		return methods;
	}

        5、getAdvisor

        针对@Before,@After 或 @Around等注解标注的方法,调用getPointcut方法读取其中的表达式参数,即切点信息,并生成增强器。

@Override
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
                          int declarationOrderInAspect, String aspectName) {
    // 校验切面类
    validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
    // 获取当前方法中@Before,@After或者@Around等标注的注解,并且获取该注解的值
    // 如:@Around("execution(* com.joonwhee.open.aop.*.*(..))")
    // 将其封装为一个AspectJExpressionPointcut对象
    AspectJExpressionPointcut expressionPointcut = getPointcut(
            candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
    if (expressionPointcut == null) {
        return null;
    }
    // 根据切点信息生成增强器
    return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
            this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

        6、getPointcut

       解析传入进来的方法,读取该方法上的第一个Aspect相关注解(例如@Before。@After等),并封装成AspectJExpressionPointcut返回。

private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
    // 查找并返回给定方法的第一个AspectJ注解(@Before, @Around, @After, @AfterReturning, @AfterThrowing, @Pointcut)
    // 因为我们之前把@Pointcut注解的方法跳过了,所以这边必然不会获取到@Pointcut注解
    AspectJAnnotation<?> aspectJAnnotation =
            AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    // 如果方法没有使用AspectJ的注解,则返回null
    if (aspectJAnnotation == null) {
        return null;
    }
    // 使用AspectJExpressionPointcut实例封装获取的信息
    AspectJExpressionPointcut ajexp =
            new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
    // 提取得到的注解中的表达式,
    // 例如:@Around("execution(* com.joonwhee.open.aop.*.*(..))"),得到:execution(* com.joonwhee.open.aop.*.*(..))
    ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
    ajexp.setBeanFactory(this.beanFactory);
    return ajexp;
}

        7、findAspectJAnnotationOnMethod

        该方法用来查找方法上的直接,返回第一个找到的。

protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
    // 设置要查找的注解类
    Class<?>[] classesToLookFor = new Class<?>[]{
            Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
    for (Class<?> c : classesToLookFor) {
        // 查找方法上是否存在当前遍历的注解,如果有则返回
        AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
        if (foundAnnotation != null) {
            return foundAnnotation;
        }
    }
    return null;
}

        8、InstantiationModelAwarePointcutAdvisorImpl

        根据切点信息生成增强器,其中aspectJAdviceMethod负责保存用来进行增强的方法,instantiateAdvice实例化增强器。

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();
    // aspectJAdviceMethod保存的是我们用来进行逻辑增强的方法(@Around、@After等修饰的方法)
    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);
    }
}

        9、instantiateAdvice

        instantiateAdvice方法实际上是调用的ReflectiveAspectJAdvisorFactory的getAdvice方法。根据方法使用的aspectJ注解创建对应的增强器,比如@Before则生成AspectJMethodBeforeAdvice对象。

private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
    return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,
            this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
}
 
// ReflectiveAspectJAdvisorFactory.java
@Override
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
                        MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
    // 获取切面类
    Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    // 校验切面类(重复校验第3次...)
    validate(candidateAspectClass);
 
    // 查找并返回方法的第一个AspectJ注解
    AspectJAnnotation<?> aspectJAnnotation =
            AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    if (aspectJAnnotation == null) {
        return null;
    }
    // 如果我们到这里,我们知道我们有一个AspectJ方法。检查切面类是否使用了AspectJ注解
    if (!isAspect(candidateAspectClass)) {
        throw new AopConfigException("Advice must be declared inside an aspect type: " +
                "Offending method '" + candidateAdviceMethod + "' in class [" +
                candidateAspectClass.getName() + "]");
    }
    AbstractAspectJAdvice springAdvice;
    // 根据方法使用的aspectJ注解创建对应的增强器
    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:
            return null;
        default:
            throw new UnsupportedOperationException(
                    "Unsupported advice type on method: " + candidateAdviceMethod);
    }
    // 配置增强器
    // 切面类的name,其实就是beanName
    springAdvice.setAspectName(aspectName);
    springAdvice.setDeclarationOrder(declarationOrder);
    // 获取增强方法的参数
    String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
    if (argNames != null) {
        // 如果参数不为空,则赋值给springAdvice
        springAdvice.setArgumentNamesFromStringArray(argNames);
    }
    springAdvice.calculateArgumentBindings();
    // 最后,返回增强器
    return springAdvice;
}

        这里提一下AspectJAfterAdvice、AspectJAfterThrowingAdvice、AspectJAroundAdvice这些增强器都继承了MethodInterceptor接口,增强器正是通过该接口的invoke方法生效的。

public interface MethodInterceptor extends Interceptor {
	
	/**
	 * Implement this method to perform extra treatments before and
	 * after the invocation. Polite implementations would certainly
	 * like to invoke {@link Joinpoint#proceed()}.
	 * @param invocation the method invocation joinpoint
	 * @return the result of the call to {@link Joinpoint#proceed()};
	 * might be intercepted by the interceptor
	 * @throws Throwable if the interceptors or the target object
	 * throws an exception
	 */
	Object invoke(MethodInvocation invocation) throws Throwable;

}

三、findAdvisorsThatCanApply

        1、findAdvisorsThatCanApply

        遍历所有上文中查找出来的增强器,首先处理引介增强,这个用的很少,个人没见过,这种增强器能够将被代理类中没有的方法插入到代理类中。

        然后再进行一次循环,这次将会对普通类型的增强器调用canapply方法进行判断,看其是否能够作用于当前正在生成的Bean上。

// AbstractAdvisorAutoProxyCreator.java
protected List<Advisor> findAdvisorsThatCanApply(
	List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
	ProxyCreationContext.setCurrentProxiedBeanName(beanName);
	try {
		return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
	}
	finally {
		ProxyCreationContext.setCurrentProxiedBeanName(null);
	}
}

// AopUtils.java
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
    if (candidateAdvisors.isEmpty()) {
        return candidateAdvisors;
    }
    List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
    // 首先处理引介增强(@DeclareParents)用的比较少可以忽略https://www.cnblogs.com/HigginCui/p/6322283.html
    for (Advisor candidate : candidateAdvisors) {
        if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
            eligibleAdvisors.add(candidate);
        }
    }
    boolean hasIntroductions = !eligibleAdvisors.isEmpty();
    // 遍历所有的candidateAdvisors
    for (Advisor candidate : candidateAdvisors) {
        // 引介增强已经处理,直接跳过
        if (candidate instanceof IntroductionAdvisor) {
            continue;
        }
        // 判断是否可以应用到当前bean类型
        if (canApply(candidate, clazz, hasIntroductions)) {
            eligibleAdvisors.add(candidate);
        }
    }
    return eligibleAdvisors;
}

         2、canApply

        通过 ClassFilter 对类进行过滤和通过 MethodMatcher 对方法进行过滤。这里的 ClassFilter 其实主要指的是 @Aspect 注解中使用的切点表达式,而 MethodMatcher 主要指的是 @Before,@After 等注解中使用的切点表达式。

    // AopUtils.java
	public static boolean canApply(Advisor advisor, Class<?> targetClass) {
		return canApply(advisor, targetClass, false);
	}

	public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
		if (advisor instanceof IntroductionAdvisor) {
			return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
		}
		else if (advisor instanceof PointcutAdvisor) {
			PointcutAdvisor pca = (PointcutAdvisor) advisor;
			return canApply(pca.getPointcut(), targetClass, hasIntroductions);
		}
		else {
			// It doesn't have a pointcut so we assume it applies.
			return true;
		}
	}

    public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
		Assert.notNull(pc, "Pointcut must not be null");
        // 获取当前Advisor的CalssFilter,并且调用其matches()方法判断当前切点表达式是否与目标bean匹配,
        // 这里ClassFilter指代的切点表达式主要是当前切面类上使用的@Aspect注解中所指代的切点表达式
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}

        // 判断如果当前Advisor所指代的方法的切点表达式如果是对任意方法都放行,则直接返回
		MethodMatcher methodMatcher = pc.getMethodMatcher();
		if (methodMatcher == MethodMatcher.TRUE) {
			// No need to iterate the methods if we're matching any method anyway...
			return true;
		}

		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) {
			Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
			for (Method method : methods) {
                // 使用matches判断能否作用于该方法上
				if ((introductionAwareMethodMatcher != null &&
						introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
						methodMatcher.matches(method, targetClass)) {
					return true;
				}
			}
		}

		return false;
	}

        本文主要介绍了Advisor 增强器的获取与解析:

        (1)即首先获取 BeanFactory 中所有实现了 Advisor 接口的 bean,然后获取 BeanFactory 中所有标注了 @Aspect 注解的 bean,解析该 bean 中的所有的切面逻辑,并且封装为一个个 Advisor,这两种方式得到的 Advisor 都有可能是最终会应用到目标 bean 上的切面逻辑。

        (2)通过解析Advisor上的切点表达式,并逐个与当前bean进行匹配的方式过滤出所有适用当前bean中方法的增强器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值