前文,咱们剖析了Spring IOC的初始化过程和Bean的生命周期等,而Spring AOP也是基于IOC的Bean加载来实现的。本文次要介绍Spring AOP原理解析的切面实现过程(将切面类的所有切面办法依据应用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor,为后续交给代理加强实现做筹备的过程)。@pdai
  • Spring框架系列(9) - Spring AOP实现原理详解之AOP切面的实现

    • 引入
    • aop配置标签的解析

      • config配置标签的解析
      • aspectj-autoproxy配置标签的解析
    • 注解切面代理创立类(AnnotationAwareAspectJAutoProxyCreator)

      • postProcessBeforeInstantiation

        • 判断是否是aop根底类
        • 是否应该跳过shouldSkip
        • 切面办法转成Advisor
        • 获取表达式的切点
        • 封装成Advisor
        • 小结
      • postProcessAfterInitialization
    • 总结
    • 更多文章

引入

咱们应该从哪里开始着手看Spring AOP的源码呢?和咱们上文剖析的IOC源码实现有什么关系呢?
  1. 前文中咱们写了AOP的Demo,依据其XML配置咱们不难发现AOP是基于IOC的Bean加载来实现的;这便使咱们的次要入口

所以了解Spring AOP的初始化必须要先了解Spring IOC的初始化。

  1. 而后咱们就能找到如下初始化的流程和aop对应的handler

即parseCustomElement办法找到parse aop:aspectj-autoproxy的handler(org.springframework.aop.config.AopNamespaceHandler)

(PS:其实你会发现,最重要的是知识点的关联关系,而不是知识点自身,就后续代码而言不就是打个断点缓缓看的事了么。)

aop配置标签的解析

上文中,咱们找到了AopNamespaceHandler,其实就是注册BeanDefinition的解析器BeanDefinitionParser,将aop:xxxxxx配置标签交给指定的parser来解决。
public class AopNamespaceHandler extends NamespaceHandlerSupport {    /**     * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the     * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'     * and '{@code scoped-proxy}' tags.     */    @Override    public void init() {        // In 2.0 XSD as well as in 2.5+ XSDs        // 注册解析<aop:config> 配置        registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());        // 注册解析<aop:aspectj-autoproxy> 配置        registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());        registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());        // Only in 2.0 XSD: moved to context namespace in 2.5+        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());    }}

config配置标签的解析

<aop:config/>由ConfigBeanDefinitionParser这个类解决,作为parser类最重要的就是parse办法

@Override@Nullablepublic BeanDefinition parse(Element element, ParserContext parserContext) {    CompositeComponentDefinition compositeDef =            new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));    parserContext.pushContainingComponent(compositeDef);    configureAutoProxyCreator(parserContext, element);    List<Element> childElts = DomUtils.getChildElements(element);    for (Element elt: childElts) {        String localName = parserContext.getDelegate().getLocalName(elt);        if (POINTCUT.equals(localName)) {            parsePointcut(elt, parserContext);        }        else if (ADVISOR.equals(localName)) {            parseAdvisor(elt, parserContext);        }        else if (ASPECT.equals(localName)) {            parseAspect(elt, parserContext);        }    }    parserContext.popAndRegisterContainingComponent();    return null;}

打个断点看下

parseAspect的办法如下, 解决办法不难,我这里就不开展了

