当前位置: 首页 > 科技观察

这篇文章带你了解Spring的@Enable开头的注解

时间:2023-03-22 16:43:12 科技观察

上一篇介绍Spring的重试机制的时候提到过Spring有很多@Enable开头的注解,我一般都不会去关注当我使用它时。但是为什么会有这些注解呢,今天给大家介绍一下。@Enable注解首先我们来看一下常用的以@Enable开头的注解及其用途。@EnableRetry:开启Spring的重试功能;@EnableScheduling:开启Spring的定时功能;@EnableAsync:开启Spring的异步功能;@EnableAutoConfiguration:开启Spring的自动装配功能;以上是我们经常用到的,大家用过看到过,就知道在使用相应的功能时,如果不配置上面的注解功能,是不会生效的。以我们上一篇文章中的Spring重试为例,我们需要在启动类上配置@EnableRetry,否则自动重试注解@Retryable不会生效,如下图,没看过的可以去看看,Java远程调用失败?如何优雅地重试?.@Import注解有的朋友会问,这个@EnableRetry注解有什么作用呢?没有这个注解就没有办法了吗?要知道这个注解有什么作用,我们可以点击查看源码,代码如下:导入java.lang。注释.保留;导入java.lang.annotation.RetentionPolicy;导入java.lang.annotation.Target;导入org.springframework.context.annotation.EnableAspectJAutoProxy;导入org.springframework.context.annotation.Import;@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@EnableAspectJAutoProxy(proxyTargetClass=false)@Import(RetryConfiguration.class)@Documentedpublic@interfaceEnableRetry{booleanproxyTargetClass()defaultfalse;}可以看到源码很简单,最有用的一行@Import(RetryConfiguration.class),我们可以尝试把这行代码放到启动类上看看效果,如下图,可以看到项目可以正常启动,而且还是有效的,解释我们的@EnableRetry注释是一样的。从上面的实验结果可以看出,@EnableRetry注解其实是对@Import(RetryConfiguration.class)的封装。同样,通过源码我们也可以看出@EnableScheduling注解是对@Import({SchedulingConfiguration.class})的引用是一个wrapper。@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Import({SchedulingConfiguration.class})@Documentedpublic@interfaceEnableScheduling{}如果没有@Enablexxx注解,我们直接通过@Import注解即可可以这样写,在一个@Import注解中包含多个配置类,但是在配置类很多的场景下这样相对不够简洁,所以有@Enable注解对应各自的功能。包com.example.demo;导入org.springframework.boot.SpringApplication;导入org.springframework.boot.autoconfigure.SpringBootApplication;导入org.springframework.context.annotation.ComponentScan;导入org.springframework.context.annotation.Import;导入org.springframework.retry.annotation.RetryConfiguration;导入org.springframework.scheduling.annotation.SchedulingConfiguration;@SpringBootApplication@ComponentScan(value="com.example.demo.*")@Import({RetryConfiguration.class,SchedulingConfiguration.class})publicclassDemoApplication{publicstaticvoidmain(String[]args){SpringApplication.run(DemoApplication.class,args);}}为什么要使用@Import注解?那么很多朋友又要问了,为什么要使用@Import注解来加载配置类呢?不能在项目中的Spring上下文中直接获取吗?为此,让我们进行实验。通过下面的代码,我们可以看到是否可以获取到Spring容器com.example.demo;importorg.springframework.boot.SpringApplication;importorg.springframework.boot中RetryConfiguration的Beanpackage。自动配置。SpringBoot应用;导入组织.springframework.context.ConfigurableApplicationContext;导入org.springframework.context.annotation.ComponentScan;导入org.springframework.context.annotation.Import;导入org.springframework.retry.annotation.RetryConfiguration;导入org.springframework.scheduling.annotation.SchedulingConfiguration@SpringBootApplication@ComponentScan(value="com.example.demo.*")//@Import({RetryConfiguration.class,SchedulingConfiguration.class})publicclassDemoApplication{publicstaticvoidmain(String[]args){ConfigurableApplicationContextapplicationContext=SpringApplication.run(DemoApplication.class,args);对象bean=applicationContext.getBean("org.springframework.retry.annotation.RetryConfiguration");System.out.println(bean.toString());}}启动后我们可以看到如下结果,提醒我们找不到容器中的bean。有朋友会问是不是bean的名字写错了,其实并没有。然后我们可以释放注释行并再次运行它。看,我们这次成功获取到这个Bean了。这个实验告诉我们,其实默认情况下,在Spring容器中是找不到RetryConfigurationBean的,所以我们需要使用@Import注解,将类加载到容器中。那么为什么在容器中找不到这个bean呢?其实很简单,因为这个Bean和我们当前环境中的类不在同一个包中。项目启动过程中不会扫描RetryConfiguration类所在的包,所以找不到是正常的。综上所述,通过上面的@EnableRetry注解,我们了解了Spring@Enable开头注解的使用原理。相信你对这些注解有了更深的理解。简单的说,因为我们要使用的很多类不在我们项目所在的包下,所以我们无法扫描所有的依赖包,也不方便通过@Import导入所有的配置类。而是让每个功能项目包都提供一个以@Enable开头的注解,我们直接启用这个注解就可以达到效果。这样我们在平时的开发中也可以自己实现,实现自己的以@Enable开头的注解来实现具体的功能。