SpringAOPアノテーションメソッドのソースコード分析

SpringAOPアノテーションメソッドのソースコード分析

TSMYKJavaテクノロジープログラミング

序文

前回の記事「SpringAOP関数の使い方の詳細な説明」では、Sprig AOPの使い方の詳細を学びました。それでは、Springでどのように実装されているかを見てみましょう。

アスペクトj-自動プロキシ

Spring AOPを使用する場合は、最初に構成アイテム<aop:aspectj-autoproxy Exposure-proxy = "true" proxy-target-class = "true" />を構成ファイルに追加する必要があることを認識しています。属性はオプションです。Springの各タグには、解析用の対応するパーサーがあり、aspectj-autoproxyタグの場合、以下に示すように、AspectJAutoProxyBeanDefinitionParserパーサーが解析に使用されます。


public class AopNamespaceHandler extends NamespaceHandlerSupport {
    @Override
    public void init() {
        registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
        // 注册 aspectj-autoproxy 标签的解析器
        registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
        registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    }
}

AspectJAutoProxyBeanDefinitionParserには2つの主要な関数があります。1つはAnnotationAwareAspectJAutoProxyCreatorBeanを登録することで、もう1つは<aop:aspectj-autoproxy />の2つの属性を解析することです。これらの中で、AOPの関数は基本的にAnnotationAwareAspectJAutoProxyCreatorによって実行されます。

AnnotationAwareAspectJAutoProxyCreatorを登録します

すべてのパーサーはインターフェースBeanDefinitionParserを実装し、エントリはparseメソッドから解析されます。AspectJAutoProxyBeanDefinitionParserのparseメソッドは次のとおりです。


class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        // 注册AnnotationAwareAspectJAutoProxyCreator bean 和处理标签的两个属性
        AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
        // 处理子标签
        extendBeanDefinition(element, parserContext);
        return null;
    }
}

AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessaryメソッドは次のとおりです。


public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {
    // 注册 AnnotationAwareAspectJAutoProxyCreator
    BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            parserContext.getRegistry(), parserContext.extractSource(sourceElement));
    // 解析标签的两个属性expose-proxy 和 proxy-target-class
    useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
    // 注册组件并通知,便于监听器进一步处理,这里可以不用看
    registerComponentIfNecessary(beanDefinition, parserContext);
}

この方法では、主に3つの関数が完了し、コードの各行が1つの関数を完了します。

  1. AnnotationAwareAspectJAutoProxyCreatorを登録します
  2. export-proxy属性とproxy-target-class属性の処理
  3. コンポーネントを登録して通知する

    AnnotationAwareAspectJAutoProxyCreatorを登録します


public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
// 注册
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
    //如果已经注册且与现在的不一致,则需要根据优先级来判断到底需要使用哪一个
    //AUTO_PROXY_CREATOR_BEAN_NAME=org.springframework.aop.config.internalAutoProxyCreator
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        // 如果缓存中和现在注册的class不一样
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            int requiredPriority = findPriorityForClass(cls);
            // 判断优先级,如果现在的优先级比缓存中的大,则取现在的这个
            if (currentPriority < requiredPriority) {
                apcDefinition.setBeanClassName(cls.getName());
            }
        }
        //如果相同,则无需再创建
        return null;
    }
    // 如果还没有注册,则进行注册
    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;
}

export-proxy属性とproxy-target-class属性の処理


处理 expose-proxy 和 proxy-target-class 属性

private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry,Element sourceElement) {
    if (sourceElement != null) {
        // 获取proxy-target-class的值
        boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
        if (proxyTargetClass) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }
        // 获取 expose-proxy的值
        boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
        if (exposeProxy) {
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
        }
    }
}
//设置属性 proxyTargetClass 为true
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
    }
}
//设置属性 exposeProxy为true
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
    }
}

