专栏首页Java技术大杂烩Spring AOP 注解方式源码解析

Spring AOP 注解方式源码解析

本文首发于个人公众号 Java 技术大杂烩,欢迎关注

前言

在上篇文章 Spring AOP 功能使用详解 中,知道了 Sprig AOP 的一个详细用法,现在的看看Spring 中是如何实现的。

aspectj-autoproxy

我们知道,要想使用 Spring AOP ,必须首先在配置文件中添加该配置项 <aop:aspectj-autoproxy expose-proxy="true" proxy-target-class="true"/> ,其中的两个属性是可选的。对于 Spring 的每一个标签都有对应的解析器来进行解析,而对于 aspectj-autoproxy 标签则会使用 AspectJAutoProxyBeanDefinitionParser 解析器来进行解析,如下所示:

public class AopNamespaceHandler extends NamespaceHandlerSupport {
    @Override
    public void init() {
        registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
        // 注册 aspectj-autoproxy 标签的解析器
        registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
        registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    }
}

AspectJAutoProxyBeanDefinitionParser 中主要完成两部分功能,一个是注册 AnnotationAwareAspectJAutoProxyCreator 这个 bean,一个就是解析<aop:aspectj-autoproxy /> 的两个属性 其中 对于 AOP 的功能,基本上都是靠 AnnotationAwareAspectJAutoProxyCreator 来完成的;

注册 AnnotationAwareAspectJAutoProxyCreator

所有的解析器都实现了接口 BeanDefinitionParser,入口都是从 parse 方法开始进行解析的,而 AspectJAutoProxyBeanDefinitionParserparse 方法如下:

class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        // 注册AnnotationAwareAspectJAutoProxyCreator bean 和处理标签的两个属性
        AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
        // 处理子标签
        extendBeanDefinition(element, parserContext);
        return null;
    }
}

AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary 方法如下:

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {
    // 注册 AnnotationAwareAspectJAutoProxyCreator
    BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            parserContext.getRegistry(), parserContext.extractSource(sourceElement));
    // 解析标签的两个属性expose-proxy 和 proxy-target-class
    useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
    // 注册组件并通知,便于监听器进一步处理,这里可以不用看
    registerComponentIfNecessary(beanDefinition, parserContext);
}

在该方法中,主要完成三个功能,每行代码完成一个功能:

  1. 注册 AnnotationAwareAspectJAutoProxyCreator
  2. 处理 expose-proxy 和 proxy-target-class 属性
  3. 注册组件并通知

注册 AnnotationAwareAspectJAutoProxyCreator

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
// 注册
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
    //如果已经注册且与现在的不一致,则需要根据优先级来判断到底需要使用哪一个
    //AUTO_PROXY_CREATOR_BEAN_NAME=org.springframework.aop.config.internalAutoProxyCreator
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        // 如果缓存中和现在注册的class不一样
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            int requiredPriority = findPriorityForClass(cls);
            // 判断优先级,如果现在的优先级比缓存中的大,则取现在的这个
            if (currentPriority < requiredPriority) {
                apcDefinition.setBeanClassName(cls.getName());
            }
        }
        //如果相同,则无需再创建
        return null;
    }
    // 如果还没有注册,则进行注册
    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    // 注册
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}

处理 expose-proxy 和 proxy-target-class 属性

处理 expose-proxy 和 proxy-target-class 属性

private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry,Element sourceElement) {
    if (sourceElement != null) {
        // 获取proxy-target-class的值
        boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
        if (proxyTargetClass) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }
        // 获取 expose-proxy的值
        boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
        if (exposeProxy) {
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
        }
    }
}
//设置属性 proxyTargetClass 为true
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
    }
}
//设置属性 exposeProxy为true
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
    }
}

到这里,就完成了AnnotationAwareAspectJAutoProxyCreator 的注册,上面说过, AOP 的功能,基本上都是靠 AnnotationAwareAspectJAutoProxyCreator 来完成的,接下来看看这个类是如何完成AOP操作的。

解析 Advce

先来看看 AnnotationAwareAspectJAutoProxyCreator 的类图如下所示:

从上面的类图可知,AnnotationAwareAspectJAutoProxyCreator 实现了 BeanPostProcessor ,在 Spring 中实现了该接口的bean,当 Spring 在加载该 bean 时会在初始化之前调用它的 postProcessAfterInitializatio方法;父类 AbstractAutoProxyCreatorpostProcessAfterInitialization 方法实现如下:

