ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

AOP底层

2022-01-23 18:01:41  阅读:126  来源: 互联网

标签:增强器 return Object 代理 bean AOP null 底层


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

标签:增强器,return,Object,代理,bean,AOP,null,底层
来源: https://blog.csdn.net/qq_20265015/article/details/122648869

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有