private void parseAspect(Element aspectElement, ParserContext parserContext) {    String aspectId = aspectElement.getAttribute(ID);    String aspectName = aspectElement.getAttribute(REF);    try {        this.parseState.push(new AspectEntry(aspectId, aspectName));        List<BeanDefinition> beanDefinitions = new ArrayList<>();        List<BeanReference> beanReferences = new ArrayList<>();        List<Element> declareParents = DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS);        for (int i = METHOD_INDEX; i < declareParents.size(); i++) {            Element declareParentsElement = declareParents.get(i);            beanDefinitions.add(parseDeclareParents(declareParentsElement, parserContext));        }        // We have to parse "advice" and all the advice kinds in one loop, to get the        // ordering semantics right.        NodeList nodeList = aspectElement.getChildNodes();        boolean adviceFoundAlready = false;        for (int i = 0; i < nodeList.getLength(); i++) {            Node node = nodeList.item(i);            if (isAdviceNode(node, parserContext)) {                if (!adviceFoundAlready) {                    adviceFoundAlready = true;                    if (!StringUtils.hasText(aspectName)) {                        parserContext.getReaderContext().error(                                "<aspect> tag needs aspect bean reference via 'ref' attribute when declaring advices.",                                aspectElement, this.parseState.snapshot());                        return;                    }                    beanReferences.add(new RuntimeBeanReference(aspectName));                }                AbstractBeanDefinition advisorDefinition = parseAdvice(                        aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences);                beanDefinitions.add(advisorDefinition);            }        }        AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition(                aspectElement, aspectId, beanDefinitions, beanReferences, parserContext);        parserContext.pushContainingComponent(aspectComponentDefinition);        List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT);        for (Element pointcutElement : pointcuts) {            parsePointcut(pointcutElement, parserContext);        }        parserContext.popAndRegisterContainingComponent();    }    finally {        this.parseState.pop();    }}

aspectj-autoproxy配置标签的解析

<aop:aspectj-autoproxy/>则由AspectJAutoProxyBeanDefinitionParser这个类解决的,咱们看下parse 办法

@Override@Nullablepublic BeanDefinition parse(Element element, ParserContext parserContext) {    // 注册AspectJAnnotationAutoProxyCreator    AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);    // 拓展BeanDefinition    extendBeanDefinition(element, parserContext);    return null;}

AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary办法对应如下

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(        ParserContext parserContext, Element sourceElement) {    BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(            parserContext.getRegistry(), parserContext.extractSource(sourceElement));    useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);    registerComponentIfNecessary(beanDefinition, parserContext);}

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary对应如下

@Nullablepublic static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(        BeanDefinitionRegistry registry, @Nullable Object source) {    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);}

到这里,咱们发现AOP的创立工作是交给AnnotationAwareAspectJAutoProxyCreator来实现的。

注解切面代理创立类(AnnotationAwareAspectJAutoProxyCreator)

AnnotationAwareAspectJAutoProxyCreator是如何工作的呢?这时候咱们就要看AnnotationAwareAspectJAutoProxyCreator类构造关系了。

如下是类构造关系

它实现了两类接口:

  • BeanFactoryAware属于Bean级生命周期接口办法
  • InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,个别称它们的实现类为“后处理器”,是容器级生命周期接口办法

联合前文Spring Bean生命周期的流程

咱们就能够定位到外围的初始化办法必定在postProcessBeforeInstantiation和postProcessAfterInitialization中。

postProcessBeforeInstantiation

如下是上述类构造中postProcessBeforeInstantiation的办法,读者在本人看代码的时候倡议打个断点看,能够不便了解

