逐行理解Spring AOP源码

本文详细解析了Spring AOP的工作原理,包括AOP自动代理的开启、触发时机、Bean匹配的Advisors链获取过程、Advisor的筛选逻辑、代理类的创建流程等内容。通过源码分析,介绍了JDK动态代理和Cglib动态代理的具体实现。


本文主要是对于他人文章的整理,最后给出了参考链接。具体内容根据本人的理解,有所取舍。后续对于AOP有更深入的理解,再不断进行更新

AOP依赖于ioc容器进行管理。


开启AOP自动代理及触发时机

如果让Spring支持注解模式的AOP,那么需要在启动类上添加@EnableAspectJAutoProxy注解,它的作用是让ioc容器中所有的advisor来匹配方法。注解的定义如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
    boolean proxyTargetClass() default false;
    boolean exposeProxy() default false;
}

其中比较重要的注解是@Inport,它将AspectJAutoProxyRegistrar注入到了ioc容器中。源码定义如下:

// 实现了ImportBeanDefinitionRegistrar接口
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	/**
	 * Register, escalate, and configure the AspectJ auto proxy creator based on the value
	 * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
	 * {@code @Configuration} class.
	 */
	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		
        // 注册registerAspectJAnnotationAutoProxyCreator的BeanDefinition
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
	
		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		
        // 根据@EnableAspectJAutoProxy 注解的proxyTargetClass和exposeProxy属性值,将属性值注入到
        // registerAspectJAnnotationAutoProxyCreator的BeanDefinition中
        if (enableAspectJAutoProxy != null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}
}

AspectJAutoProxyRegistrar主要就是将registerAspectJAnnotationAutoProxyCreator的BeanDefinition注册到ioc容器中。

registerAspectJAnnotationAutoProxyCreator的类继承图如下所示:


在这里插入图片描述

AspectJAnnotationAutoProxyCreator其实就是一个BeanPostProcessor

Spring Bean 创建的过程,在执行完创建实例对象createBeanInstance和属性装配populateBean之后,我们才算得到一个真正的实现类。在initializeBean中,IoC容器会处理Bean初始化之后的各种回调事件,然后返回一个最终的bean对象。

其中就包括了BeanPostProcessorpostProcessBeforeInitialization 回调 和 postProcessAfterInitialization 回调。而AspectJAnnotationAutoProxyCreator恰恰是一个BeanPostProcessor。那就很容易联想到,Spring AOP 就是在这一步,进行代理增强!

代理模式的实现思路是:(接口)+ 真实实现类 + 代理类,先要有真实的实现类,才能生产代理类。

从源码中可以看到,postProcessBeforeInitialization回调和 postProcessAfterInitialization回调是重写了AbstractAutoProxyCreator中的方法。

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

其中postProcessBeforeInitialization方法调用链如下所示:


在这里插入图片描述

postProcessAfterInitialization会执行创建代理类的操作,用配置的interceptors 来创建一个代理类。首先,看一下wrapIfNecessary方法的实现:

