SpringBoot源码简析EnableAspectJAutoProxy

导读:本篇文章讲解 SpringBoot源码简析EnableAspectJAutoProxy,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

相关阅读

简介

开启@Aspect注解驱动的自动代理的功能;

源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

    // 代理模式:CGLIB or JDK Interface
    // 默认为false,表示基于JDK Interface
    // 设置为true,会影响所有需要代理的Spring管理的Bean
    boolean proxyTargetClass() default false;

    // 表示代理是否暴露,以便通过AopContext可以获取到代理
    // 默认为false
    boolean exposeProxy() default false;
}

配置

配合@Configuration使用,表示开启@Aspect注解驱动的自动代理的功能;

@Configuration
@EnableAspectJAutoProxy
public class AppConfig {

    @Bean
    public FooService fooService() {
        return new FooService();
    }
 
    @Bean
    public MyAspect myAspect() {
        return new MyAspect();
    }
}

public class FooService {
    // various methods
}

@Aspect
public class MyAspect {
    @Before("execution(* FooService+.*(..))")
    public void advice() {
        // advise FooService methods as appropriate
    }
}

简析

通过Import机制 ,@EnableAspectJAutoProxy引入AspectJAutoProxyRegistrar.class,代码如下:

@Import(AspectJAutoProxyRegistrar.class)

AspectJAutoProxyRegistrar

AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar,用于向容器里注册自动代理创建器AbstractAutoProxyCreator,代码如下:

/**
 * importingClassMetadata : 通过Import引入该类的配置类的元数据信息,本例中配置类为CglibAutoProxyConfiguration
 * registry : Bean定义容器
 */
public void registerBeanDefinitions(
        AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

    // 向Bean定义容器注册AnnotationAwareAspectJAutoProxyCreator如果需要的话
    AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

    // 获取@EnableAspectJAutoProxy注解的属性数据
    AnnotationAttributes enableAspectJAutoProxy =
            AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
    if (enableAspectJAutoProxy != null) {
        // @EnableAspectJAutoProxy注解的属性数据存在,则解析配置
        if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
            // 如果proxyTargetClass属性值为true,则强制使用CGLIB代理
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }
        if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
            // 如果exposeProxy属性值为true,则强制暴露代理代理
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
        }
    }
}

核心逻辑为
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);,代码如下:

@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}

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

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

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

    // 判断当前容器中是否存在自动代理创建器的Bean定义
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        // 获取已存在的Bean定义
        BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        // 判断已存在的Bean定义的className和当前是否一致
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
            // 不一致则使用优先级更高的
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            int requiredPriority = findPriorityForClass(cls);
            if (currentPriority < requiredPriority) {
                apcDefinition.setBeanClassName(cls.getName());
            }
        }
        // 已存在,则不需要注册
        return null;
    }

    // 不存在,则需要注册

    // 根据当前class创建Bean定义并放入容器中
    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;
}

public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        // 添加Bean定义的proxyTargetClass属性
        definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
    }
}

public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        // 添加Bean定义的exposeProxy属性
        definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
    }
}

AnnotationAwareAspectJAutoProxyCreator

简介

自动代理创建器AbstractAutoProxyCreator是Spring AOP自动代理的核心,详见:Spring AOP基础组件 AbstractAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator属于AbstractAutoProxyCreator的继承层次,用于处理AspectJ注解定义的切面以及Spring的Advisor
如果配置文件中定义了<aop:include>元素,则仅那些名称于包含模式匹配的@AspectJ Bean才会被当作定义用于Spring自动代理的切面;

核心代码

public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {

    // 配置的模式,正则形式
    @Nullable
    private List<Pattern> includePatterns;


    // 设置模式
    public void setIncludePatterns(List<String> patterns) {
        this.includePatterns = new ArrayList<>(patterns.size());
        for (String patternText : patterns) {
            this.includePatterns.add(Pattern.compile(patternText));
        }
    }

    @Override
    protected List<Advisor> findCandidateAdvisors() {
        // Add all the Spring advisors found according to superclass rules.
        List<Advisor> advisors = super.findCandidateAdvisors();
        // Build Advisors for all AspectJ aspects in the bean factory.
        if (this.aspectJAdvisorsBuilder != null) {
            // 为所有AspectJ切面构建Advisor
            advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }
        return advisors;
    }

    @Override
    protected boolean isInfrastructureClass(Class<?> beanClass) {
        return (super.isInfrastructureClass(beanClass) ||
                // AspectJ切面类也认为是基础类型
                (this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
    }

    protected boolean isEligibleAspectBean(String beanName) {
        if (this.includePatterns == null) {
            // 未配置匹配模式,则认为都满足
            return true;
        }
        else {
            // 配置了匹配模式,则必须匹配上配置的模式才认为满足
            for (Pattern pattern : this.includePatterns) {
                if (pattern.matcher(beanName).matches()) {
                    return true;
                }
            }
            return false;
        }
    }


    // 将AspectJ切面转换为Advisor的适配器
    private class BeanFactoryAspectJAdvisorsBuilderAdapter extends BeanFactoryAspectJAdvisorsBuilder {

        public BeanFactoryAspectJAdvisorsBuilderAdapter(
                ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {

            super(beanFactory, advisorFactory);
        }

        @Override
        protected boolean isEligibleBean(String beanName) {
            return AnnotationAwareAspectJAutoProxyCreator.this.isEligibleAspectBean(beanName);
        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/4773.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!