この時点で、AnnotationAwareAspectJAutoProxyCreatorの登録が完了します。前述のように、AOPの機能は基本的にAnnotationAwareAspectJAutoProxyCreatorによって完了します。次に、このクラスがAOP操作を完了する方法を見てみましょう。

解析Advce

次のように、AnnotationAwareAspectJAutoProxyCreatorのクラス図を見てみましょう。

SpringAOPアノテーションメソッドのソースコード分析
上記のクラス図からわかるように、AnnotationAwareAspectJAutoProxyCreatorはBeanPostProcessorを実装し、このインターフェイスのBeanはSpringに実装されます。SpringがBeanをロードすると、初期化の前にpostProcessAfterInitializatioメソッドを呼び出します。親クラスAbstractAutoProxyCreatorのpostProcessAfterInitializationメソッドが実装されます。次のように:


public Object postProcessAfterInitialization(Object bean, String beanName) {
    if (bean != null) {
        // 根据beanClass 和 beanName 创建缓存的 key
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            // 如果该bean适合被代理,则必须包装
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}
// 包装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;
    }
    //如果bean是Advice.class, Pointcut.class, Advisor.class, AopInfrastructureBean.class, 则直接返回
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        // 添加该bean不需要增强的标志到缓存中
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // 获取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;
    }
    // 不需要增强,直接返回
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

上記のコードから、AnnotationAwareAspectJAutoProxyCreatorをインスタンス化する前にAOP拡張が分析されることがわかります。分析が拡張された後、拡張プロキシが作成されます。この記事では、最初に拡張取得について説明し、プロキシの作成は次のようになります。次の記事で行われる説明。

強化される

getAdvicesAndAdvisorsForBean()メソッドについて、Beanの対応するクラスとbeanNameに従ってすべての拡張機能を取得します。


protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
    // 找出所有符合条件的增强
    List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
    if (advisors.isEmpty()) {
        return DO_NOT_PROXY;
    }
    return advisors.toArray();
}

findEligibleAdvisors()lig:


protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 获取所有增强
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 获取所有增强中适用于 bean 的增强并应用
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    // 对增强进行扩展和排序
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

すべての拡張機能を取得するメソッドfindCandidateAdvisors()多くの複雑な論理的判断の後、AOPで拡張された取得とポイントカット式の分析はすべてこのメソッド内に実装されます。


protected List<Advisor> findCandidateAdvisors() {
    // 调用父类方法加载配置文件中的AOP声明
    List<Advisor> advisors = super.findCandidateAdvisors();
    // 创建所有AspectJ增强
    if (this.aspectJAdvisorsBuilder != null) {
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }
    return advisors;
}
//父类 findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {
    return this.advisorRetrievalHelper.findAdvisorBeans();
}
// 寻找所有符合增强的bean,this.advisorRetrievalHelper.findAdvisorBeans
public List<Advisor> findAdvisorBeans() {
    String[] advisorNames = this.cachedAdvisorBeanNames;
    if (advisorNames == null) {
        // 寻找Advisor注解的beanName
        advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);
        this.cachedAdvisorBeanNames = advisorNames;
    }
    List<Advisor> advisors = new ArrayList<>();
    for (String name : advisorNames) {
        // 该bean符合增强
        if (isEligibleBean(name)) {
            if (this.beanFactory.isCurrentlyInCreation(name)) {
                // 该bean正创建,则忽略
            }
            else {
                advisors.add(this.beanFactory.getBean(name, Advisor.class));
            }
        }
    }
    return advisors;
}

メソッドthis.aspectJAdvisorsBuilder.buildAspectJAdvisors()に対応するBeanのアノテーション拡張を取得し、すべてのAspectJアノテーション付きBeanを検索します。各拡張メソッドについて、対応するアドバイザ、つまりアドバイザのメソッドが作成されます。


