AOP底层

<aop:aspectj-autoproxy/>

在开启AOP时,bean.xml一定会开启这个标签,而Spring启动的时候,就需要将这个标签以及标签的解析器注册到Spring 容器中。

// 注册 <aspectj-autoproxy/> 标签及其解析器
this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());

AspectJAutoProxyBeanDefinitionParser 类是标签 <aop:aspectj-autoproxy /> 的解析器,该类实现了 BeanDefinitionParser 接口,并实现了 BeanDefinitionParser#parse 接口方法,属于标准的标签解析器定义。Spring 容器在启动时会调用 AspectJAutoProxyBeanDefinitionParser#parse 方法解析标签,实现如下:

public BeanDefinition parse(Element element, ParserContext parserContext) {
    // 注册标签解析器,默认使用 AnnotationAwareAspectJAutoProxyCreator
    AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
    // 解析 <aop:include /> 子标签,记录到 BeanDefinition 到 includePatterns 属性中
    this.extendBeanDefinition(element, parserContext);
    return null;
}

该方法做了两件事情:注册标签解析器和处理 <aop:include /> 子标签。

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {
    // 1. 注册或更新代理创建器 ProxyCreator 的 BeanDefinition 对象
    BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            parserContext.getRegistry(), parserContext.extractSource(sourceElement));
    // 2. 获取并处理标签的 proxy-target-class 和 expose-proxy 属性
    useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
    // 3. 注册组件,并发布事件通知
    registerComponentIfNecessary(beanDefinition, parserContext);
}

根据标签解析器创建ProxyCreator 代理创建器的BeanDefinition对象:

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

传入一个AOP的代理创建器的class对象,BeanDefinition注册器和标签

private static BeanDefinition registerOrEscalateApcAsRequired(
        Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

    // 如果名为 org.springframework.aop.config.internalAutoProxyCreator 的 bean 已经在册
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        // 已经在册的 ProxyCreator 与当前期望的类型不一致,则依据优先级进行选择
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            int requiredPriority = findPriorityForClass(cls);
            // 选择优先级高的 ProxyCreator 更新注册
            if (currentPriority < requiredPriority) {
                apcDefinition.setBeanClassName(cls.getName());
            }
        }
        return null;
    }

    // 没有对应在册的 ProxyCreator,注册一个新的
    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;
}

这里简述一下所述代码的逻辑:

  • 期望注册一个ProxyCreator的BeanDefinition,这个代理创建器的默认实现类是AnnotationAwareAspectJAutoProxyCreator,如果有存在了,就不创建,直接选择优先级最高的那个
  • 如果不存在这个代理创建器,就创建一个并注册到Registry里面。

创建完代理创建器后,就要解析标签了

useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); 这一行代码

主要是解析aop:aspectj-autoproxy/ 的 proxy-target-class 和 expose-proxy 属性配置,这两个操作都是给之前那个ProxyCreator添加一些属性,后面才用到

  • proxy-target-class 是判断用jdk动态代理还是CGLIB代理
    • false 表示使用 java 原生动态代理
    • true 表示使用 CGLib 动态
  • expose-proxy 代表要不要对内部方法实现增强
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
    if (sourceElement != null) {
        /*
         * 获取并处理 proxy-target-class 属性:
         * - false 表示使用 java 原生动态代理
         * - true 表示使用 CGLib 动态
         *
         * 但是对于一些没有接口实现的类来说,即使设置为 false 也会使用 CGlib 进行代理
         */
        boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
        if (proxyTargetClass) {
            // 为之前注册的 ProxyCreator 添加一个名为 proxyTargetClass 的属性,值为 true
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }

        /*
         * 获取并处理 expose-proxy 标签,实现对于内部方法调用的 AOP 增强
         */
        boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
        if (exposeProxy) {
            // 为之前注册的 ProxyCreator 添加一个名为 exposeProxy 的属性,值为 true
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
        }
    }
}

ProxyCreator好像很重要,决定了什么代理,怎么增强,他其实是是实现了BeanPostProcessor 后置处理器,然后它实现了postProcessAfterInitialization方法

public interface BeanPostProcessor {

    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

}

然后下一个是具体的实现

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        // 如果 beanName 不为空则直接使用 beanName(FactoryBean 则使用 &{beanName}),否则使用 bean 的 className
        Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            // 尝试对 bean 进行增强,创建返回增强后的代理对象
            return this.wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

