一文帶你瞭解 Spring 的 @Enable 開頭的註解
@Enable 註解
首先我們先看一下有哪些常用的
@Enable
開頭的註解,以及都是幹什麼用的。
@EnableRetry
:開啟
Spring
的重試功能;
@EnableScheduling
:開啟
Spring
的定時功能;
@EnableAsync
:開啟
Spring
的非同步功能;
@EnableAutoConfiguration
:開啟
Spring
的自動裝配功能;
上面這幾個是我們經常會用到和看到的,都知道在使用相應的功能的時候,如果沒有配置上面的註解功能都是不生效的。以我們前面的文章的
Spring
重試為例,我們需要在啟動類上面配置
@EnableRetry
,否則自動重試註解
@Retryable
是不會生效的,如下所示,沒看過的可以去看下,Java 遠端呼叫失敗?如何優雅的進行重試?。
@Import 註解
那有的小夥伴就要問了,這個
@EnableRetry
註解到底有什麼作用呢?不用這個註解就沒辦法了嗎?
要知道這個註解有什麼功效,我們可以點開看看原始碼,程式碼如下
package org。springframework。retry。annotation;import java。lang。annotation。Documented;import java。lang。annotation。ElementType;import java。lang。annotation。Retention;import java。lang。annotation。RetentionPolicy;import java。lang。annotation。Target;import org。springframework。context。annotation。EnableAspectJAutoProxy;import org。springframework。context。annotation。Import;@Target(ElementType。TYPE)@Retention(RetentionPolicy。RUNTIME)@EnableAspectJAutoProxy(proxyTargetClass = false)@Import(RetryConfiguration。class)@Documentedpublic @interface EnableRetry { boolean proxyTargetClass() default false;}
可以看到原始碼很簡單,其中最有用的就一行
@Import(RetryConfiguration。class)
,我們可以嘗試把這一行程式碼放到啟動類上面看看效果,如下所示,可以看到專案可以正常啟動,並且也還是有效果的,說明跟我們的
@EnableRetry
註解是一樣的。
從上面的實驗效果我們可以看到
@EnableRetry
註解其實就是對
@Import(RetryConfiguration。class)
的一個封裝,同樣的透過原始碼我們還可以看到
@EnableScheduling
註解就是對
@Import({SchedulingConfiguration。class})
的一個封裝。
@Target({ElementType。TYPE})@Retention(RetentionPolicy。RUNTIME)@Import({SchedulingConfiguration。class})@Documentedpublic @interface EnableScheduling {}
那如果在沒有
@Enablexxx
註解的時候,我們直接透過
@Import
註解是可以這樣寫的,在一個
@Import
註解裡面包含多個配置類,不過這種在配置類較多的場景下還是相對不夠簡潔的,因而才有了各自功能對應的
@Enable
註解。
package com。example。demo;import org。springframework。boot。SpringApplication;import org。springframework。boot。autoconfigure。SpringBootApplication;import org。springframework。context。annotation。ComponentScan;import org。springframework。context。annotation。Import;import org。springframework。retry。annotation。RetryConfiguration;import org。springframework。scheduling。annotation。SchedulingConfiguration;@SpringBootApplication@ComponentScan(value = “com。example。demo。*”)@Import({RetryConfiguration。class, SchedulingConfiguration。class})public class DemoApplication { public static void main(String[] args) { SpringApplication。run(DemoApplication。class, args); }}
為什麼要使用 @Import 註解呢
那麼很多的小夥伴又要問了,為啥要透過使用
@Import
註解將配置類載入進來呢?在專案中的
Spring
上下文中不是能直接獲取到嗎?為此我們來實驗一下,透過下面的程式碼我們看下是否能在
Spring
的容器中獲取到
RetryConfiguration
的
Bean
package com。example。demo;import org。springframework。boot。SpringApplication;import org。springframework。boot。autoconfigure。SpringBootApplication;import org。springframework。context。ConfigurableApplicationContext;import org。springframework。context。annotation。ComponentScan;import org。springframework。context。annotation。Import;import org。springframework。retry。annotation。RetryConfiguration;import org。springframework。scheduling。annotation。SchedulingConfiguration;@SpringBootApplication@ComponentScan(value = “com。example。demo。*”)//@Import({RetryConfiguration。class, SchedulingConfiguration。class})public class DemoApplication { public static void main(String[] args) { ConfigurableApplicationContext applicationContext = SpringApplication。run(DemoApplication。class, args); Object bean = applicationContext。getBean(“org。springframework。retry。annotation。RetryConfiguration”); System。out。println(bean。toString()); }}
啟動過後我們可以看到結果如下,提示我們在容器中找不到這個
bean
,有點小夥伴會說是不是
bean
的名字寫錯了,其實並不是,緊接著我們再把註釋的那一行放開再執行一下。
可以看到,這次我們成功的獲取到了這個
Bean
,這個實驗就是告訴我們,其實在預設情況下,
Spring
的容器中是找不到
RetryConfiguration
這個
Bean
的,因此我們需要透過使用
@Import
註解,將該類載入到容器中。
那麼為什麼在容器中找不到這個
Bean
呢?
其實很簡單,因為這個
Bean
跟我們當前環境的類是不是同一個包裡面的,在專案啟動的過程中並不會掃描到
RetryConfiguration
類所在的包,因此找不到是很正常的。
總結
上面透過
@EnableRetry
這個註解帶大家瞭解了一下
Spring
的
@Enable
開頭的註解的使用原理,相信大家對這些註解有了更深入的瞭解。簡單來說就是因為我們要使用的很多類並不在我們專案所在的包下面,我們不能將所有的依賴包都進行掃描,也不不方便將所有的配置類都透過
@Import
的方式進行匯入,而是讓每個功能的專案包都提供一個
@Enable
開頭的註解,我們直接啟用註解就可以達到效果。