springboot自動配置原理以及手動實現配置類

springboot自動配置原理以及手動實現配置類

1、原理

spring有一個思想是「約定大於配置」。

配置類自動配置可以幫助開發人員更加專註於業務邏輯開發,springboot在啟動的時候可以把一些配置類自動注入到spring的IOC容器里,項目運行之後就可以直接使用這些配置類的屬性和方法等。

springboot有一個全局配置文件,application.properties / application.yml,各種屬性都可以在文件中進行自定義配置。

自動配置實現原理:

我們都知道項目的入口是 @SpringBootApplication 註解,這個註解標識了該類是springboot的啟動類,那我們就從它入手一探究竟。

image-20220930213911027

我們可以看到這個註解是一個複合註解,其中的 @EnableAutoConfiguration 註解表示開啟自動配置,這個註解也是複合註解。

我們可以看到它導入了一個名為AutoConfigurationImportSelector的類,那麼這個類的作用是什麼呢?

image-20220930214038213

我們繼續往下看,可以看到 selectImports( ) 方法

image-20220930221426796

selectImports 這個方法通過調用 SpringFactoriesLoader.loadFactoryNames() 方法掃描spring-boot-autoconfigure-xxx.jar/META-INF路徑下的 spring.factories文件,通過類的全路徑拿到需要配置的類名,然後通過反射將其全部注入IOC容器中。

image-20220930221556112

image-20220930221728628

每個配置類都有一些屬性,XXXAutoConfiguration自動配置類,會有一個@EnableConfigurationProperties註解,它的參數是一個XXXProperties類,該註解的作用是把XXXProperties類的實例載入到Spring的IOC容器中,而XXXProperties類中的屬性就是自動配置的屬性。

XXXProperties類有一個註解@ConfigurationProperties,該註解可以掃描全局配置文件application.properties或者application.yml文件中以prefix開頭的一組配置綁定到DataSourceProperties實例的屬性上,實現自動配置。

// 全局掃描注入 配置文件中以spring.datasource開頭的值
@ConfigurationProperties(
    prefix = "spring.datasource"
)

2、手動寫一個自動配置類

有了上面的理解,我們可以自己動手寫一個自動配置類。

自動配置類做的事情就是把@EnableConfigurationProperties註解標識的類注入到IOC容器。

2.1、所以我們先寫一個自動配置類SeviceAutoConfiguration

package com.ycw.autoconfig.configuration;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * @author Administrator
 * @date 2022-09-30 21:51
 */
@Slf4j
@Configuration  // 自動配置類
@EnableConfigurationProperties(ServiceProperties.class)     // 標識XXXProperties類的實例
public class SeviceAutoConfiguration {

}

2.2、寫真正要加入容器的類ServiceProperties

package com.ycw.autoconfig.configuration;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * @author Administrator
 * @date 2022-09-30 21:50
 */
@Data
@Slf4j
@ConfigurationProperties(prefix = "myconfig")   // 掃描全局配置文件完成屬性注入
public class ServiceProperties {
	private String name;
	public void print(){
		log.info("自動配置成功! " + name);
	}
}

2.3、在resources目錄下新建目錄META-INF,新建文件spring.factories完成對自動配置類全路徑配置

image-20220930223207593

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.ycw.autoconfig.configuration.SeviceAutoConfiguration

2.4、在全局配置文件application.properties中添加屬性注入

image-20220930223402246

2.5、寫一個Controller測試,ControllerTest

package com.ycw.autoconfig.controller;

import com.ycw.autoconfig.configuration.ServiceProperties;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @author Administrator
 * @date 2022-09-30 21:54
 */
@RestController
public class ControllerTest {
	@Resource
	private ServiceProperties serviceProperties;
	@RequestMapping("test")
	public void test(){
		serviceProperties.print();
	}
}

運行之後我們可以看到:

image-20220930223517183

分析一下這個過程:

  1. 啟動類@SpringBootApplication通過spring.factories文件中的org.springframework.boot.autoconfigure.EnableAutoConfiguration找到了SeviceAutoConfiguration

  2. @Configuration 註解的類SeviceAutoConfiguration被springboot掃描到後,它所標識的@EnableConfigurationProperties(ServiceProperties.class) 開始進入被注入容器的過程

  3. ServiceProperties 類的註解@ConfigurationProperties(prefix = “myconfig”) 使得springboot掃描全局配置文件application.properties

  4. application.properties中的 myconfig.name=yangchuanwei 被注入到屬性name中,自此ServiceProperties已經被自動配置成功!


獲取demo地址可以關注公眾號【靠譜楊的挨踢生活】,回復【autoconfig】獲取下載鏈接。