public Object postProcessAfterInitialization(Object bean, String beanName) {
    if (bean != null) {
        // 根据beanClass 和 beanName 创建缓存的 key
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            // 如果该bean适合被代理,则必须包装
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}
// 包装bean
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    // 如果已经处理过,则直接返回
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    // 该bean无需增强,则直接返回
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    //如果bean是Advice.class, Pointcut.class, Advisor.class, AopInfrastructureBean.class, 则直接返回
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        // 添加该bean不需要增强的标志到缓存中
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // 获取bean所有的增强
    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;
}

从上述代码可知,在实例化 AnnotationAwareAspectJAutoProxyCreator 之前会对 AOP 增强进行解析,解析到增强后,会对增强创建代理;这篇文章先来看看增强的获取,关于代理的创建,则在下一篇文章进行讲解。

获取增强

根据 bean 对应的 class 和 beanName 来获取它所有的增强,对于方法为 getAdvicesAndAdvisorsForBean()

protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
    // 找出所有符合条件的增强
    List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
    if (advisors.isEmpty()) {
        return DO_NOT_PROXY;
    }
    return advisors.toArray();
}

findEligibleAdvisors() 方法:

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 获取所有增强
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 获取所有增强中适用于 bean 的增强并应用
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    // 对增强进行扩展和排序
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

其中获取所有增强的方法 findCandidateAdvisors() 经过大量复杂的逻辑判断,AOP 增强的获取和切点表达式的解析都在该方法内部进行实现 :

protected List<Advisor> findCandidateAdvisors() {
    // 调用父类方法加载配置文件中的AOP声明
    List<Advisor> advisors = super.findCandidateAdvisors();
    // 创建所有AspectJ增强
    if (this.aspectJAdvisorsBuilder != null) {
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }
    return advisors;
}
//父类 findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {
    return this.advisorRetrievalHelper.findAdvisorBeans();
}
// 寻找所有符合增强的bean,this.advisorRetrievalHelper.findAdvisorBeans
public List<Advisor> findAdvisorBeans() {
    String[] advisorNames = this.cachedAdvisorBeanNames;
    if (advisorNames == null) {
        // 寻找Advisor注解的beanName
        advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);
        this.cachedAdvisorBeanNames = advisorNames;
    }
    List<Advisor> advisors = new ArrayList<>();
    for (String name : advisorNames) {
        // 该bean符合增强
        if (isEligibleBean(name)) {
            if (this.beanFactory.isCurrentlyInCreation(name)) {
                // 该bean正创建,则忽略
            }
            else {
                advisors.add(this.beanFactory.getBean(name, Advisor.class));
            }
        }
    }
    return advisors;
}

获取 bean 的注解增强,对应方法 this.aspectJAdvisorsBuilder.buildAspectJAdvisors(),查找所有 AspectJ 注解的bean,对于每一个增强方法,都会创建对应的Advisor,即一个方法对于一个Advisor

// 查找所有 AspectJ 注解的bean,对于每一个增强方法,都会创建对应的Advisor,即一个方法对于一个Advisor
public List<Advisor> buildAspectJAdvisors() {
    List<String> aspectNames = this.aspectBeanNames;
    // .... 省略一些null判断
    List<Advisor> advisors = new ArrayList<>();
    aspectNames = new ArrayList<>();
    // 获取所有的 beanName
    String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
    for (String beanName : beanNames) {
        // 如果该 bean不符合条件,则跳过
        if (!isEligibleBean(beanName)) {
            continue;
        }
        Class<?> beanType = this.beanFactory.getType(beanName);
        // 如果该 bean 存在 Aspect 注解
        if (this.advisorFactory.isAspect(beanType)) {
            aspectNames.add(beanName);
            // 根据beanType和beanName创建AspectMetadata ,表示增强的元数据
            AspectMetadata amd = new AspectMetadata(beanType, beanName);
            if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                // 解析标记了 AspectJ 注解中的增强方法
                List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                if (this.beanFactory.isSingleton(beanName)) {
                    // 如果该 bean是单例,则直接把解析到增强方法放到缓存中
                    this.advisorsCache.put(beanName, classAdvisors);
                }else {
                    //否则把对于的工厂放到缓存中
                    this.aspectFactoryCache.put(beanName, factory);
                }
                advisors.addAll(classAdvisors);
             }else {
                tadataAwareAspectInstanceFactory 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;
}

上述方法已经完成了 Advisor 的提取,其中增强器的获取则交给了 advisorFactory.getAdvisors() 方法,如下:

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
    //获取标记为 AspectJ 的类
    Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    // 获取name
    String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
    //验证aspectClass 
    validate(aspectClass);

    //AOP 可以将增强延迟初始化,这里使用装饰器对工厂将包装
    MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

    List<Advisor> advisors = new ArrayList<>();
    // 处理每个增强方法,getAdvisorMethods 返回该增强类的所有增强方法
    for (Method method : getAdvisorMethods(aspectClass)) {
        // 每个方法对应一个 advisor
        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);
    }

    // 获取 DeclareParents 注解
    for (Field field : aspectClass.getDeclaredFields()) {
        Advisor advisor = getDeclareParentsAdvisor(field);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }
    return advisors;
}