该方法的核心在于调用 AbstractAutoProxyCreator#wrapIfNecessary 方法尝试基于 AOP 配置对当前 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;
    }
    // 对于 AOP 的基础支撑类,或者指定不需要被代理的类,设置为不进行代理
    if (this.isInfrastructureClass(bean.getClass()) || this.shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // 获取适用于当前 bean 的 Advisor
    Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    // 基于获取到的 Advisor 为当前 bean 创建代理对象
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        Object proxy = this.createProxy(
                bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

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

简述一下上面的流程:如果在增强的时候这个bean已经增强过或者不需要增强(this.advisedBeans.get(cacheKey) == false),则直接返回.
否则就选择合适的增强器进行增强,然后返回一个代理对象。

选择合适的增强器过程如下:

protected Object[] getAdvicesAndAdvisorsForBean(
        Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
    // 获取适用于当前 bean 的 Advisor
    List<Advisor> advisors = this.findEligibleAdvisors(beanClass, beanName);
    // 没有合格的 Advisor,不进行代理
    if (advisors.isEmpty()) {
        return DO_NOT_PROXY; // null
    }
    return advisors.toArray();
}

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 获取所有候选的 Advisor(包括注解的、XML 中配置的)
    List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
    // 从所有 Advisor 中寻找适用于当前 bean 的 Advisor
    List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    // 如果 Advisor 不为空,则在最前面追加一个 ExposeInvocationInterceptor
    this.extendAdvisors(eligibleAdvisors);
    // 对 Advisor 进行排序
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

简述一下上面的流程:先获取程序中的所有增强器,如果有,找到所有匹配当前bean的增强器,如果找到了,就将这些增强器排序。(是按照 before 之类来排序吗)

protected List<Advisor> findCandidateAdvisors() {
    // 调用父类的 findCandidateAdvisors 方法,兼容父类查找 Advisor 的规则
    List<Advisor> advisors = super.findCandidateAdvisors();
    // 获取所有注解定义的 Advisor
    if (this.aspectJAdvisorsBuilder != null) {
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }
    return advisors;
}

方法首先调用了父类的实现,这主要是为了兼容父类查找候选增强器的规则,例如我们的示例中使用的是注解方式定义的增强,但是父类却是基于 XML 配置的方式查找增强器,这里的兼容能够让我们在以注解方式编程时兼容其它以 XML 配置的方式定义的增强。
具体的获取增强器的流程:

  • 获取容器中所有的beanName 集合
  • 过滤出切面(@Aspect、以ajc$ 开头的字段等)
  • 每一个切面的切点生成对应的增强器并缓存,避免重复
    具体看一下如何获取切点以生成增强器:
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
    // 获取切面 aspect 对应的 class 和 beanName
    Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
    // 校验切面定义的合法性
    this.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<>();

    // 1. 遍历处理切面中除被 @Pointcut 注解以外的方法
    for (Method method : this.getAdvisorMethods(aspectClass)) {
        Advisor advisor = this.getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }

    // 2. 如果增强器不为空,同时又配置了增强延迟初始化,则需要追加实例化增强器 SyntheticInstantiationAdvisor
    if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
        Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
        advisors.add(0, instantiationAdvisor);
    }

    // 3. 获取所有引介增强定义
    for (Field field : aspectClass.getDeclaredFields()) {
        // 创建引介增强器 DeclareParentsAdvisor
        Advisor advisor = this.getDeclareParentsAdvisor(field);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }

    return advisors;
}

描述上述方法的过程:

  • 获取切面的class和beanName’
  • 校验
  • 遍历@Around、@Before、@After、@AfterReturning,以及 @AfterThrowing 注解的方法
  • 调用 getAdvisor 方法生成增强器

具体的getAdisor方法如下:

