日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
SpringBoot手動(dòng)配置@Enable的秘密

在 Spring Boot開發(fā)過程中,我們經(jīng)常會(huì)看到使用 @EnableXXX來(lái)激活我們某一個(gè)功能性的模塊,通過類注解激活后我們就能使用所激活的配置給我們帶來(lái)的功能。

創(chuàng)新互聯(lián)公司服務(wù)項(xiàng)目包括蘆山網(wǎng)站建設(shè)、蘆山網(wǎng)站制作、蘆山網(wǎng)頁(yè)制作以及蘆山網(wǎng)絡(luò)營(yíng)銷策劃等。多年來(lái),我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,蘆山網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到蘆山省份的部分城市,未來(lái)相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

今天我們就來(lái)探究一下這個(gè) @EnableXXX給我們做了哪些工作,或者我們應(yīng)該怎么通過自定義的方式開發(fā)我們自己的功能模塊。

演示環(huán)境

  • IntelliJ IDEA 2020.2.1 (Community Edition)
  • Maven 3.5.4
  • Spring Boot 2.1.1.RELEASE

走進(jìn)源碼

在 SpringBoot中 @Enable的實(shí)現(xiàn)方式用兩種。

一種是注解驅(qū)動(dòng)的方式,我們以 @EnableWebMvc為例進(jìn)行探究;

另外一種是接口編程的方式,我們以 @EnableCaching為例進(jìn)行探究。

1、注解驅(qū)動(dòng)方式(@EnableWebMvc)

在 Spring Boot項(xiàng)目中,當(dāng)我們可以使用 @EnableWebMvc注解用來(lái)激活我們的 Spring MVC相關(guān)的配置,接下來(lái)進(jìn)入源碼一探究竟。

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

通過觀察上面的源碼,我們就可以大膽的猜測(cè),其實(shí)使用 @EnableWebMvc注解的作用就是導(dǎo)入 DelegatingWebMvcConfiguration.class這個(gè)類,接下來(lái)我們就進(jìn)入這個(gè)類看看。

@Configuration  
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
........
@Override
protected void addInterceptors(InterceptorRegistry registry) {
this.configurers.addInterceptors(registry);
}
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
this.configurers.addResourceHandlers(registry);
}
........
}

進(jìn)入到這個(gè)類中我們發(fā)現(xiàn)了這個(gè) @Configuration注解,到這兒我們好像明白了寫什么。首先這個(gè) DelegatingWebMvcConfiguration類繼承了 WebMvcConfigurationSupport類,重寫了里面的關(guān)于 WebMvc的相關(guān)配置,然后作為一個(gè)配置類加載到我們的 Spring容器中。至此來(lái)實(shí)現(xiàn)啟動(dòng)(激活)WebMvc模塊。

2、接口編程的方式(@EnableCaching)

在 Spring Boot項(xiàng)目中,當(dāng)我們可以使用 @EnableCaching注解用來(lái)激活我們的緩存相關(guān)的配置,接著進(jìn)入源碼看看到底做了什么。

@Target(ElementType.TYPE)  
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(CachingConfigurationSelector.class)
public @interface EnableCaching {
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
int order() default Ordered.LOWEST_PRECEDENCE;
}

這里 @EnableCaching同樣是使用 @Import導(dǎo)入了一個(gè)配置類,而它導(dǎo)入的是 CachingConfigurationSelector,接著我進(jìn)入這個(gè)類看一看。

public class CachingConfigurationSelector extends AdviceModeImportSelector {  
.....
@Override
public String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return getProxyImports();
case ASPECTJ:
return getAspectJImports();
default:
return null;
}
}
.....
}

發(fā)現(xiàn)其實(shí)這個(gè)類沒有被注解標(biāo)注,但是它繼承了 AdviceModeImportSelector,而這個(gè)類又繼承了 ImportSelector,并且我們可以看看 ImportSelector的代碼:

public interface ImportSelector {  
/**
* Select and return the names of which class(es) should be imported based on
* the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
*/
String[] selectImports(AnnotationMetadata importingClassMetadata);
}

這個(gè)類中只用一個(gè)方法,那就是 selectImports。也就是說當(dāng)我們重寫了這個(gè)方法之后,我們可以在方法中添加自己的邏輯判斷,來(lái)決定最后導(dǎo)入哪些配置類。這樣就可以實(shí)現(xiàn)靈活的加載配置。這個(gè)方法的返回值 String[]里面存放的是所有復(fù)合條件的配置類的全路徑信息。

自定義實(shí)現(xiàn)

通過上面的分析我們已經(jīng)完成了對(duì) @EnableXXX套路的了解,接下來(lái)我們自己動(dòng)手實(shí)現(xiàn)下。首先需要準(zhǔn)備一個(gè) Spirng Boot的項(xiàng)目,這里我已經(jīng)準(zhǔn)備好了。

1、注解驅(qū)動(dòng)方式的自定義實(shí)現(xiàn)

根據(jù)我們分析源碼的步驟我們首先需要準(zhǔn)備一個(gè)配置類。接下來(lái)在 configuration包下,創(chuàng)建一個(gè) HelloConfiguration。代碼如下:

/**  
* Hello模塊的配置
*/
@Configuration
public class HelloConfiguration {
@Bean
public String hello() { // method name is bean name
System.out.println("Bean : hello is loading.");
return "hello word !";
}
}

這里被 @Bean標(biāo)注的方法,方法名會(huì)作為 bean對(duì)象的名稱。而且當(dāng)該 bean被加載的時(shí)候我們還會(huì)在控制臺(tái)輸出一段話 Bean : hello is loading.。