//获取增强类的所有增强方法 getAdvisorMethods 
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
    final List<Method> methods = new ArrayList<>();
    ReflectionUtils.doWithMethods(aspectClass, method -> {
        // 排除掉 Pointcut 方法
        if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
            methods.add(method);
        }
    });
    methods.sort(METHOD_COMPARATOR);
    return methods;
}

普通增强器的获取

普通增强器的获取是通过 getAdvisor() 方法来获取的,其中包括了对切点注解的获取和注解信息生成增强,如下:

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) {
    // 切点信息的获取,如@After, @Before
    AspectJExpressionPointcut expressionPointcut = getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
    // 根据切点信息,生成不同的增强器
    return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

获取切点信息 getPonitcut:

private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
    // 获取方法上的注解
    AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    // 使用 AspectJExpressionPointcut 封装切点信息
    AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
    // 设置切点表达式如:execution(* *Service*(..))
    ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
    if (this.beanFactory != null) {
        ajexp.setBeanFactory(this.beanFactory);
    }
    return ajexp;
}

// 获取方法上的注解 findAspectJAnnotationOnMethod
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
    // ASPECTJ_ANNOTATION_CLASSES 是一个数组:{Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class}
    for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
        AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
        if (foundAnnotation != null) {
            return foundAnnotation;
        }
    }
    return null;
}
// 获取注解
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
    A result = AnnotationUtils.findAnnotation(method, toLookFor);
    if (result != null) {
        return new AspectJAnnotation<>(result);
    }
    else {
        return null;
    }
}

上述方法获取到具体的切点信息后,会根据切点信息生成对应的增强器,每一种切点信息如 @After, @Before 都对应一种 InstantiationModelAwarePointcutAdvisorImpl 对象,如下:

new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName)

在该对象实例化的过程中,就是一些赋值过程,此外,根据不同的增强类型,如 @After, @Before,需要创建不同的增强器,如下所示:

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
        Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
        MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
    // .... 一些属性的赋值操作
    // A singleton aspect.
    this.pointcut = this.declaredPointcut;
    this.lazy = false;
    this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);

}

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

// 创建不同的增强器
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
        MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
    // 获取 Aspect 注解对应的class
    Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    validate(candidateAspectClass);
    // 再次获取Aspect注解类的所有增强方法来进行判断
    AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    if (aspectJAnnotation == null) {
        return null;
    }
    // 最终的增强器
    AbstractAspectJAdvice springAdvice;
    // 根据注解类型创建不同的增强器
    switch (aspectJAnnotation.getAnnotationType()) {
        // Pointcut注解 不处理
        case AtPointcut:
            return null;
        case AtAround:
            // around 注解,对应AspectJAroundAdvice增强器
            springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        case AtBefore:
            // Before注解,对应AspectJMethodBeforeAdvice增强器
            springAdvice = new AspectJMethodBeforeAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        case AtAfter:
           // After注解,对应AspectJAfterAdvice增强器
            springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        case AtAfterReturning:
             // AfterReturning注解,对应AfterReturning增强器
            springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
            // 设置返回值
            if (StringUtils.hasText(afterReturningAnnotation.returning())) {
                springAdvice.setReturningName(afterReturningAnnotation.returning());
            }
            break;
        case AtAfterThrowing:
            // AtAfterThrowing注解,对应AspectJAfterThrowingAdvice增强器
            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);
    }

    // 对获取到增强器进行一些配置
    springAdvice.setAspectName(aspectName);
    springAdvice.setDeclarationOrder(declarationOrder);
    String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
    if (argNames != null) {
        springAdvice.setArgumentNamesFromStringArray(argNames);
    }
    springAdvice.calculateArgumentBindings();

    return springAdvice;
}

接下来看下增强器的实现:

@Before 注解对应的增强器 AspectJMethodBeforeAdvice

springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);

public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {

    public AspectJMethodBeforeAdvice(Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
        super(aspectJBeforeAdviceMethod, pointcut, aif);
    } 
    // before 方法
    @Override
    public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
        invokeAdviceMethod(getJoinPointMatch(), null, null);
    }
    // .......
}
// invokeAdviceMethod 方法
protected Object invokeAdviceMethod(JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex){
        return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
}
// invokeAdviceMethodWithGivenArgs 方法:
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
    Object[] actualArgs = args;
    if (this.aspectJAdviceMethod.getParameterCount() == 0) {
        actualArgs = null;
    }
    ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
    // 激活增强方法
    return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);

}

