Spring AOP の自動設定とプロキシ生成メカニズム

Spring Boot では、AOP 機能を有効にするために AopAutoConfiguration という自動設定クラスが提供されている。このクラスは特定の条件が満たされた場合にのみ有効化され、AspectJ ベースの AOP を自動的に設定する。

@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class, AnnotatedElement.class })
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {

    @Configuration
    @EnableAspectJAutoProxy(proxyTargetClass = false)
    @ConditionalOnProperty(
        prefix = "spring.aop", 
        name = "proxy-target-class", 
        havingValue = "false", 
        matchIfMissing = false
    )
    public static class JdkDynamicAutoProxyConfiguration {
    }

    @Configuration
    @EnableAspectJAutoProxy(proxyTargetClass = true)
    @ConditionalOnProperty(
        prefix = "spring.aop", 
        name = "proxy-target-class", 
        havingValue = "true", 
        matchIfMissing = true
    )
    public static class CglibAutoProxyConfiguration {
    }
}

上記の設定により、spring.aop.proxy-target-class プロパティの値に応じて、JDK 動的プロキシまたは CGLIB プロキシが選択される。@EnableAspectJAutoProxy アノテーションは、内部で AspectJAutoProxyRegistrar をインポートし、AOP 用の Bean 定義を登録する。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
    boolean proxyTargetClass() default false;
    boolean exposeProxy() default false;
}

AspectJAutoProxyRegistrarImportBeanDefinitionRegistrar を実装しており、コンテナの初期化時に AnnotationAwareAspectJAutoProxyCreator を Bean として登録する。このクラスは BeanPostProcessor の一種であり、Bean の生成後に AOP プロキシの適用が必要かどうかを判断する。

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(
            AnnotationMetadata metadata, BeanDefinitionRegistry registry) {

        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

        AnnotationAttributes attrs = AnnotationConfigUtils.attributesFor(metadata, EnableAspectJAutoProxy.class);
        if (attrs != null) {
            if (attrs.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            if (attrs.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }
}

最終的に、AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary が呼び出され、AnnotationAwareAspectJAutoProxyCreator の登録または既存のプロキシクリエータの昇格処理が行われる。

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

タグ: Spring AOP AspectJ

6月7日 20:49 投稿