AOP过程源码分析

一些概念

  1. Advice:一段具体的切面逻辑,例如:目标方法执行前需要执行的那段代码就是advice
  2. Advisor:它内部需要指定一个 AdviceAdvisor 决定该拦截哪些方法,拦截后需要完成的工作还是内部的 Advice 来做
  3. Pointcut:切入点,用于定义哪些方法需要被增强或者说需要被拦截
  4. Aspect:一般会定义一堆Pointcut
  5. Joinpoint:一般作为advice的第一个参数

加载

在Bean加载完成之后,执行完org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)之后,会执行后置处理器BeanPostProcessorsorg.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization),在后置处理器中有AbstractAutoProxyCreator来判断当前Bean是否有切面,如果有切面的话,就会创建一个代理对象并返回。

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;
        }
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // Create proxy if we have advice.
        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;
    }

getAdvicesAndAdvisorsForBean中寻找advisor的逻辑

    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 寻找候选的advisor 
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 寻找可用的advisor
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
      // 对advisor进行排序(按照order 默认order为Integer.MAX_VALUE)
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

findCandidateAdvisors中分为了两步获取advisor

  1. 寻找所有实现了Advisor接口的advisor,其中
  2. 寻找所有被@AspectJ注解标记的advisor
    protected List<Advisor> findCandidateAdvisors() {
        // Add all the Spring advisors found according to superclass rules.
        List<Advisor> advisors = super.findCandidateAdvisors();
        // Build Advisors for all AspectJ aspects in the bean factory.
        if (this.aspectJAdvisorsBuilder != null) {
            advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }
        return advisors;
    }

其中TransactionAttributeSourceAdvisor就是实现了Advisor接口,内部有一个TransactionInterceptor,会通过getAdvice()返回,因此在后续的advisor将会使用TransactionInterceptor来进行切入。

image-20230825183806044

buildAspectJAdvisors()的逻辑主要是寻找所有@AspectJ的Bean,其中org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#aspectBeanNames为:所有的@AspectJ标记的Bean

aspectBeanNames的判断逻辑

org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors中的this.advisorFactory.isAspect(beanType)进行判断

public boolean isAspect(Class<?> clazz) {
  return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}

private boolean hasAspectAnnotation(Class<?> clazz) {
  return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
}

private boolean compiledByAjc(Class<?> clazz) {
        // The AJTypeSystem goes to great lengths to provide a uniform appearance between code-style and
        // annotation-style aspects. Therefore there is no 'clean' way to tell them apart. Here we rely on
        // an implementation detail of the AspectJ compiler.
    // AJC_MAGIC = "ajc$";
        for (Field field : clazz.getDeclaredFields()) {
            if (field.getName().startsWith(AJC_MAGIC)) {
                return true;
            }
        }
        return false;
}

可以看到会把类中有Aspect注解的类加入到Advisor中

image-20230824180421675

寻找可用的advisors

org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply

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

遍历类中的所有方法,逐个匹配切入点(pointCut

advisors排序

org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#sortAdvisors对advisors进行排序

org.springframework.core.annotation.AnnotationAwareOrderComparator为advisors的比较器,通过findOrder()提供切面中的order值。

public int compare(Advisor o1, Advisor o2) {
        int advisorPrecedence = this.advisorComparator.compare(o1, o2);
        if (advisorPrecedence == SAME_PRECEDENCE && declaredInSameAspect(o1, o2)) {
            advisorPrecedence = comparePrecedenceWithinAspect(o1, o2);
        }
        return advisorPrecedence;
    }
    private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) {
        boolean p1 = (o1 instanceof PriorityOrdered);
        boolean p2 = (o2 instanceof PriorityOrdered);
        if (p1 && !p2) {
            return -1;
        }
        else if (p2 && !p1) {
            return 1;
        }

        int i1 = getOrder(o1, sourceProvider);
        int i2 = getOrder(o2, sourceProvider);
        return Integer.compare(i1, i2);
    }

org.springframework.core.annotation.AnnotationAwareOrderComparator#findOrder

    protected Integer findOrder(Object obj) {
        Integer order = super.findOrder(obj);
        if (order != null) {
            return order;
        }
        return findOrderFromAnnotation(obj);
    }

根据order的大小排,大的优先级低,小的优先级高。

执行

生成的代理类基本都是DynamicAdvisedInterceptor类型,DynamicAdvisedInterceptorCglibAopProxy的子。

image-20230825164240115