上述几种不同类型的增强器都是 AbstractAspectJAdvice 的子类,最终都会在该类的 invokeAdviceMethod 方法中去激活增强方法。

上述的几个方法逻辑已经完成了所有增强器的解析,但是对于所有的增强器来说,并不一定都适用于当前的bean,所以还需要选出适合的增强器,

也就是上述 findEligibleAdvisors 方法的第二步,即 findAdvisorsThatCanApply 方法:

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 获取所有增强
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 获取所有增强中适用于 bean 的增强并应用
    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 {
        // 过滤已经得到的 advisors
        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) {
        // 首先处理引介增强
        if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
            eligibleAdvisors.add(candidate);
        }
    }
    boolean hasIntroductions = !eligibleAdvisors.isEmpty();
    for (Advisor candidate : candidateAdvisors) {
        if (candidate instanceof IntroductionAdvisor) {
            // 上面已经处理过了
            continue;
        }
        if (canApply(candidate, clazz, hasIntroductions)) {
            eligibleAdvisors.add(candidate);
        }
    }
    return eligibleAdvisors;
}

findAdvisorsThatCanApply 的主要作用是根据beanClass方法增强来判断该增强是否适用于当前的bean,对应方法为 canAppley() ,如下:

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 {
        return true;
    }
}

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
    // 不匹配,直接返回
    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));
    // 判断方法是否匹配
    for (Class<?> clazz : classes) {
        Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
        for (Method method : methods) {
            if (introductionAwareMethodMatcher != null ?
                    introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                    methodMatcher.matches(method, targetClass)) {
                return true;
            }
        }
    }
    return false;
}

以上就是 Spring AOP 增强的解析,它包括了 Aspect 注解类的解析和该类下所有增强方法的解析。

总结

Spring AOP 功能,对应的解析类实现了 BeanPostProcessor 接口,这可以让我们在 bean 初始化之前可以对 bean 进行一些操作,对于 注解的 AOP 来说,在实例化 AnnotationAwareAspectJAutoProxyCreator bean 之前,会去解析 Aspect 注解的类,以及该类下所有的增强方法,每个增强方法都会对应一个 Advisor ,在解析增强方法得到 Advisor 时,则会根据方法不同的注解类型来创建不同的增强器。

上述主要介绍了如何去获取bean 对应的增强器,我们知道, Spring AOP 是通过动态代理来实现,在获取到增强器之后,就可以来创建对应的代理了,关于代理的创建,下篇文章介绍。

本文分享自微信公众号 - Java技术大杂烩(tsmyk0715),作者:TSMYK

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-01-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Spring 事务初始化源码分析

    在上篇文章 Spring 事务使用详解 中详细介绍了 Spring 事务的使用过程,今天就来看下 Spring 事务是如何来实现,比如 Spring 事务在初始...

    Java技术大杂烩
  • Spring 的 getBean 方法源码解析

    在文章 Spring 中 bean 注册的源码解析 和 Spring bean 创建过程源码解析 了解了 bean 的注册和创建过程,当通过 getBean 方...

    Java技术大杂烩
  • Spring bean 创建过程源码解析

    在上一篇文章 Spring 中 bean 注册的源码解析 中分析了 Spring 中 bean 的注册过程,就是把配置文件中配置的 bean 的信息加载到内...

    Java技术大杂烩
  • Spring AOP 源码分析 - 筛选合适的通知器

    从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析。本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP ...

    田小波
  • SpringAop源码分析(基于注解)二:筛选通知器

    我们已经知道BeanPostProcessors是在Bean实例化前后起作用的,如果看过前面的文章Spring Ioc源码分析 之 Bean的加载(八):初始化...

    大王叫下
  • Netty之WebSocket协议应用开发

    上一篇聊了一下使用Netty进行HTTP协议的应用开发,今儿就来说一下HTTP协议的弊端以及WebSocket协议的开发使用。

    Liusy
  • 算法:有效括号

    版权声明: ...

    Fisherman渔夫
  • [续]iOS开发中的这些权限,你搞懂了吗?

    Jacklin999
  • iOS开发中权限再度梳理

    Jacklin999
  • SQL反模式学习笔记5 外键约束【不用钥匙的入口】

    一些开发人员不推荐使用引用完整性约束,可能不使用外键的原因有一下几点:

    张传宁老师

扫码关注云+社区

领取腾讯云代金券