Spring boot自動裝配,是指spring應用程序上下文,根據類路徑,和定義的bean,猜測並自動裝配該應用程序可能要用到的bean。
自動裝配原理初探
pom.xml
- 核心依賴:在父工程spring-boot-dependencies中
- 引入spring-boot依賴時,不需要指定版本號,版本號統一在spring-boot-dependencies中管理。
- 引入插件時,若maven加載報錯找不到,要指定版本號
啟動器starter
starter啟動器是一種零配置、開箱即用的spring生態內第三方配置庫。就好比Spring生態內一站式技術解決方案商店。
啟動器包含了應用正常運轉所需的全部依賴。該依賴具有完整性,可傳遞性。
-
spring boot所有官方啟動器都是以spring-boot-starter開頭的,方便開發者搜索starter
-
比如spring-boot-starter-web,會自動導入web環境所有的依賴。
-
springboot會將所有的功能場景,配置並包裝成一個個啟動器。
-
需要使用什么功能,只需導入對應的啟動器就可以了。
-
Spring官方支持的啟動器列表詳見:
主程序
主程序是啟動Spring boot的入口。一般@SpringBootApplication 或者@EnableAutoConfiguration注解修飾的類,是Spring boot項目的主程序。主程序本身也是一個主配置類。
@SpringBootApplication //標注這是一個Spring boot應用程序,啟動類下的所有資源被導入
public class Springboot01HelloApplication {
public static void main(String[] args) {
/*運行Spring boot應用程序*/
SpringApplication.run(Springboot01HelloApplication.class, args);
}
}
主程序要放在root package下面。用戶自定義的包也要在root package下。以便conponent-scan
可以自動掃描跟主程序同級的包,自動裝配成Spring bean。
@SpringBootApplication注解
@SpringBootApplication等價於@SpringBootConfiguration、@EnableAutoConfiguration、 @ComponentScan三個注解。
@SpringBootConfiguration
@Configuration //表明是一個配置類
@Conponent //注冊為Spring的一個組件
@EnableAutoConfiguration
@AutoConfigurationPackage //自動配置包
@Import(AutoConfigurationPackages.Registrar.class) //自動配置包注冊者
@Import(AutoConfigurationImportSelector.class) //自動配置導入選擇器
@ComponentScan //自動掃描跟主程序同級的包
@Configuration注解
spring boot推薦基於java代碼的配置java config。使用@Configuration注解修飾類,表示該類為一個配置類。同時也被標記為@Component
組件。
- 可以通過@Import注解引入其它@Configuration類。
proxyBeanMethods
屬性- ture:full模式, 利用cglib代理增強,bean是單例的。SpringBoot啟動會檢查容器中是否存在該組件。
- false:lite模式,每一次調用,都返回新實例對象。SpringBoot啟動時不會檢查該組件,啟動更快。
@Conditional組合注解
使用@Conditional
組合注解來指定自動加載bean的條件。@Conditional
指定的條件成立,才會在Application Context 中加載組件,自動配置類才生效。
- 作用在TYPE上,Spring 自動掃描的一切類 (@Configuration, @Component, @Service, @Repository, @Controller) 都可以通過添加相應的
@ConditionalOnXxxx
來判斷是否自動加載到應用上下文。 - 作用在METHOD上,僅限於@Bean標記的方法。
@Conditional擴展注解 | 判斷條件 |
---|---|
@ConditionalOnJava | 運行指定的Java版本 |
@ConditionalOnBean | 容器中存在指定Bean |
@ConditionalOnMissingBean | 容器中不存在指定Bean |
@ConditionalOnExpression | 滿足指定的SpEL表達式,支持多個配置屬性組合判斷 |
@ConditionalOnClass | 類路徑上有指定的類 |
@ConditionalOnMissingClass | 類路徑上沒有指定的類 |
@ConditionalOnSingleCandidate | 容器中只有一個指定的Bean,或者有一個用@Primary指定的首選Bean |
@ConditionalOnProperty | properties或yaml文件中配置的指定屬性是否有指定的值 |
@ConditionalOnResource | 類路徑下是否有指定的資源文件 |
@ConditionalOnWebApplication | 當前應用是Web應用 |
@ConditionalOnNotWebApplication | 當前應用不是Web應用 |
@ConditionalOnJndi | 指定的資源通過 JNDI 加載 |
在配置文件中,配置debug屬性值為true,即可在啟動日志中,查看到已生效Positive match的bean,未生效Negative match的bean,以及排除在外Exclude的bean。
步驟
加載META-INF/spring.factories
配置文件
AutoConfigurationImportSelector
類getAutoConfigurationEntry()
方法中:
//獲取所有配置
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
//獲取候選配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
SpringFactoriesLoader
類loadSpringFactories()
:
Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
......
}
自動配置核心文件FACTORIES_RESOURCE_LOCATION
:META-INF/spring.factories
,自動配置類在spring-boot-autoconfigure-2.4.3.jar
包下面。
- XXXAutoConfiguration:自動配置類,容器根據匹配條件,自動加載組件到應用上下文
- XXXProperties:用於裝配配置文件中自定義的配置內容。
結論:
- Spingboot所有的自動配置都是在啟動類中掃描並加載。
- 從classpath中搜尋
META-INF/spring.factories
配置文件,並將里面所有XXXAutoConfiguration配置項,通過反射,實例化為org.springframework.boot.autoconfigure
包下面的配置類,並納入到IOC容器管理。 - 整個J2EE的整體解決方案和自動配置都在springboot-autoconfigure的jar包中。
- Spring boot自動配置機制,免去了我們手動編寫配置注入依賴等工作。