因此会执行到org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept这个方法中。

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            Object oldProxy = null;
            boolean setProxyContext = false;
            Object target = null;
            TargetSource targetSource = this.advised.getTargetSource();
            try {
                if (this.advised.exposeProxy) {
                    // Make invocation available if necessary.
                    oldProxy = AopContext.setCurrentProxy(proxy);
                    setProxyContext = true;
                }
                // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
                target = targetSource.getTarget();
                Class<?> targetClass = (target != null ? target.getClass() : null);
        // chain中存储了需要进行调用的切面,其顺序是按照类中的order进行排序
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                Object retVal;
                // Check whether we only have one InvokerInterceptor: that is,
                // no real advice, but just reflective invocation of the target.
        // 如果不存在切面,那么直接执行目标方法
                if (chain.isEmpty() && CglibMethodInvocation.isMethodProxyCompatible(method)) {
                    // We can skip creating a MethodInvocation: just invoke the target directly.
                    // Note that the final invoker must be an InvokerInterceptor, so we know
                    // it does nothing but a reflective operation on the target, and no hot
                    // swapping or fancy proxying.
                    Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                    retVal = invokeMethod(target, method, argsToUse, methodProxy);
                }
                else {
                    // We need to create a method invocation...
          // 如果存在切面,在此处进行调用
                    retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
                }
                retVal = processReturnType(proxy, target, method, retVal);
                return retVal;
            }
            finally {
                if (target != null && !targetSource.isStatic()) {
                    targetSource.releaseTarget(target);
                }
                if (setProxyContext) {
                    // Restore old proxy.
                    AopContext.setCurrentProxy(oldProxy);
                }
            }
        }

接着进入org.springframework.aop.framework.ReflectiveMethodInvocation#proceed方法

public Object proceed() throws Throwable {
        // We start with an index of -1 and increment early.
  // proceed方法会循环调用,直到interceptorsAndDynamicMethodMatchers中的所有切面都执行完
  // currentInterceptorIndex 为当前调用的第几个切面
  // interceptorsAndDynamicMethodMatchers为所有切面
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }

  // 每调用一次interceptorsAndDynamicMethodMatchers会加1
        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
      // 是否是动态生成的Interceptor,通过@AspecJ注解标记的切面都是这种类型
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            // Evaluate dynamic method matcher here: static part will already have
            // been evaluated and found to match.
            InterceptorAndDynamicMethodMatcher dm =
                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
            if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
                return dm.interceptor.invoke(this);
            }
            else {
                // Dynamic matching failed.
                // Skip this interceptor and invoke the next in the chain.
                return proceed();
            }
        }
        else {
            // It's an interceptor, so we just invoke it: The pointcut will have
            // been evaluated statically before this object was constructed.
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

第一个执行的是ExposeInvocationInterceptor,这个是spring默认的,通过threadlocal来记录方法调用的全链路。

ExposeInvocationInterceptor内部invoke方法比较简单

public Object invoke(MethodInvocation mi) throws Throwable {
    // invocation 为 thread local
        MethodInvocation oldInvocation = invocation.get();
        invocation.set(mi);
        try {
            return mi.proceed();
        }
        finally {
            invocation.set(oldInvocation);
        }
    }

@Around为例,对于动态生成的切面会执行到此处org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint#proceed(java.lang.Object[])

    public Object proceed(Object[] arguments) throws Throwable {
        Assert.notNull(arguments, "Argument array passed to proceed cannot be null");
        if (arguments.length != this.methodInvocation.getArguments().length) {
            throw new IllegalArgumentException("Expecting " +
                    this.methodInvocation.getArguments().length + " arguments to proceed, " +
                    "but was passed " + arguments.length + " arguments");
        }
        this.methodInvocation.setArguments(arguments);
    // 在执行完invocableClone之后会继续调用proceed()方法,因此会回到前面循环,执行下一个切面
        return this.methodInvocation.invocableClone(arguments).proceed();
    }

org.springframework.aop.framework.ReflectiveMethodInvocation#invocableClone(java.lang.Object...)内部逻辑如下,可以看到通过系统调用对当前对象尽行了一次clone,然后把当前的ReflectiveMethodInvocation返回,所以可以继续执行proceed()

public MethodInvocation invocableClone(Object... arguments) {
        // Force initialization of the user attributes Map,
        // for having a shared Map reference in the clone.
        if (this.userAttributes == null) {
            this.userAttributes = new HashMap<>();
        }

        // Create the MethodInvocation clone.
        try {
      // clone() 为系统调用
            ReflectiveMethodInvocation clone = (ReflectiveMethodInvocation) clone();
            clone.arguments = arguments;
            return clone;
        }
        catch (CloneNotSupportedException ex) {
            throw new IllegalStateException(
                    "Should be able to clone object of type [" + getClass() + "]: " + ex);
        }
    }

所有切面执行完,最后调用目标方法org.springframework.aop.framework.CglibAopProxy.CglibMethodInvocation#invokeJoinpoint,执行完目标方法返回结果。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