配置類我們已經(jīng)準(zhǔn)備好了,接下來(lái)我們?cè)?annotation包中編寫激活配置的注解。

/**  
* 激活Hello模塊配置
*
* @author Jerome Zhu
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(HelloConfiguration.class) // 模塊裝配:注解驅(qū)動(dòng)實(shí)現(xiàn)
public @interface EnableHello {
}

最后我們?cè)?bootstrap包中編寫驗(yàn)證我們 @EnableHello模塊的啟動(dòng)類。

/**  
* 驗(yàn)證自定義 {@link EnableHello} 模塊化裝配
*
* @author Jerome Zhu
*/
@EnableHello
public class EnableHelloBootstrap {
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(EnableHelloBootstrap.class)
.web(WebApplicationType.NONE)
.run(args);
String helloBean = context.getBean("hello", String.class);
System.out.println("hello Bean: " + helloBean);
context.close();
}
}

我們?cè)谖覀儐?dòng)類上標(biāo)注了 @EnableHello來(lái)激活我們的 Hello模塊,并且在 Spring Boot項(xiàng)目啟動(dòng)后,獲取到了應(yīng)用的上下文 ConfigurableApplicationContext。然后我們根據(jù)我們注入的 bean的名字 hello來(lái)獲取 bean,接著打印 bean的內(nèi)容,最后關(guān)閉上下文。

我們啟動(dòng)程序后,可以在控制臺(tái)中看到這樣兩行輸出:

Bean : hello is loading.  
hello Bean: hello word !

這剛好就是我們配置的內(nèi)容,到這兒我們就完成了基于注解驅(qū)動(dòng)方式激活(啟動(dòng))配置。

2、接口編程方式自定義實(shí)現(xiàn)

根據(jù)我們讀過源碼后,我們首先最重要的是有一個(gè)繼承 ImportSelector的實(shí)現(xiàn)類。在 annotation包中創(chuàng)建一個(gè) HelloImportSelector配置類。

/**  
* Hello {@link ImportSelector} 的實(shí)現(xiàn)
*/
public class HelloImportSelector implements ImportSelector {
private final String key = "jerome";
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
if ("jerome".equals(key)) {
return new String[]{HelloJeromeConfiguration.class.getName()};
}
return new String[]{HelloConfiguration.class.getName()};
}
}

這里為了體現(xiàn)出 selectImports方法的作用,我們?cè)诒绢愔刑砑右粋€(gè) key字段。當(dāng) key的值為 jerome的時(shí)候我們?nèi)ゼ虞d HelloJeromeConfiguration這個(gè)配置類。首先看一個(gè)這個(gè)配置類的內(nèi)容。

/**  
* Hello模塊的配置
*
* @author Jerome Zhu
*/
@Configuration
public class HelloJeromeConfiguration {
@Bean
public String hello() { // method name is bean name
System.out.println("Bean : hello is loading.");
return "hello jerome !";
}
}

加載這個(gè)配置類后 bean的名字還是 hello但是內(nèi)容變成了 hello jerome !。接著我們對(duì) @EnableHello注解進(jìn)行改造改造成 @EnableHellos。

/**  
* 激活Hellos模塊配置
*
* @author Jerome Zhu
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(HelloImportSelector.class) // 模塊裝配:接口驅(qū)動(dòng)實(shí)現(xiàn) 優(yōu)點(diǎn)可選bean
public @interface EnableHellos {
}

這里使用了 HelloImportSelector來(lái)實(shí)現(xiàn)我們的模塊裝配。

這里 @EnableHellos可能不符合命名規(guī)范,這里只做演示使用,不要噴我。

最后我們?cè)?bootstrap包中編寫驗(yàn)證我們 @EnableHello模塊的啟動(dòng)類。

/**  
* 驗(yàn)證自定義 {@link EnableHellos} 模塊化裝配
*
* @author Jerome Zhu
*/
@EnableHellos
public class EnableHellosBootstrap {
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(EnableHellosBootstrap.class)
.web(WebApplicationType.NONE)
.run(args);
String helloBean = context.getBean("hello", String.class);

System.out.println("hello Bean: " + helloBean);
context.close();
}
}

這里和基于注解驅(qū)動(dòng)方式激活(啟動(dòng))配置的驗(yàn)證方法一樣,我就是直接拷貝的,主要修改了 @EnableHellos這個(gè)激活注解。

我們啟動(dòng)程序后,可以在控制臺(tái)中看到這樣兩行輸出:  

Bean : hello is loading.  
hello Bean: hello jerome !

這剛好就是我們配置的內(nèi)容,到這兒我們就完成了基于接口編程方式激活(啟動(dòng))配置。

總結(jié)

我們通過上面了解了 @EnableXXX的兩種實(shí)現(xiàn)方式。其中基于注解驅(qū)動(dòng)方式激活(啟動(dòng))配置的方式是相對(duì)方便的一個(gè)實(shí)現(xiàn),需要激活什么就直接導(dǎo)入該配置類即可;而基于接口編程方式激活(啟動(dòng))配置的方式相對(duì)更加靈活,可以根據(jù)自定義的規(guī)則來(lái)選擇激活哪些配置類,不激活哪些配置類,這是一種比較靈活的方式,方便我們對(duì)其進(jìn)行擴(kuò)展。

總之這兩種方式都是手動(dòng)激活的方式,換言之我們需要在啟動(dòng)類上添加 @Enable***的注解,來(lái)手動(dòng)激活配置,這種方式在某些場(chǎng)景并不是很方便。


文章標(biāo)題:SpringBoot手動(dòng)配置@Enable的秘密
分享路徑:http://www.5511xx.com/article/ccisige.html