// 查找所有 AspectJ 注解的bean,对于每一个增强方法,都会创建对应的Advisor,即一个方法对于一个Advisor
public List<Advisor> buildAspectJAdvisors() {
    List<String> aspectNames = this.aspectBeanNames;
    // .... 省略一些null判断
    List<Advisor> advisors = new ArrayList<>();
    aspectNames = new ArrayList<>();
    // 获取所有的 beanName
    String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
    for (String beanName : beanNames) {
        // 如果该 bean不符合条件,则跳过
        if (!isEligibleBean(beanName)) {
            continue;
        }
        Class<?> beanType = this.beanFactory.getType(beanName);
        // 如果该 bean 存在 Aspect 注解
        if (this.advisorFactory.isAspect(beanType)) {
            aspectNames.add(beanName);
            // 根据beanType和beanName创建AspectMetadata ,表示增强的元数据
            AspectMetadata amd = new AspectMetadata(beanType, beanName);
            if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                // 解析标记了 AspectJ 注解中的增强方法
                List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                if (this.beanFactory.isSingleton(beanName)) {
                    // 如果该 bean是单例,则直接把解析到增强方法放到缓存中
                    this.advisorsCache.put(beanName, classAdvisors);
                }else {
                    //否则把对于的工厂放到缓存中
                    this.aspectFactoryCache.put(beanName, factory);
                }
                advisors.addAll(classAdvisors);
             }else {
                tadataAwareAspectInstanceFactory factory =new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                this.aspectFactoryCache.put(beanName, factory);
                advisors.addAll(this.advisorFactory.getAdvisors(factory));
            }
            this.aspectBeanNames = aspectNames;
            return advisors;
            }
        }
    }
    if (aspectNames.isEmpty()) {
        return Collections.emptyList();
    }
    // 记录缓存
    List<Advisor> advisors = new ArrayList<>();
    for (String aspectName : aspectNames) {
        List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
        if (cachedAdvisors != null) {
            advisors.addAll(cachedAdvisors);
        }
        else {
            MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
            advisors.addAll(this.advisorFactory.getAdvisors(factory));
        }
    }
    return advisors;
}

上記のメソッドはAdvisorの抽出を完了し、エンハンサーの取得は次のようにadvisorFactory.getAdvisors()メソッドに渡されます。


public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
    //获取标记为 AspectJ 的类
    Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    // 获取name
    String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
    //验证aspectClass 
    validate(aspectClass);

    //AOP 可以将增强延迟初始化,这里使用装饰器对工厂将包装
    MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

    List<Advisor> advisors = new ArrayList<>();
    // 处理每个增强方法,getAdvisorMethods 返回该增强类的所有增强方法
    for (Method method : getAdvisorMethods(aspectClass)) {
        // 每个方法对应一个 advisor
        Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }

    // 如果寻找的增强器不为空且配置了增强延迟初始化,那么需要在首位添加同步实例化增强器
    if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
        Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
        advisors.add(0, instantiationAdvisor);
    }

    // 获取 DeclareParents 注解
    for (Field field : aspectClass.getDeclaredFields()) {
        Advisor advisor = getDeclareParentsAdvisor(field);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }
    return advisors;
}

//获取增强类的所有增强方法 getAdvisorMethods 
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
    final List<Method> methods = new ArrayList<>();
    ReflectionUtils.doWithMethods(aspectClass, method -> {
        // 排除掉 Pointcut 方法
        if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
            methods.add(method);
        }
    });
    methods.sort(METHOD_COMPARATOR);
    return methods;
}

通常のエンハンサーの入手

通常のエンハンサーは、次のように、ポイントカット注釈の取得と注釈情報生成の拡張を含むgetAdvisor()メソッドを介して取得されます。


public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) {
    // 切点信息的获取,如@After, @Before
    AspectJExpressionPointcut expressionPointcut = getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
    // 根据切点信息,生成不同的增强器
    return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

カットポイント情報を取得するgetPonitcut:


private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
    // 获取方法上的注解
    AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    // 使用 AspectJExpressionPointcut 封装切点信息
    AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
    // 设置切点表达式如:execution(* *Service*(..))
    ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
    if (this.beanFactory != null) {
        ajexp.setBeanFactory(this.beanFactory);
    }
    return ajexp;
}

