经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring Boot » 查看文章
SpringBoot中神奇的@Enable*注解?
来源:cnblogs  作者:java_lover  时间:2019/10/24 10:11:59  对本文有异议

在SpringBoot开发过程,我们经常会遇到@Enable开始的好多注解,比如@EnableEurekaServer、@EnableAsync、@EnableScheduling等,今天我们就来分析下这些注解到底是如何工作的?

一、@Enable*实现的原理

通过这些@Enable*注解的源码可以看出,所有@Enable*注解里面都有一个@Import注解,而@Import是用来导入配置类的,所以@Enable*自动开启的实现原理其实就是导入了一些自动配置的Bean。

二、@Import注解的用法

@Import注解允许导入@Configuration类,ImportSelector和ImportBeanDefinitionRegistrar的实现类,等同于正常的组件类。

有以下三种使用方式

1. 直接导入配置类

@EnableEurekaServer使用了这种方式,注解源码如下:

  1. @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import({EurekaServerMarkerConfiguration.class})
    public @interface EnableEurekaServer {
    }

可以看到@EnableEurekaServer注解直接导入了配置类EurekaServerMarkerConfiguration,而这个配置类中向spring容器中注册了一个EurekaServerMarkerConfiguration的Bean。

EurekaServerMarkerConfiguration的源码如下:

  1. @Configuration
    public class EurekaServerMarkerConfiguration {
        public EurekaServerMarkerConfiguration() {
        }

        @Bean
        public EurekaServerMarkerConfiguration.Marker eurekaServerMarkerBean() {
            return new EurekaServerMarkerConfiguration.Marker();
        }

        class Marker {
            Marker() {
            }
        }
    }

2. 依据条件选择配置类

@EnableAsync使用了这种方式,注解源码如下:

  1. @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(AsyncConfigurationSelector.class)
    public @interface EnableAsync {

        Class<? extends Annotation> annotation() default Annotation.class;

        boolean proxyTargetClass() default false;

        AdviceMode mode() default AdviceMode.PROXY;

        int order() default Ordered.LOWEST_PRECEDENCE;
    }

EnableAsync注解中导入了AsyncConfigurationSelector,AsyncConfigurationSelector通过条件来选择需要导入的配置类,继承AdviceModeImportSelector又实现了ImportSelector接口,接口重写selectImports方法进行事先条件判断PROXY或者ASPECTJ选择不同的配置类。

AsyncConfigurationSelector源码如下:

  1. public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {

        private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
                "org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";


        /**
         * Returns {@link ProxyAsyncConfiguration} or {@code AspectJAsyncConfiguration}
         * for {@code PROXY} and {@code ASPECTJ} values of {@link EnableAsync#mode()},
         * respectively.
         */
        @Override
        @Nullable
        public String[] selectImports(AdviceMode adviceMode) {
            switch (adviceMode) {
                case PROXY:
                    return new String[] {ProxyAsyncConfiguration.class.getName()};
                case ASPECTJ:
                    return new String[] {ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME};
                default:
                    return null;
            }
        }

    }

3. 动态注册Bean

@EnableAspectJAutoProxy使用了这种方式,注解源码如下:

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

        boolean proxyTargetClass() default false;

        boolean exposeProxy() default false;
    }

EnableAspectJAutoProxy注解中导入了AspectJAutoProxyRegistrar,AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,在运行时把Bean注册到spring容器中。

AspectJAutoProxyRegistrar的源码如下:

  1. class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

        /**
         * Register, escalate, and configure the AspectJ auto proxy creator based on the value
         * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
         * {@code @Configuration} class.
         */
        @Override
        public void registerBeanDefinitions(
                AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

            AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

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

    }

原文链接:http://www.cnblogs.com/haha12/p/11730357.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号