SpringBoot AoP(4)代理类的创建与运行

1,083 阅读2分钟

创建

AbstractAutoProxyCreator->wrapIfNecessary():
    // 如果有的话,就创建代理
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

先遍历切面方法,如果未解析会先解析切面表达式,之后查看bean的类和方法,看是否符合切面表达式,符合的话,返回的specificInterceptors就不会为空了

AopUtils->canApply():
    // 这里matches方法一般都返回true,但是getClassFilter第一次调用时,会解析切面方法
    if (!pc.getClassFilter().matches(targetClass)) {
        return false;
    }
    ......
    for (Class<?> clazz : classes) {
        Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
        for (Method method : methods) {
            // 不同的切面表达式有不同的逻辑,但最终都是遍历方法,返回truefalse
            // 比如@annotation()是看方法有无目标注解
            // @within()是看类有无目标注解
            // 由此可见,只要有一个方法满足了切面表达式,就会创建aop代理
            if (introductionAwareMethodMatcher != null ?
                    introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                    methodMatcher.matches(method, targetClass)) {
                return true;
            }
        }
    }
    return false;
AbstractAutoProxyCreator->wrapIfNecessary():
    // 根据返回的specificInterceptors是否为空来判断是否满足切面表达式
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 这里返回的的proxy即为被代理的对象
        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;
AbstractAutoProxyCreator->createProxy():
    return proxyFactory.getProxy(getProxyClassLoader());
ProxyFactory->getProxy():
    return createAopProxy().getProxy(classLoader);
ProxyCreatorSupport->createAopProxy():
    return getAopProxyFactory().createAopProxy(this);
DefaultAopProxyFactory->createAopProxy():
    // 如果目标类是接口或者是Proxy类及其子类的话,创建jdk动态代理,否则创建cglib代理
    // 通俗来说,就是,jdk动态代理只能创建接口的动态代理,而cglib可以创建普通类的动态代理
    if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
        return new JdkDynamicAopProxy(config);
    }
    return new ObjenesisCglibAopProxy(config);

下图是普通bean与cglib增强bean的构造区别: AoP部分与CglibAopProxy$DynamicAdvisedInterceptor有关,advisors以及advisorArray是满足切面表达式的Advisor实现类。

运行

AoP代理的主要逻辑是遍历advisorArray,获得方法满足的切面方法,然后调用advisor.getAdvice()获得Advice实现类,放入拦截器集合中,之后以类似责任链模式执行,详细代码见CglibAopProxy->DynamicAdvisedInterceptor->intercept()DefaultAdvisorChainFactory->getInterceptorsAndDynamicInterceptionAdvice()ReflectiveMethodInvocation->proceed()

这里需要获得方法满足的切面方法,是因为有的AoP只对满足表达式的方法生效,其他方法不生效,但是方法寄生于类上,所以该类会是一个增强类,当然,对类生效的一定对方法生效

小结:

  • aop的实现载体是动态代理,实例化完成之后,利用了IoC的后置处理器AnnotationAwareAspectJAutoProxyCreator,通过它的postProcessAfterInitialization()方法来判断bean实例是否需要被代理,若满足表达式,则返回代理bean,否则,返回原始bean实例
  • @Around/@Before/@After/@AfterReturning/@AfterThrowing这些注解决定的是方法的执行顺序
    • 一般方法的执行顺序为:doAround()->proceedingJoinPoint.proceed()->doBefore()->add()->doAfterReturning()->doAfter()->doAround()
    • 报异常时的执行顺序为:doAround()->proceedingJoinPoint.proceed()->doBefore()->add()->doAfterThrowing()->doAfter()
  • 对于Advisor类,看是否满足切面表达式的过程
    1. 调用advisor.getPointcut()
    2. 调用pointCut.getMethodMatcher()
    3. 根据methodMatcher的实现类调用不同的匹配方法,返回true则是满足
      • 如果methodMatcher是IntroductionAwareMethodMatcher实现类,那么调用introductionAwareMethodMatcher.matches(Method method, Class<?> targetClass, boolean hasIntroductions)
      • 否则调用methodMatcher.matches(Method method, Class<?> targetClass)
  • 根据增强类反推Advisor以及拦截器
    1. 如果一个增强类有成员变量CglibAopProxy$DynamicAdvisedInterceptor说明它有AoP代理
    2. 它有唯一的成员变量advised,advisor位于其advisors成员变量中,这是一个List集合
    3. advice是切面拦截器,运行时会执行它的invoke()方法;pointcut是切面类,可以根据它查看切面表达式;order是排序,越小越先执行