// 获取方法上的注解 findAspectJAnnotationOnMethod
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
    // ASPECTJ_ANNOTATION_CLASSES 是一个数组:{Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class}
    for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
        AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
        if (foundAnnotation != null) {
            return foundAnnotation;
        }
    }
    return null;
}
// 获取注解
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
    A result = AnnotationUtils.findAnnotation(method, toLookFor);
    if (result != null) {
        return new AspectJAnnotation<>(result);
    }
    else {
        return null;
    }
}

上記のメソッドは、特定のポイントカット情報を取得した後、ポイントカット情報に従って対応するエンハンサーを生成します。@ After、@ Beforeなどの各ポイントカット情報は、次のようにInstantiationModelAwarePointcutAdvisorImplオブジェクトに対応します。


new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName)

オブジェクトをインスタンス化するプロセスには、いくつかの割り当てプロセスがあります。さらに、@ After、@ Beforeなどのさまざまなエンハンサータイプに応じて、以下に示すように、さまざまなエンハンサーを作成する必要があります。


public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
        Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
        MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
    // .... 一些属性的赋值操作
    // A singleton aspect.
    this.pointcut = this.declaredPointcut;
    this.lazy = false;
    this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);

}

instanceiateAdviceメソッドは次のとおりです。これにより、さまざまな拡張アノテーションに基づいてさまざまなエンハンサーが作成されます。


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) {
    // 获取 Aspect 注解对应的class
    Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    validate(candidateAspectClass);
    // 再次获取Aspect注解类的所有增强方法来进行判断
    AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    if (aspectJAnnotation == null) {
        return null;
    }
    // 最终的增强器
    AbstractAspectJAdvice springAdvice;
    // 根据注解类型创建不同的增强器
    switch (aspectJAnnotation.getAnnotationType()) {
        // Pointcut注解 不处理
        case AtPointcut:
            return null;
        case AtAround:
            // around 注解,对应AspectJAroundAdvice增强器
            springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        case AtBefore:
            // Before注解,对应AspectJMethodBeforeAdvice增强器
            springAdvice = new AspectJMethodBeforeAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        case AtAfter:
           // After注解,对应AspectJAfterAdvice增强器
            springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        case AtAfterReturning:
             // AfterReturning注解,对应AfterReturning增强器
            springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
            // 设置返回值
            if (StringUtils.hasText(afterReturningAnnotation.returning())) {
                springAdvice.setReturningName(afterReturningAnnotation.returning());
            }
            break;
        case AtAfterThrowing:
            // AtAfterThrowing注解,对应AspectJAfterThrowingAdvice增强器
            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);
    }

    // 对获取到增强器进行一些配置
    springAdvice.setAspectName(aspectName);
    springAdvice.setDeclarationOrder(declarationOrder);
    String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
    if (argNames != null) {
        springAdvice.setArgumentNamesFromStringArray(argNames);
    }
    springAdvice.calculateArgumentBindings();

    return springAdvice;
}

次に、エンハンサーの実装を見てください。

@Beforeアノテーションに対応するエンハンサーAspectJMethodBeforeAdvice:


springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);

public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {

    public AspectJMethodBeforeAdvice(Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
        super(aspectJBeforeAdviceMethod, pointcut, aif);
    } 
    // before 方法
    @Override
    public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
        invokeAdviceMethod(getJoinPointMatch(), null, null);
    }
    // .......
}
// invokeAdviceMethod 方法
protected Object invokeAdviceMethod(JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex){
        return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
}
// invokeAdviceMethodWithGivenArgs 方法:
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
    Object[] actualArgs = args;
    if (this.aspectJAdviceMethod.getParameterCount() == 0) {
        actualArgs = null;
    }
    ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
    // 激活增强方法
    return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);

}