/**
* Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
* @param bean the raw bean instance
* @param beanName the name of the bean
* @param cacheKey the cache key for metadata access
* @return a proxy wrapping the bean, or the raw bean instance as-is
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    
    // 判断是不是基础Bean(Advice、PointCut、Advisor、AopInfrastructureBean),是就直接跳过
    // 判断是不是应该跳过,AOP解析直接解析出切面信息,并且将切面信息进行缓存
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // Create proxy if we have advice.
    // 如果定义了advice,则创建代理类
    // 返回匹配当前Bean的所有advisor、advice、interceptor
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 创建代理类对象
        Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

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

方法的调用链如下所示:


在这里插入图片描述

当一个类是合法的可以被代理的类,那么可以使用wrapIfNecessary方法进行进一步的包装,方法的返回值是代理类或者实现类本身。方法的核心逻辑有两步(针对于需要生成代理类的场景):

  • 返回匹配当前Bean的所有advisor、advice、interceptor
  • 调用createProxy方法实现真正代理类对象的创建

获取Bean匹配的Advisors链

获取匹配当前Bean所有的Advisor分为两步:

  • 获取容器中所有的advisor作为候选,即解析ioc容器中所有Aspect类的advice包装成Advisor
  • 从候选的Advisor中筛选出匹配当前Bean的Advisors链

其中shouldSkip的实现是AspectJAwareAdvisorAutoProxyCreatorshouldSkip方法,它首先调用findCandidateAdvisors来获取所有的候选Advisors,然后根据传入的beanClassbeanName判断是否是AspectJPointcutAdvisorAspectJPointcutAdvisor来决定是否跳过。

public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {

	@Override
	protected boolean shouldSkip(Class<?> beanClass, String beanName) {
		// TODO: Consider optimization by caching the list of the aspect names
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		for (Advisor advisor : candidateAdvisors) {
			if (advisor instanceof AspectJPointcutAdvisor &&
					((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
				return true;
			}
		}
		return super.shouldSkip(beanClass, beanName);
	}
}

返回匹配当前Bean的所有advisor、advice、interceptor调用的是getAdvicesAndAdvisorsForBean方法,它的源码定义如下:

@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
    Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

    List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
    if (advisors.isEmpty()) {
        return DO_NOT_PROXY;
    }
    return advisors.toArray();
}

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

它也是调用了findCandidateAdvisors方法来获取所有候选的Advisors。那么,接下来看一下它如何获取所有的Advisors ,方法源码定义如下:

public List<Advisor> findAdvisorBeans() {
    // 获取缓存中所有Advisor对应的beanName
    String[] advisorNames = this.cachedAdvisorBeanNames;
    if (advisorNames == null) {
        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the auto-proxy creator apply to them!
        advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
            this.beanFactory, Advisor.class, true, false);
        this.cachedAdvisorBeanNames = advisorNames;
    }
    if (advisorNames.length == 0) {
        return new ArrayList<>();
    }

    List<Advisor> advisors = new ArrayList<>();
    // 遍历所有的advisor
    for (String name : advisorNames) {
        if (isEligibleBean(name)) {
            if (this.beanFactory.isCurrentlyInCreation(name)) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Skipping currently created advisor '" + name + "'");
                }
            }
            else {
                try {
                    // 如果对应的Bean已经被创建,则从BeanFactory中获取指定的Bean,将其添加到advisors这个list中
                    advisors.add(this.beanFactory.getBean(name, Advisor.class));
                }
                catch (BeanCreationException ex) {
                    Throwable rootCause = ex.getMostSpecificCause();
                    if (rootCause instanceof BeanCurrentlyInCreationException) {
                        BeanCreationException bce = (BeanCreationException) rootCause;
                        String bceBeanName = bce.getBeanName();
                        if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
                            if (logger.isTraceEnabled()) {
                                logger.trace("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;
                }
            }
        }
    }
    // 返回所有已创建的Advisors
    return advisors;
}

而获取通过@Aspect注解的Advisor,真正调用的是BeanFactoryAspectJAdvisorsBuilderbuildAspectJAdvisors方法,源码定义如下:

// 在BeanFactory中寻找被@Aspect注解的Bean,在每个Aspect类的advice方法创建一个Spring Advisor,然后返回Advisors链

public List<Advisor> buildAspectJAdvisors() {
    List<String> aspectNames = this.aspectBeanNames;

    // 第一次实例化singleton bean时会触发解析切面,解析后aspectNames被缓存下来
    if (aspectNames == null) {
        synchronized (this) {
            aspectNames = this.aspectBeanNames;
            if (aspectNames == null) {
                // 用于保存所有解析出来的Advisors集合对象
                List<Advisor> advisors = new ArrayList<>();
                aspectNames = new ArrayList<>();
                // 取出所有的Spring Bean的名称
                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                    this.beanFactory, Object.class, true, false);
                // 遍历判断
                for (String beanName : beanNames) {
                    if (!isEligibleBean(beanName)) {
                        continue;
                    }
                    // 通过beanName去ioc容器中获取对应的Class对象
                    Class<?> beanType = this.beanFactory.getType(beanName, false);
                    if (beanType == null) {
                        continue;
                    }
                    // 是否用@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);
                            // 从Advice类中解析出所有的Advisor
                            // 会给每个Aspect类的advice方法创建一个Spring Advisor
                            List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                            // 加入到缓存中
                            if (this.beanFactory.isSingleton(beanName)) {
                                this.advisorsCache.put(beanName, classAdvisors);
                            }
                            else {
                                this.aspectFactoryCache.put(beanName, factory);
                            }
                            advisors.addAll(classAdvisors);
                        }
                        else {
                            // Per target or per this.
                            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 ArrayList<>();
    for (String aspectName : aspectNames) {
        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;
}

为了避免每次都去获取所有的beanName,解析判断,引入了缓存的机制;还有就是Aspect类是根据Spring Bean 是否被 @Aspect注解修饰来判断的。

接下来看一下上面的核心方法getAdvisors

@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
    // 获取标记为Aspect的类
    Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    // 获取切面类的名称
    String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
    // 校验切面类
    validate(aspectClass);

    MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
        new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

    List<Advisor> advisors = new ArrayList<>();
    // 获取到切面类中除了@PointCut注解外所有的方法
    for (Method method : getAdvisorMethods(aspectClass)) {
       	// 循环解析切面中的方法,获取当前方法的Advisor
        Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
        if (advisor != null) {
            // 保存获取到的Advisor
            advisors.add(advisor);
        }
    }
	// 如果寻找的Advisor不为空,且配置了Advisor延迟初始化,那么需要在首位加入同步实例化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;
}

接着看上面的getAdvisor方法:

@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
                          int declarationOrderInAspect, String aspectName) {
	// 检验
    validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
	// 获取当前方法的PointCut
    AspectJExpressionPointcut expressionPointcut = getPointcut(
        candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
    if (expressionPointcut == null) {
        return null;
    }
	// 根据PointCut生成Advisor
    return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
                                                          this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

Advisor的对象类型是InstantiationModelAwarePointcutAdvisorImpl,调用的构造方法如下:

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
                                                  Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
                                                  MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
	
    // 切点表达式
    this.declaredPointcut = declaredPointcut;
    // 切面的Class对象
    this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
    // 切面方法的名称
    this.methodName = aspectJAdviceMethod.getName();
    // 切面方法的参数类型
    this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
    // 切面方法独享
    this.aspectJAdviceMethod = aspectJAdviceMethod;
    // aspectJ的Advisor工厂
    this.aspectJAdvisorFactory = aspectJAdvisorFactory;
    // aspectJ的实例工厂
    this.aspectInstanceFactory = aspectInstanceFactory;
    // 切面的顺序
    this.declarationOrder = declarationOrder;
    // 切面的名称
    this.aspectName = aspectName;
	// 如果配置了延迟初始化
    if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
        // Static part of the pointcut is a lazy type.
        Pointcut preInstantiationPointcut = Pointcuts.union(
            aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);

        // Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
        // If it's not a dynamic pointcut, it may be optimized out
        // by the Spring AOP infrastructure after the first evaluation.
        this.pointcut = new PerTargetInstantiationModelPointcut(
            this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
        this.lazy = true;
    }
    else {
        // A singleton aspect.
        this.pointcut = this.declaredPointcut;
        this.lazy = false;
        // 非懒加载,直接初始化
        this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
    }
}

而Advisor的初始化调用的是instantiateAdvice方法:

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

中间调用了getAdvice方法:

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

    // 检查是否是被@Aspect注释的类
    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;
	// 判断方法上注释的advice注解的类型
    switch (aspectJAnnotation.getAnnotationType()) {
        case AtPointcut:
            if (logger.isDebugEnabled()) {
                logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
            }
            return null;
        case AtAround:
            springAdvice = new AspectJAroundAdvice(
                candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        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;
        default:
            throw new UnsupportedOperationException(
                "Unsupported advice type on method: " + candidateAdviceMethod);
    }

    // Now to configure the advice...
    springAdvice.setAspectName(aspectName);
    springAdvice.setDeclarationOrder(declarationOrder);
    String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
    if (argNames != null) {
        springAdvice.setArgumentNamesFromStringArray(argNames);
    }
    springAdvice.calculateArgumentBindings();

    return springAdvice;
}

到此为止,获取了被@Aspect注解注释的类中所有的advice,并根据advice方法上注解的类型生成了Advisor。此时的Advisors包含的是候选的Advisors,接下来还需要筛选匹配当前Bean的Advisors链。

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 获取候选的Advisors
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 筛选出匹配当前Bean的Advisors链
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

上面findAdvisorsThatCanApply方法的实现如下:

protected List<Advisor> findAdvisorsThatCanApply(
    List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

    ProxyCreationContext.setCurrentProxiedBeanName(beanName);
    try {
        return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    }
    finally {
        ProxyCreationContext.setCurrentProxiedBeanName(null);
    }
}

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
    if (candidateAdvisors.isEmpty()) {
        return candidateAdvisors;
    }
    List<Advisor> eligibleAdvisors = new ArrayList<>();
    for (Advisor candidate : candidateAdvisors) {
        // 获取IntroductionAdvisor类型的Advisor
        if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
            eligibleAdvisors.add(candidate);
        }
    }
    boolean hasIntroductions = !eligibleAdvisors.isEmpty();
    for (Advisor candidate : candidateAdvisors) {
        if (candidate instanceof IntroductionAdvisor) {
            // already processed
            continue;
        }
        // 筛选的关键方法
        if (canApply(candidate, clazz, hasIntroductions)) {
            eligibleAdvisors.add(candidate);
        }
    }
    return eligibleAdvisors;
}

其中筛选的关键方法canApply的实现如下:

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;
        // 判断这个Advisor的PointCut是否可以应用到类中的某个方法上
        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");
    // 使用calssfilter来匹配class
    if (!pc.getClassFilter().matches(targetClass)) {
        return false;
    }

    MethodMatcher methodMatcher = pc.getMethodMatcher();
    if (methodMatcher == MethodMatcher.TRUE) {
        // 如果匹配的是任意方法,则无需迭代
        return true;
    }

    IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
    if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
        introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
    }
	
    // 查找当前类及其祖宗类实现的所有接口
    Set<Class<?>> classes = new LinkedHashSet<>();
    if (!Proxy.isProxyClass(targetClass)) {
        classes.add(ClassUtils.getUserClass(targetClass));
    }
    classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
	// 获取到所有的实现接口,然后遍历匹配接口的public方法
    for (Class<?> clazz : classes) {
        // 获取当前类的方法列表
        Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
        for (Method method : methods) {
            // 使用methodMatcher匹配方法,匹配成功即立即返回
            if (introductionAwareMethodMatcher != null ?
                introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                methodMatcher.matches(method, targetClass)) {
                return true;
            }
        }
    }

    return false;
}

筛选的工作主要由ClassFilterMethodMatcher 完成,比如AspectJExpressionPointcut的实现了ClassFilterMethodMatcher接口,最终由AspectJ表达式解析。找到Advisors链之后,调用sortAdvisors方法进行排序,最后得到的就是目标类使用的Advisors链。

总结

Spring AOP 如何 获取对应 Bean 适配的Advisors 链的核心逻辑如下

  • 获取当前ioc容器中所有的 Aspect 类
  • 给每个Aspect 类的advice 方法创建一个 Spring Advisor,这一步又能细分为
    • 遍历所有advice 方法
    • 解析方法的注解和pointcut
    • 实例化 Advisor 对象
  • 获取到候选的 Advisors并且缓存起来,方便下一次直接获取
  • 从候选的 Advisors 中筛选出与目标类适配的Advisor
    • 获取到Advisor 的切入点 pointcut
    • 获取到当前 target类所有的 public 方法
    • 遍历方法,通过切入点的methodMatcher匹配当前方法,只要有一个匹配成功,就相当于当前的Advisor 适配
  • 对筛选之后的 Advisor 链进行排序
  • 结束

解析Aspect实现Advice织入

前面得到了匹配当前Bean的Advisors链,接下来就需要调用createProxy方法来创建代理类对象,方法的实现如下:

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
                             @Nullable Object[] specificInterceptors, TargetSource targetSource) {
	
    // 如果bean工厂为ConfigurableListableBeanFactory
    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }
	// 创建ProxyBeanfactory
    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);
	
    // 如果proxyTargetClass设置为true,都是使用Cglib生成代理类
    // 否则,根据具体情况进行判断
    if (!proxyFactory.isProxyTargetClass()) {
        // 判断时根据接口还是类来生成代理类
        if (shouldProxyTargetClass(beanClass, beanName)) {
            // 根据类来生成代理类,使用Cglib代理
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            // 根据接口生成代理类
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }
	
    // 类所有的Advisors数组
    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    // 加入Advisor
    proxyFactory.addAdvisors(advisors);
    // 设置要代理的类
    proxyFactory.setTargetSource(targetSource);
    // 定制代理
    customizeProxyFactory(proxyFactory);
	// 默认为false,代理配置后不允许修改代理的配置
    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }
	// 根据工厂的各种配置生成代理类
    return proxyFactory.getProxy(getProxyClassLoader());
}

基本流程如下:

  • 获取当前类中的属性
  • 添加代理接口
  • 封装Advisor并加入到ProxyFactory
  • 设置要代理的类
  • Spring中为子类提供了定制的函数customizeProxyFactory,子类可以在此函数中对ProxyFactory的进一步封装
  • 获取代理操作

getProxy方法的实现如下,首先创建一个AopProxy,然后在获取代理类:

public Object getProxy(@Nullable ClassLoader classLoader) {
    return createAopProxy().getProxy(classLoader);
}

其中创建AopProxy源码如下:

protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
        activate();
    }
    return getAopProxyFactory().createAopProxy(this);
}

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    // 判断使用JDK代理还是Cglib代理
    // 如果proxyTargetClass为true,使用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.");
        }
        // 如果是实现接口,使用JDK动态代理生成代理类
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
           	// JDK代理生活曾代理类
            return new JdkDynamicAopProxy(config);
        }
        // 否则,使用Cglib生成代理类
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        // 上面的条件都不满足,则使用JDK动态代理
        return new JdkDynamicAopProxy(config);
    }
}

这一步之后我们根据ProxyConfig获取到了对应的AopProxy的实现类,分别是JdkDynamicAopProxyObjenesisCglibAopProxy

JDK动态代理

JdkDynamicAopProxy的定义如下:

public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
    Assert.notNull(config, "AdvisedSupport must not be null");
    if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
        throw new AopConfigException("No advisors and no TargetSource specified");
    }
    this.advised = config;
}

它的getProxy方法实现如下:

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
    @Override
    public Object getProxy() {
        return getProxy(ClassUtils.getDefaultClassLoader());
    }

    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isTraceEnabled()) {
            logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
        }
        // 获取完成的用于代理的接口集合
        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
        // 查找可能在提供的接口集上定义的任何equals或hashCode方法
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

最后也是调用了Proxy类的newProxyInstance方法来生成代理类对象。JDK动态代理中,用代理类的对应方法时,代理类实际上是通过invoke(Object proxy, Method method, Object[] args)方法来完成目标类方法的调用,并在里面进行一些代理类想做的增强操作。Spring AOP中,同样也是在invoke方法会完成AOP编织实现的封装。

invoke方法的实现如下:

@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object oldProxy = null;
    boolean setProxyContext = false;

    TargetSource targetSource = this.advised.targetSource;
    Object target = null;

    try {
        if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
            // 如果当前方法为equals方法,并且接口中未定义该方法,则自动生成equals方法
            return equals(args[0]);
        }
        else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
            // 如果当前方法为hashCode方法,并且接口中未定义该方法,则自动生成hashCode方法
            return hashCode();
        }
        else if (method.getDeclaringClass() == DecoratingProxy.class) {
            // There is only getDecoratedClass() declared -> dispatch to proxy config.
            return AopProxyUtils.ultimateTargetClass(this.advised);
        }
        else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                 method.getDeclaringClass().isAssignableFrom(Advised.class)) {
            // Service invocations on ProxyConfig with the proxy config...
            return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
        }

        Object retVal;
		// 有时目标类对象内部的自我调用无法实现切面增强,需要通过属性暴露代理
        if (this.advised.exposeProxy) {
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }

		// 获取目标类
        target = targetSource.getTarget();
        // 获取目标类的Class对象
        Class<?> targetClass = (target != null ? target.getClass() : null);

        // 获取方法的拦截器链,即Advisors链
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

       
        if (chain.isEmpty()) {
            // 如果没有拦截器,则直接调用目标类的对应方法
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
        }
        else {
            // 否则,先调用拦截器,在调用目标类方法
            MethodInvocation invocation =
                new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            // 责任链模式,沿着Advisors链前进
            retVal = invocation.proceed();
        }

        // 返回结果
        Class<?> returnType = method.getReturnType();
        if (retVal != null && retVal == target &&
            returnType != Object.class && returnType.isInstance(proxy) &&
            !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
            // Special case: it returned "this" and the return type of the method
            // is type-compatible. Note that we can't help if the target sets
            // a reference to itself in another returned object.
            retVal = proxy;
        }
        else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
            throw new AopInvocationException(
                "Null return value from advice does not match primitive return type for: " + method);
        }
        return retVal;
    }
    finally {
        if (target != null && !targetSource.isStatic()) {
            // Must have come from TargetSource.
            targetSource.releaseTarget(target);
        }
        if (setProxyContext) {
            // Restore old proxy.
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}

invoke方法逻辑的核心是利用责任链模式,递归调用的方法,来完成advice的织入。

理解设计模式中的责任链模式

因此,关键的实现逻辑在proceed方法,实现如下:

@Override
@Nullable
public Object proceed() throws Throwable {
    // 递归操作,从索引为-1的拦截器开始调用,并按序递增
    // 当Advisors链的Advisor全部迭代调用完毕后,开始调用目标类中的对应方法,通过反射实现
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        return invokeJoinpoint();
    }
	// 获取下一个要执行的Advisor
    Object interceptorOrInterceptionAdvice =
        this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
        InterceptorAndDynamicMethodMatcher dm =
            (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
        Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
        if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
            // 调用Advisor
            return dm.interceptor.invoke(this);
        }
        else {
            // Dynamic matching failed.
            // Skip this interceptor and invoke the next in the chain.
            return proceed();
        }
    }
    else {
        // 如果PointCut设置的是不是匹配具体的方法,则直接调用,不用匹配方法
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}

我们来看看((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this),这个方法有多种实现,其中一些我们熟悉的或者说需要关注的实现,对应的就是我们Advice的类型,或者说增强的时机。对应的有BeforeAfterAfter-returningAfter-throwingAround

Cglib动态代理

Cglib代理和JDK代理在流程上相似,只是在具体实现上不一样。核心就是Enhancer和获得callbacks的过程。ObjenesisCglibAopProxygetProxy方法的实现如下:

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
	}

	try {
           // 获取父类的Class对象,即目标类的Class类对象
		Class<?> rootClass = this.advised.getTargetClass();
		Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

		Class<?> proxySuperClass = rootClass;
		if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
			proxySuperClass = rootClass.getSuperclass();
			Class<?>[] additionalInterfaces = rootClass.getInterfaces();
			for (Class<?> additionalInterface : additionalInterfaces) {
				this.advised.addInterface(additionalInterface);
			}
		}

		// Validate the class, writing log messages as necessary.
		validateClassIfNecessary(proxySuperClass, classLoader);

		// 创建Cglib的Enhancer
		Enhancer enhancer = createEnhancer();
		if (classLoader != null) {
			enhancer.setClassLoader(classLoader);
			if (classLoader instanceof SmartClassLoader &&
					((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
				enhancer.setUseCache(false);
			}
		}
           // 设置父类
		enhancer.setSuperclass(proxySuperClass);
		enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
		enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
		enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

		Callback[] callbacks = getCallbacks(rootClass);
		Class<?>[] types = new Class<?>[callbacks.length];
		for (int x = 0; x < types.length; x++) {
			types[x] = callbacks[x].getClass();
		}
		// 设置回调
		enhancer.setCallbackFilter(new ProxyCallbackFilter(
				this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
		enhancer.setCallbackTypes(types);

		// 创建并返回代理类实例
		return createProxyClassAndInstance(enhancer, callbacks);
	}
	catch (CodeGenerationException | IllegalArgumentException ex) {
		throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
				": Common causes of this problem include using a final class or a non-visible class",
				ex);
	}
	catch (Throwable ex) {
		// TargetSource.getTarget() failed
		throw new AopConfigException("Unexpected AOP exception", ex);
	}
}

至此,Spring AOP实现面向切面的过程就解析结束了,当返回对应的代理类后,后续程序获取到的bean就是代理类对象,而不是目标类对象。对于目标类方法的代调用,都会代理到代理类对象上,在方法执行的前后进行增强操作的织入。

对于JDK代理和Cglib代理的选择原则是:如果是单例的我们最好使用CGLib代理,如果是多例的我们最好使用JDK代理

JDK在创建代理对象时的性能要高于CGLib代理,而生成代理对象的运行性能却比CGLib的低。


参考

Spring AOP 源码解析
Spring AOP - 注解方式使用介绍(长文详解)
向您图文并茂生动讲解Spring AOP 源码(2)
向您生动地讲解Spring AOP 源码(3)
Spring AOP 源码解析

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值