前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >spring aop (上中)获取Bean的增强

spring aop (上中)获取Bean的增强

作者头像
平凡的学生族
发布2019-06-03 08:47:21
1.4K0
发布2019-06-03 08:47:21
举报
文章被收录于专栏:后端技术后端技术

生成aop代理对象 生成aop拦截链调用

《Spring技术内幕》学习笔记8——创建AOP代理对象并对目标对象切面拦截

  • spring boot 源码解析20-spring boot aop自动化配置 @EnableAspectJAutoProxy被自动配置,并注册id为org.springframework.aop.config.internalAutoProxyCreator的Bean。如果Bean已存在则根据优先级替换。 这个Bean的class一般都是AnnotationAwareAspectJAutoProxyCreator(它会被AspectJAutoProxyRegistrar注册,而刚好又优先级最高,所以注册后也不会被取代)。 总而言之一句话,注册了个AnnotationAwareAspectJAutoProxyCreator的Bean,它是一个BeanPostProcessor。我们可以猜到,这个后置处理器会对Bean生成代理。
  • Spring AOP 注解方式源码解析虽然起点是从xml开始解析的,但最终也会生成AnnotationAwareAspectJAutoProxyCreator。我最后看的这篇。

AnnotationAwareAspectJAutoProxyCreator

postProcessAfterInitialization->wrapIfNecessary:

代码语言:javascript
复制
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    ...

    // 获取Bean的增强
    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;
    }

    ...
}

会对Bean获取增强,再创建代理。所以我们主要研究getAdvicesAndAdvisorsForBean和createProxy。本文先研究获取Bean的增强。

AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean

getAdvicesAndAdvisorsForBean->findEligibleAdvisors,其中

  • findCandidateAdvisors找到候选的Advisor
  • findAdvisorsThatCanApply筛选出能应用在该Bean上的Advisor
  • 对增强进行扩展和排序

找到候选Advisor

findCandidateAdvisors

getAdvisors: 为切面的每个通知方法,生成InstantiationModelAwarePointcutAdvisorImpl这个Advisor,其构造函数中,会调用getAdvice根据注解生成对应Advice:

代码语言:javascript
复制
@Override
@Nullable
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
        MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

    Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    validate(candidateAspectClass);

    AspectJAnnotation<?> aspectJAnnotation =
            AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
            
    ...

    AbstractAspectJAdvice springAdvice;

    switch (aspectJAnnotation.getAnnotationType()) {
        case 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);
    }

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

筛选出合适的Advisor

findAdvisorsThatCanApply->findAdvisorsThatCanApply(...)->AopUtils.findAdvisorsThatCanApply->canApply 会判断一个Advisor是否能用在该class上(即使只是用在个别方法上)。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.06.02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • AnnotationAwareAspectJAutoProxyCreator
  • AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean
  • 找到候选Advisor
  • 筛选出合适的Advisor
相关产品与服务
云顾问
云顾问(Tencent Cloud Smart Advisor)是一款提供可视化云架构IDE和多个ITOM领域垂直应用的云上治理平台,以“一个平台,多个应用”为产品理念,依托腾讯云海量运维专家经验,助您打造卓越架构,实现便捷、灵活的一站式云上治理。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档