上記のさまざまなタイプのエンハンサーはすべてAbstractAspectJAdviceのサブクラスであり、最終的にはこのクラスのinvokeAdviceMethodメソッドのエンハンサーメソッドを非アクティブ化します。

上記のメソッドロジックはすべてのエンハンサーの分析を完了しましたが、すべてのエンハンサーについて、必ずしも現在のBeanに適用できるとは限らないため、適切なエンハンサーを選択する必要があります。

これは、上記のfindEligibleAdvisorsメソッドの2番目のステップであるfindAdvisorsThatCanApplyメソッドです。


protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 获取所有增强
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 获取所有增强中适用于 bean 的增强并应用
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    // 对增强进行扩展和排序
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

findAdvisorsThatCanApply方法:


protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

    ProxyCreationContext.setCurrentProxiedBeanName(beanName);
    try {
        // 过滤已经得到的 advisors
        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<>();
    for (Advisor candidate : candidateAdvisors) {
        // 首先处理引介增强
        if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
            eligibleAdvisors.add(candidate);
        }
    }
    boolean hasIntroductions = !eligibleAdvisors.isEmpty();
    for (Advisor candidate : candidateAdvisors) {
        if (candidate instanceof IntroductionAdvisor) {
            // 上面已经处理过了
            continue;
        }
        if (canApply(candidate, clazz, hasIntroductions)) {
            eligibleAdvisors.add(candidate);
        }
    }
    return eligibleAdvisors;
}

findAdvisorsThatCanApplyの主な機能は、beanClassとメソッドの拡張機能に基づいて、拡張機能が現在のBeanに適用可能かどうかを判断することです。対応するメソッドは、次のようにcanAppley()です。


public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
    // 引介增强处理
    if (advisor instanceof IntroductionAdvisor) {
        return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
    }else if (advisor instanceof PointcutAdvisor) {
        // 一般增强处理
        PointcutAdvisor pca = (PointcutAdvisor) advisor;
        return canApply(pca.getPointcut(), targetClass, hasIntroductions);
    }else {
        return true;
    }
}

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
    // 不匹配,直接返回
    if (!pc.getClassFilter().matches(targetClass)) {
        return false;
    }
    MethodMatcher methodMatcher = pc.getMethodMatcher();
    if (methodMatcher == MethodMatcher.TRUE) {
        return true;
    }

    IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
    if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
        introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
    }

    Set<Class<?>> classes = new LinkedHashSet<>();
    if (!Proxy.isProxyClass(targetClass)) {
        classes.add(ClassUtils.getUserClass(targetClass));
    }
    classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
    // 判断方法是否匹配
    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;
            }
        }
    }
    return false;
}

上記は、Spring AOPの拡張分析です。これには、Aspectアノテーションクラスの分析と、このクラスのすべての拡張メソッドの分析が含まれます。

総括する

Spring AOP関数では、対応する分析クラスがBeanPostProcessorインターフェースを実装します。これにより、Beanの初期化前にBeanでいくつかの操作を実行できます。注釈付きAOPの場合、AnnotationAwareAspectJAutoProxyCreator Beanをインスタンス化する前に、アスペクト注釈付きクラスを解決します。このクラスの拡張メソッドでは、各拡張メソッドがアドバイザに対応します。拡張メソッドを分析してアドバイザを取得すると、メソッドのさまざまなアノテーションタイプに応じてさまざまなエンハンサーが作成されます。

上記は主にBeanに対応するエンハンサーの入手方法を紹介しています。SpringAOPは動的プロキシを介して実装されていることがわかっています。エンハンサーを入手した後、対応するプロキシを作成できます。プロキシの作成については、次の記事で紹介します。

おすすめ

転載: blog.51cto.com/15077536/2608535