public Advisor getAdvisor(Method candidateAdviceMethod,
                          MetadataAwareAspectInstanceFactory aspectInstanceFactory,
                          int declarationOrderInAspect,
                          String aspectName) {

    // 校验切面类定义的合法性
    this.validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

    // 获取注解配置的切点信息,封装成 AspectJExpressionPointcut 对象
    AspectJExpressionPointcut expressionPointcut = this.getPointcut(
            candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
    if (expressionPointcut == null) {
        return null;
    }

    // 依据切点信息生成对应的增强器
    return new InstantiationModelAwarePointcutAdvisorImpl(
            expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

描述getAdvisor方法如下:

  • 校验(切面类的class对象)
  • 获取注解配置的切点信息,封装成 Pointcut 对象
  • 把PointCut、方法等属性封装成一个切点增强器对象 --》 InstantiationModelAwarePointcutAdvisorImpl()对象
    这个切点增强器对象调用了一个增强器实例化方法,也就生成增强(先生成增强器,再生成增强):
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) {

    // 获取切面 class 对象,并校验切面定义
    Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    this.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 (!this.isAspect(candidateAspectClass)) {
        throw new AopConfigException("Advice must be declared inside an aspect type: " +
                "Offending method '" + candidateAdviceMethod + "' in class [" + candidateAspectClass.getName() + "]");
    }

    AbstractAspectJAdvice springAdvice;

    // 依据切点注解类型使用对应的增强类进行封装
    switch (aspectJAnnotation.getAnnotationType()) {
        // @Pointcut
        case AtPointcut:
            if (logger.isDebugEnabled()) {
                logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
            }
            return null;
        // @Around
        case AtAround:
            springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        // @Before
        case AtBefore:
            springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        // @After
        case AtAfter:
            springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        // @AfterReturning
        case AtAfterReturning:
            springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
            if (StringUtils.hasText(afterReturningAnnotation.returning())) {
                springAdvice.setReturningName(afterReturningAnnotation.returning());
            }
            break;
        // @AfterThrowing
        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;
}

生成增强方法的过程主要为:

  • 校验class
  • 获取切点方法上的注解
  • 对于每个注解,依据注解类型(@PointCut除外)进行增强类的封装。
  • @AfterReturning 和 @AfterThrowing 特殊一点,因为他们还需要接收一个返回结果或者异常结果()
@AfterReturning(value = "execution(* com.springaop.aop01.Service.Impl.IUserServceImpl.*(..))",returning = "result")


AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
            if (StringUtils.hasText(afterReturningAnnotation.returning())) {
                springAdvice.setReturningName(afterReturningAnnotation.returning());
                
@AfterThrowing(value = "execution(* com.springaop.aop01.Service.Impl.IUserServceImpl.*(..))",throwing = "exception")
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
            if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
                springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
            }

在真正调用的时候:会触发一个invoke方法

public Object invoke(MethodInvocation mi) throws Throwable {
    // 执行增强方法
    this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
    // 执行目标方法
    return mi.proceed();
}

先调用增强方法,再调用目标方法

以上是普通的增强方法的调用,接下来是引介增强方法

使用专门的 DeclareParentsAdvisor 类创建对应的增强器

private Advisor getDeclareParentsAdvisor(Field introductionField) {
    // 获取 @DeclareParents 注解定义
    DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
    if (declareParents == null) {
        return null;
    }

    // 没有指定默认的接口实现类
    if (DeclareParents.class == declareParents.defaultImpl()) {
        throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents");
    }

    // 使用 DeclareParentsAdvisor 类型创建对应的引介增强器
    return new DeclareParentsAdvisor(
            introductionField.getType(), declareParents.value(), declareParents.defaultImpl());
}

找到bean中的所有增强器后,需要为当前的bean匹配合适的增强器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<>();

    // 1. 筛选引介增强器
    for (Advisor candidate : candidateAdvisors) {
        if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
            eligibleAdvisors.add(candidate);
        }
    }
    // 表示是否含有引介增强
    boolean hasIntroductions = !eligibleAdvisors.isEmpty();

    // 2. 筛选其它类型的增强器
    for (Advisor candidate : candidateAdvisors) {
        // 引介增强已经处理过,这里直接跳过
        if (candidate instanceof IntroductionAdvisor) {
            // already processed
            continue;
        }
        // 筛选其它类型的增强器
        if (canApply(candidate, clazz, hasIntroductions)) {
            eligibleAdvisors.add(candidate);
        }
    }
    return eligibleAdvisors;
}

方法首先会使用类过滤器(ClassFilter)筛选引介增强器,然后,方法会过滤筛选其它类型的增强器,如果没有任何一个增强器适用于当前 bean 类型,则方法最终会返回值为 null 的 DO_NOT_PROXY 数组对象,表示当前 bean 不需要被增强。这里增强器已经筛选完毕了,那么就要创建增强代理对象了

Object proxy = this.createProxy(
                bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
protected Object createProxy(Class<?> beanClass,
                             @Nullable String beanName,
                             @Nullable Object[] specificInterceptors,
                             TargetSource targetSource) {

    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }

    // ProxyFactory 用于为目标 bean 实例创建代理对象
    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);

    // proxy-target-class = false,表示使用 JDK 原生动态代理
    if (!proxyFactory.isProxyTargetClass()) {
        // 检测当前 bean 是否应该基于类而非接口生成代理对象,即包含 preserveTargetClass=true 属性
        if (this.shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        // 如果是基于接口生成代理,则添加需要代理的接口到 ProxyFactory 中(除内置 callback 接口、语言内在接口,以及标记接口)
        else {
            this.evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    // 将拦截器封装成 Advisor 对象
    Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
    proxyFactory.addAdvisors(advisors);
    proxyFactory.setTargetSource(targetSource);
    // 模板方法,定制代理工厂
    this.customizeProxyFactory(proxyFactory);

    // 设置代理工厂被配置之后是否还允许修改,默认为 false,表示不允许修改
    proxyFactory.setFrozen(this.freezeProxy);
    if (this.advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }

    // 基于 ProxyFactory 创建代理类
    return proxyFactory.getProxy(this.getProxyClassLoader());
}

具体流程如下:

  • 新建一个代理工厂ProxyFactory,
  • 判断是否要用jdk来代理还是CGLib来代理
  • 将拦截器封装成Advisor对象
  • 创建代理对象

拦截器封装成代理对象如下:

public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
    // 已经是 Advisor,则无需多做处理
    if (adviceObject instanceof Advisor) {
        return (Advisor) adviceObject;
    }
    // 要求必须是 Advice 类型
    if (!(adviceObject instanceof Advice)) {
        throw new UnknownAdviceTypeException(adviceObject);
    }
    Advice advice = (Advice) adviceObject;
    // 如果是 MethodInterceptor,则直接使用 DefaultPointcutAdvisor 进行包装
    if (advice instanceof MethodInterceptor) {
        // So well-known it doesn't even need an adapter.
        return new DefaultPointcutAdvisor(advice);
    }
    // 否则遍历注册的适配器,如果存在关联的适配器则使用 DefaultPointcutAdvisor 进行包装
    for (AdvisorAdapter adapter : this.adapters) {
        // Check that it is supported.
        if (adapter.supportsAdvice(advice)) {
            return new DefaultPointcutAdvisor(advice);
        }
    }
    throw new UnknownAdviceTypeException(advice);
}

重点分析一下通过代理工厂 ProxyFactory 创建增强代理对象的过程

public Object getProxy(@Nullable ClassLoader classLoader) {
    return this.createAopProxy() // 1. 创建 AOP 代理
            .getProxy(classLoader); // 2. 基于 AOP 代理创建目标类的增强代理对象
}

该方法的执行过程可以拆分成两个步骤:

  1. 创建 AOP 代理,Spring 默认提供了两种 AOP 代理实现,即 java 原生代理和 CGLib 代理;
  2. 基于 AOP 代理创建目标类的增强代理对象。

如果目标类实现了接口,则 Spring 默认会使用 java 原生代理。
如果目标类未实现接口,则 Spring 会使用 CGLib 生成代理。
如果目标类实现了接口,但是在配置时指定了 proxy-target-class=true,则使用 CGLib 生成代理。

创建完代理后,就要增强代理对象
首先来看一下jdk代理对象的增强。Java 原生代理要求代理类实现 InvocationHandler 接口,并在 InvocationHandler#invoke 方法中实现代理增强逻辑。

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 {
        // 当前是 equals 方法,但是被代理类接口中未定义 equals 方法
        if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
            return this.equals(args[0]);
        }
        // 当前是 hashCode 方法,但是被代理类接口中未定义 hashCode 方法
        else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
            return this.hashCode();
        }
        // 如果是 DecoratingProxy 中定义的方法(即 DecoratingProxy#getDecoratedClass),直接返回目标类对象
        else if (method.getDeclaringClass() == DecoratingProxy.class) {
            return AopProxyUtils.ultimateTargetClass(this.advised);
        } else if (!this.advised.opaque // 允许被转换成 Advised 类型
                && method.getDeclaringClass().isInterface() // 接口类型
                && method.getDeclaringClass().isAssignableFrom(Advised.class)) // 方法所在类是 Advised 类及其父类
        {
            // 直接反射调用该方法
            return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
        }

        // 结果值
        Object retVal;

        // 指定内部间调用也需要代理
        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);

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

        // Check whether we have any advice. If we don't, we can fallback on direct
        // reflective invocation of the target, and avoid creating a MethodInvocation.
        // 拦截器链为空,则直接反射调用增强方法
        if (chain.isEmpty()) {
            // 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 = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
        }
        // 否则需要创建对应的 MethodInvocation,以链式调用拦截器方法和增强方法
        else {
            MethodInvocation invocation =
                    new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            // Proceed to the joinpoint through the interceptor chain.
            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);
        }
    }
}

流程描述:

  • 特殊处理 Object#equals、Object#hashCode、DecoratingProxy#getDecoratedClass,以及
    Advised 类及其父类中定义的方法;

  • 如果配置了 expose-proxy 属性,则记录当前代理对象,以备在内部间调用时实施增强;

  • 获取当前方法的拦截器链;

  • 如果没有拦截器定义,则直接反射调用增强方法,否则先逐一执行拦截器方法,最后再应用增强方法;

  • 处理返回值。

重点来看一下步骤 4 中应用拦截器方法的实现

public Object proceed() throws Throwable {
    // 如果所有的增强都执行完成,则执行增强方法
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        return this.invokeJoinpoint();
    }

    // 获取下一个需要执行的拦截器
    Object interceptorOrInterceptionAdvice =
            this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    // 动态拦截器,执行动态方法匹配
    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 {
            return this.proceed();
        }
    }
    // 静态拦截器,直接应用拦截方法
    else {
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}
上一篇:Spring


下一篇:Spring5学习-2