@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {    Object cacheKey = getCacheKey(beanClass, beanName);    if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {        // 如果曾经在缓存中,则疏忽        if (this.advisedBeans.containsKey(cacheKey)) {            return null;        }        // 是否是aop根底类?是否跳过?        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {            this.advisedBeans.put(cacheKey, Boolean.FALSE);            return null;        }    }    // Create proxy here if we have a custom TargetSource.    // Suppresses unnecessary default instantiation of the target bean:    // The TargetSource will handle target instances in a custom fashion.    TargetSource targetSource = getCustomTargetSource(beanClass, beanName);    if (targetSource != null) {        if (StringUtils.hasLength(beanName)) {            this.targetSourcedBeans.add(beanName);        }        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);        Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);        this.proxyTypes.put(cacheKey, proxy.getClass());        return proxy;    }    return null;}

判断是否是aop根底类

是否是aop根底类的判断办法 isInfrastructureClass 如下

@Overrideprotected boolean isInfrastructureClass(Class<?> beanClass) {    // Previously we setProxyTargetClass(true) in the constructor, but that has too    // broad an impact. Instead we now override isInfrastructureClass to avoid proxying    // aspects. I'm not entirely happy with that as there is no good reason not    // to advise aspects, except that it causes advice invocation to go through a    // proxy, and if the aspect implements e.g the Ordered interface it will be    // proxied by that interface and fail at runtime as the advice method is not    // defined on the interface. We could potentially relax the restriction about    // not advising aspects in the future.    // 父类判断它是aop根底类 or 应用@Aspect注解    return (super.isInfrastructureClass(beanClass) ||            (this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));}

父类判断它是否是aop根底类的办法 super.isInfrastructureClass(beanClass), 实质上就是判断该类是否实现了Advice, Pointcut, Advisor或者AopInfrastructureBean接口。

protected boolean isInfrastructureClass(Class<?> beanClass) {    // 该类是否实现了Advice, Pointcut, Advisor或者AopInfrastructureBean接口    boolean retVal = Advice.class.isAssignableFrom(beanClass) ||            Pointcut.class.isAssignableFrom(beanClass) ||            Advisor.class.isAssignableFrom(beanClass) ||            AopInfrastructureBean.class.isAssignableFrom(beanClass);    if (retVal && logger.isTraceEnabled()) {        logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");    }    return retVal;}

是否应该跳过shouldSkip

通过断点辅助,candidateAdvisors是就是xml配置的告诉是对应的

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

切面办法转成Advisor

findCandidateAdvisors办法如下:

@Overrideprotected List<Advisor> findCandidateAdvisors() {    // 在父类中找到所有的advisor:基于xml配置的<aop:before/>生成的    List<Advisor> advisors = super.findCandidateAdvisors();    // 为bean Factory中AspectJ切面构建advistor:通过AspectJ注解的形式生成Advisor类    if (this.aspectJAdvisorsBuilder != null) {        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());    }    return advisors;}

在以后的bean Factory中通过AspectJ注解的形式生成Advisor类,buildAspectJAdvisors办法如下

/**    * Look for AspectJ-annotated aspect beans in the current bean factory,    * and return to a list of Spring AOP Advisors representing them.    * <p>Creates a Spring Advisor for each AspectJ advice method.    * @return the list of {@link org.springframework.aop.Advisor} beans    * @see #isEligibleBean    */public List<Advisor> buildAspectJAdvisors() {    List<String> aspectNames = this.aspectBeanNames;    if (aspectNames == null) {        synchronized (this) {            aspectNames = this.aspectBeanNames;            if (aspectNames == null) {                List<Advisor> advisors = new ArrayList<>();                aspectNames = new ArrayList<>();                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(                        this.beanFactory, Object.class, true, false);                for (String beanName : beanNames) {                    if (!isEligibleBean(beanName)) {                        continue;                    }                    // We must be careful not to instantiate beans eagerly as in this case they                    // would be cached by the Spring container but would not have been weaved.                    Class<?> beanType = this.beanFactory.getType(beanName, false);                    if (beanType == null) {                        continue;                    }                    if (this.advisorFactory.isAspect(beanType)) {                        aspectNames.add(beanName);                        AspectMetadata amd = new AspectMetadata(beanType, beanName);                        if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {                            MetadataAwareAspectInstanceFactory factory =                                    new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);                            List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);                            // 单例加到advisorsCache, 非单例加到aspectFactoryCache                            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);                            // advisorFactory工厂获取advisors                            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;}

上述办法实质上的思路是:用DCL双重锁的单例实现形式,拿到切面类里的切面办法,将其转换成advisor(并放入缓存中)。

转换的成advisor的办法是:this.advisorFactory.getAdvisors

@Overridepublic List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {    Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();    String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();    validate(aspectClass);    // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator    // so that it will only instantiate once.    MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =            new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);    List<Advisor> advisors = new ArrayList<>();    for (Method method : getAdvisorMethods(aspectClass)) {        // Prior to Spring Framework 5.2.7, advisors.size() was supplied as the declarationOrderInAspect        // to getAdvisor(...) to represent the "current position" in the declared methods list.        // However, since Java 7 the "current position" is not valid since the JDK no longer        // returns declared methods in the order in which they are declared in the source code.        // Thus, we now hard code the declarationOrderInAspect to 0 for all advice methods        // discovered via reflection in order to support reliable advice ordering across JVM launches.        // Specifically, a value of 0 aligns with the default value used in        // AspectJPrecedenceComparator.getAspectDeclarationOrder(Advisor).        Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);        if (advisor != null) {            advisors.add(advisor);        }    }    // If it's a per target aspect, emit the dummy instantiating aspect.    if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {        Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);        advisors.add(0, instantiationAdvisor);    }    // Find introduction fields.    for (Field field : aspectClass.getDeclaredFields()) {        Advisor advisor = getDeclareParentsAdvisor(field);        if (advisor != null) {            advisors.add(advisor);        }    }    return advisors;}

getAdvisor办法如下

@Override@Nullablepublic Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,        int declarationOrderInAspect, String aspectName) {    validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());    AspectJExpressionPointcut expressionPointcut = getPointcut(            candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());    if (expressionPointcut == null) {        return null;    }    // 封装成advisor    return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,            this, aspectInstanceFactory, declarationOrderInAspect, aspectName);}

获取表达式的切点

获取表达式的切点的办法getPointcut如下:

@Nullableprivate AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {    AspectJAnnotation<?> aspectJAnnotation =            AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);    if (aspectJAnnotation == null) {        return null;    }    AspectJExpressionPointcut ajexp =            new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);    ajexp.setExpression(aspectJAnnotation.getPointcutExpression());    if (this.beanFactory != null) {        ajexp.setBeanFactory(this.beanFactory);    }    return ajexp;}

AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod的办法如下

private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {        Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};/**    * Find and return the first AspectJ annotation on the given method    * (there <i>should</i> only be one anyway...).    */@SuppressWarnings("unchecked")@Nullableprotected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {    for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {        AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);        if (foundAnnotation != null) {            return foundAnnotation;        }    }    return null;}

findAnnotation办法如下

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

AnnotationUtils.findAnnotation 获取注解办法如下

/**    * Find a single {@link Annotation} of {@code annotationType} on the supplied    * {@link Method}, traversing its super methods (i.e. from superclasses and    * interfaces) if the annotation is not <em>directly present</em> on the given    * method itself.    * <p>Correctly handles bridge {@link Method Methods} generated by the compiler.    * <p>Meta-annotations will be searched if the annotation is not    * <em>directly present</em> on the method.    * <p>Annotations on methods are not inherited by default, so we need to handle    * this explicitly.    * @param method the method to look for annotations on    * @param annotationType the annotation type to look for    * @return the first matching annotation, or {@code null} if not found    * @see #getAnnotation(Method, Class)    */@Nullablepublic static <A extends Annotation> A findAnnotation(Method method, @Nullable Class<A> annotationType) {    if (annotationType == null) {        return null;    }    // Shortcut: directly present on the element, with no merging needed?    if (AnnotationFilter.PLAIN.matches(annotationType) ||            AnnotationsScanner.hasPlainJavaAnnotationsOnly(method)) {        return method.getDeclaredAnnotation(annotationType);    }    // Exhaustive retrieval of merged annotations...    return MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY, RepeatableContainers.none())            .get(annotationType).withNonMergedAttributes()            .synthesize(MergedAnnotation::isPresent).orElse(null);}

封装成Advisor

注:Advisor 是 advice的包装器,蕴含了advice及其它信息

由InstantiationModelAwarePointcutAdvisorImpl结构实现

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,        Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,        MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {    this.declaredPointcut = declaredPointcut;    this.declaringClass = aspectJAdviceMethod.getDeclaringClass();    this.methodName = aspectJAdviceMethod.getName();    this.parameterTypes = aspectJAdviceMethod.getParameterTypes();    this.aspectJAdviceMethod = aspectJAdviceMethod;    this.aspectJAdvisorFactory = aspectJAdvisorFactory;    this.aspectInstanceFactory = aspectInstanceFactory;    this.declarationOrder = declarationOrder;    this.aspectName = aspectName;    if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {        // 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);    }}

通过pointcut获取advice

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

交给aspectJAdvisorFactory获取

@Override@Nullablepublic Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,        MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {    // 获取切面类    Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();    validate(candidateAspectClass);    // 获取切面注解    AspectJAnnotation<?> aspectJAnnotation =            AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);    if (aspectJAnnotation == null) {        return null;    }    // If we get here, we know we have an AspectJ method.    // Check that it's an AspectJ-annotated class    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);    }    // 切面注解转换成advice    AbstractAspectJAdvice springAdvice;    switch (aspectJAnnotation.getAnnotationType()) {        case AtPointcut: // 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);    }    // 最初将其它切面信息配置到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的过程。

postProcessAfterInitialization

有了Adisor, 注入到适合的地位并交给代理(cglib和jdk)实现了。

/*** Create a proxy with the configured interceptors if the bean is* identified as one to proxy by the subclass.* @see #getAdvicesAndAdvisorsForBean*/@Overridepublic 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;}

后文中将别离介绍代理的创立和实现:

  • Spring进阶 - Spring AOP实现原理详解之AOP代理的创立
  • Spring进阶 - Spring AOP实现原理详解之Cglib代理实现
  • Spring进阶 - Spring AOP实现原理详解之JDK代理实现

总结

通过上文的剖析,咱们做下小结:

  1. IOC Bean加载办法栈中找到parseCustomElement办法,找到parse aop:aspectj-autoproxy的handler(org.springframework.aop.config.AopNamespaceHandler)
  2. AopNamespaceHandler注册了<aop:aspectj-autoproxy/>的解析类是AspectJAutoProxyBeanDefinitionParser
  3. AspectJAutoProxyBeanDefinitionParser的parse 办法 通过AspectJAwareAdvisorAutoProxyCreator类去创立
  4. AspectJAwareAdvisorAutoProxyCreator实现了两类接口,BeanFactoryAware和BeanPostProcessor;依据Bean生命周期办法找到两个外围办法:postProcessBeforeInstantiation和postProcessAfterInitialization

    1. postProcessBeforeInstantiation:次要是解决应用了@Aspect注解的切面类,而后将切面类的所有切面办法依据应用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor
    2. postProcessAfterInitialization:次要负责将Advisor注入到适合的地位,创立代理(cglib或jdk),为前面给代理进行加强实现做筹备。

更多文章

首先, 从Spring框架的整体架构和组成对整体框架有个认知。
  • Spring根底 - Spring和Spring框架组成

    • Spring是什么?它是怎么诞生的?有哪些次要的组件和外围性能呢? 本文通过这几个问题帮忙你构筑Spring和Spring Framework的整体认知。
其次,通过案例引出Spring的外围(IoC和AOP),同时对IoC和AOP进行案例应用剖析。
  • Spring根底 - Spring简略例子引入Spring的外围

    • 上文中咱们简略介绍了Spring和Spring Framework的组件,那么这些Spring Framework组件是如何配合工作的呢?本文次要承接上文,向你展现Spring Framework组件的典型利用场景和基于这个场景设计出的简略案例,并以此引出Spring的外围要点,比方IOC和AOP等;在此基础上还引入了不同的配置形式, 如XML,Java配置和注解形式的差别。
  • Spring根底 - Spring外围之管制反转(IOC)

    • 在Spring根底 - Spring简略例子引入Spring的外围中向你展现了IoC的根底含意,同时以此发散了一些IoC相干知识点; 本节将在此基础上进一步解读IOC的含意以及IOC的应用形式
  • Spring根底 - Spring外围之面向切面编程(AOP)

    • 在Spring根底 - Spring简略例子引入Spring的外围中向你展现了AOP的根底含意,同时以此发散了一些AOP相干知识点; 本节将在此基础上进一步解读AOP的含意以及AOP的应用形式。
基于Spring框架和IOC,AOP的根底,为构建下层web利用,须要进一步学习SpringMVC。
  • Spring根底 - SpringMVC申请流程和案例

    • 前文咱们介绍了Spring框架和Spring框架中最为重要的两个技术点(IOC和AOP),那咱们如何更好的构建下层的利用呢(比方web 利用),这便是SpringMVC;Spring MVC是Spring在Spring Container Core和AOP等技术根底上,遵循上述Web MVC的标准推出的web开发框架,目标是为了简化Java栈的web开发。 本文次要介绍SpringMVC的申请流程和根底案例的编写和运行。
Spring进阶 - IoC,AOP以及SpringMVC的源码剖析
  • Spring进阶 - Spring IOC实现原理详解之IOC体系结构设计

    • 在对IoC有了初步的认知后,咱们开始对IOC的实现原理进行深刻了解。本文将帮忙你站在设计者的角度去看IOC最顶层的结构设计
  • Spring进阶 - Spring IOC实现原理详解之IOC初始化流程

    • 上文,咱们看了IOC设计要点和设计构造;紧接着这篇,咱们能够看下源码的实现了:Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的
  • Spring进阶 - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)

    • 上文,咱们看了IOC设计要点和设计构造;以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的;容器中寄存的是Bean的定义即BeanDefinition放到beanDefinitionMap中,实质上是一个ConcurrentHashMap<String, Object>;并且BeanDefinition接口中蕴含了这个类的Class信息以及是否是单例等。那么如何从BeanDefinition中实例化Bean对象呢,这是本文次要钻研的内容?
  • Spring进阶 - Spring AOP实现原理详解之切面实现

    • 前文,咱们剖析了Spring IOC的初始化过程和Bean的生命周期等,而Spring AOP也是基于IOC的Bean加载来实现的。本文次要介绍Spring AOP原理解析的切面实现过程(将切面类的所有切面办法依据应用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor,为后续交给代理加强实现做筹备的过程)。
  • Spring进阶 - Spring AOP实现原理详解之AOP代理

    • 上文咱们介绍了Spring AOP原理解析的切面实现过程(将切面类的所有切面办法依据应用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor)。本文在此基础上持续介绍,代理(cglib代理和JDK代理)的实现过程。
  • Spring进阶 - Spring AOP实现原理详解之Cglib代理实现

    • 咱们在前文中曾经介绍了SpringAOP的切面实现和创立动静代理的过程,那么动静代理是如何工作的呢?本文次要介绍Cglib动静代理的案例和SpringAOP实现的原理。
  • Spring进阶 - Spring AOP实现原理详解之JDK代理实现

    • 上文咱们学习了SpringAOP Cglib动静代理的实现,本文次要是SpringAOP JDK动静代理的案例和实现局部。
  • Spring进阶 - SpringMVC实现原理之DispatcherServlet初始化的过程

    • 前文咱们有了IOC的源码根底以及SpringMVC的根底,咱们便能够进一步深刻了解SpringMVC次要实现原理,蕴含DispatcherServlet的初始化过程和DispatcherServlet解决申请的过程的源码解析。本文是第一篇:DispatcherServlet的初始化过程的源码解析。
  • Spring进阶 - SpringMVC实现原理之DispatcherServlet解决申请的过程

    • 前文咱们有了IOC的源码根底以及SpringMVC的根底,咱们便能够进一步深刻了解SpringMVC次要实现原理,蕴含DispatcherServlet的初始化过程和DispatcherServlet解决申请的过程的源码解析。本文是第二篇:DispatcherServlet解决申请的过程的源码解析。