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

本文目录

一、@Enable*实现的原理二、@Import注解的用法1. 直接导入配置类2. 依据条件选择配置类3. 动态注册Bean

一、@Enable*实现的原理

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

二、@Import注解的用法

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

有以下三种使用方式

1. 直接导入配置类

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

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

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

EurekaServerMarkerConfiguration的源码如下:

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

2. 依据条件选择配置类

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

@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源码如下:

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使用了这种方式,注解源码如下:

@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的源码如下:

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

推荐阅读

1.Java中Integer.parseInt和Integer.valueOf,你还傻傻分不清吗?
2.SpringCloud系列-整合Hystrix的两种方式)
3.SpringCloud系列-利用Feign实现声明式服务调用)
4.手把手带你利用Ribbon实现客户端的负载均》
5.SpringCloud搭建注册中心与服务注册


限时领取免费Java相关资料,涵盖了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo/Kafka、Hadoop、Hbase、Flink等高并发分布式、大数据、机器学习等技术。
关注下方公众号即可免费领取:

Java碎碎念公众号

SpringBoot中神奇的@Enable*注解?的更多相关文章

  1. springboot中@EnableAsync与@Async注解使用

    springboot中@EnableAsync与@Async注解使用 @Async为异步注解,放到方法上,表示调用该方法的线程与此方法异步执行,需要配合@EnableAsync注解使用. 1.首先演示 ...

  2. Springboot中使用自定义参数注解获取 token 中用户数据

    使用自定义参数注解获取 token 中User数据 使用背景 在springboot项目开发中需要从token中获取用户信息时通常的方式要经历几个步骤 拦截器中截获token TokenUtil工具类 ...

  3. 在Spring-boot中,为@Value注解添加从数据库读取properties支持

    一般我们会把常用的属性放在工程的classpath文件夹中,以property,yaml或json的格式进行文件存储,便于Spring-boot在初始化时获取. @Value则是Spring一个非常有 ...

  4. Spring中的@Enable注解

    本文转载自SpringBoot中神奇的@Enable注解? 导语 在SpringBoot开发过程,我们经常会遇到@Enable开始的好多注解,比如@EnableEurekaServer.@Enable ...

  5. SpringBoot中如何灵活的实现接口数据的加解密功能?

    数据是企业的第四张名片,企业级开发中少不了数据的加密传输,所以本文介绍下SpringBoot中接口数据加密.解密的方式. 本文目录 一.加密方案介绍二.实现原理三.实战四.测试五.踩到的坑 一.加密方 ...

  6. SpringBoot中如何优雅的读取yml配置文件?

    YAML是一种简洁的非标记语言,以数据为中心,使用空白.缩进.分行组织数据,从而使得表示更加简洁易读.本文介绍下YAML的语法和SpringBoot读取该类型配置文件的过程. 本文目录 一.YAML基 ...

  7. SpringBoot 中定时执行注解(@Scheduled、@EnableScheduling)

    项目开发中经常需要执行一些定时任务,比如需要在每天凌晨时候,分析一次前一天的日志信息.Spring为我们提供了异步执行任务调度的方式,提供TaskExecutor .TaskScheduler 接口. ...

  8. [SpringBoot]SpringBoot中使用redis事务

    本文基于SpringBoot 2.X 事务在关系型数据库的开发中经常用到,其实非关系型数据库,比如redis也有对事务的支持,本文主要探讨在SpringBoot中如何使用redis事务. 事务的相关介 ...

  9. SpringBoot中关于@Enable***的注解详解

    出处:http://blog.csdn.net/qq_26525215 @EnableAspectJAutoProxy @EnableAspectJAutoProxy注解 激活Aspect自动代理 & ...

随机推荐

  1. java使用FileSystem上传文件到hadoop分布式文件系统配置

    Configuration conf = new Configuration(); conf.set("fs.defaultFS", "hdfs://sparkclust ...

  2. ExpandableListView之BaseExpandableListAdapter

    之前使用的SimpleExpandableListAdapter有较大局限性,样式单一,修改难度大,这里不建议使用,而是利用BaseExpandableListAdapter,其实SimpleExpa ...

  3. 59 (OC)* atomic是否绝对安全

    场景:如今项目中有这样一个场景,在一个自定义类型的Property在一个线程中改变的同时也要同时在另一个线程中使用它,使我不得不将Property定义成atomic,但是由此发现atomic并不会保证 ...

  4. java取json 的方法

    public static void main(String[] args) { String jsonStr = "[{\"varieties_type\":\&quo ...

  5. 【POJ - 3723 】Conscription(最小生成树)

    Conscription Descriptions 需要征募女兵N人,男兵M人. 每招募一个人需要花费10000美元. 如果已经招募的人中有一些关系亲密的人,那么可以少花一些钱. 给出若干男女之前的1 ...

  6. 利用Python进行数据分析:【NumPy】

    一.NumPy:数组计算1.NumPy是高性能科学计算和数据分析的基础包.它是pandas等其他各种工具的基础.2.NumPy的主要功能: # ndarray,一个多维数组结构,高效且节省空间 # 无 ...

  7. 平行世界中的你还是你吗?--java中的==是否相等

    故事背景 <宇宙追缉令>是黄毅瑜执导的动作科幻类电影,由哥伦比亚三星公司出品,戴尔里·林多.李连杰.杰森·斯坦森领衔主演.影片于2001年11月2日在美国上映.该片讲述了邪恶尤兰,为了成为 ...

  8. OpenGl 实现鼠标分别移动多个物体 ----------移动一个物体另外一个物体不动--读取多个3d模型操作的前期踏脚石

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/11620088.html 前言: 因为接下来的项目需求是要读取多个3D模型,并且移动拼接,那么我 ...

  9. 阿里云服务器CentOS6.9安装SVN

    1.安装SVN yum -y install subversion 出现Complete表明安装成功 2.创建SVN仓库目录 mkdir -p /data/svn/repositories/yyksv ...

  10. JS/Jquery 表单方式提交总结

    1. submit提交 (1). submit 按钮式提交 缺点:在提交前不可修改提交的form表单数据 // 1. html <form method="post" act ...