????歡迎光臨,終于等到你啦????
??我是蘇澤,一位對(duì)技術(shù)充滿熱情的探索者和分享者。????
??持續(xù)更新的專欄《Spring 狂野之旅:從入門到入魔》 ??
本專欄帶你從Spring入門到入魔?
這是蘇澤的個(gè)人主頁(yè)可以看到我其他的內(nèi)容哦????
努力的蘇澤http://suzee.blog.csdn.net/
?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-842671.html
?文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-842671.html
springboot幫我們做了什么
一個(gè)字--自動(dòng)!
通常搭建一個(gè)基于spring的web應(yīng)用,我們需要做以下工作:
1、pom文件中引入相關(guān)jar包,包括spring、springmvc、redis、mybaits、log4j、mysql-connector-java 等等相關(guān)jar ...
2、配置web.xml,Listener配置、Filter配置、Servlet配置、log4j配置、error配置 ...
3、配置數(shù)據(jù)庫(kù)連接、配置spring事務(wù)
4、配置視圖解析器
5、開(kāi)啟注解、自動(dòng)掃描功能
6、配置完成后部署tomcat、啟動(dòng)調(diào)試
......
這些都是Spring boot在背后默默為我們做的工作
那 有沒(méi)有想過(guò)為什么??
本文給大家來(lái)解讀Spring的源碼 拆解他的自動(dòng)配置 一步一步解釋為什么Springboot為何那么強(qiáng)大
?
?
進(jìn)入他的細(xì)節(jié)源碼之前 首先關(guān)注 ---架構(gòu)
解讀SpringBootApplication
@Target(ElementType.TYPE) // 注解的適用范圍,其中TYPE用于描述類、接口(包括包注解類型)或enum聲明
@Retention(RetentionPolicy.RUNTIME) // 注解的生命周期,保留到class文件中(三個(gè)生命周期)
@Documented // 表明這個(gè)注解應(yīng)該被javadoc記錄
@Inherited // 子類可以繼承該注解
@SpringBootConfiguration // 繼承了Configuration,表示當(dāng)前是注解類
@EnableAutoConfiguration // 開(kāi)啟springboot的注解功能,springboot的四大神器之一,其借助@import的幫助
@ComponentScan(excludeFilters = { // 掃描路徑設(shè)置(具體使用待確認(rèn))
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
}
@Configuration
這里的@Configuration 對(duì)我們來(lái)說(shuō)不陌生,它就是 JavaConfig 形式的 Spring Ioc 容器的配置類使用的那個(gè)@Configuration,SpringBoot?社區(qū)推薦使用基于 JavaConfig 的配置形式,所以,這里的啟動(dòng)類標(biāo)注了@Configuration 之后,本身其實(shí)也是一個(gè) IoC 容器的配置類。 舉幾個(gè)簡(jiǎn)單例子回顧下,XML 跟 config 配置方式的區(qū)別:
表達(dá)形式層面 基于 XML 配置的方式是這樣:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
default-lazy-init="true">
<!--bean定義-->
</beans>
而基于 JavaConfig 的配置方式是這樣:
@Configuration
public class MockConfiguration{
//bean定義
}
任何一個(gè)標(biāo)注了@Configuration 的 Java 類定義都是一個(gè) JavaConfig 配置類。
注冊(cè) bean 定義層面 基于 XML 的配置形式是這樣:
<bean id="mockService" class="..MockServiceImpl">
...
</bean>
而基于 JavaConfig 的配置形式是這樣的:
@Configuration
public class MockConfiguration{
@Bean
public MockService mockService(){
return new MockServiceImpl();
}
}
任何一個(gè)標(biāo)注了@Bean 的方法,其返回值將作為一個(gè) bean 定義注冊(cè)到 Spring 的 IoC 容器,方法名將默認(rèn)成該 bean 定義的 id。
表達(dá)依賴注入關(guān)系層面 為了表達(dá) bean 與 bean 之間的依賴關(guān)系,在 XML 形式中一般是這樣:
<bean id="mockService" class="..MockServiceImpl">
<propery name ="dependencyService" ref="dependencyService" />
</bean>
<bean id="dependencyService" class="DependencyServiceImpl"></bean>
而基于 JavaConfig 的配置形式是這樣的:
@Configuration
public class MockConfiguration{
@Bean
public MockService mockService(){
return new MockServiceImpl(dependencyService());
}
@Bean
public DependencyService dependencyService(){
return new DependencyServiceImpl();
}
}
@ComponentScan:
@ComponentScan注解用于指定Spring容器掃描組件的基礎(chǔ)包路徑。它會(huì)自動(dòng)掃描指定包及其子包下的類,并將被@Component及其派生注解標(biāo)注的類識(shí)別為Spring的組件,將其實(shí)例化并納入容器管理。
// 在包c(diǎn)om.example中定義了兩個(gè)被@Component注解標(biāo)記的類:UserService和UserRepository
// UserService.java
package com.example;
import org.springframework.stereotype.Component;
@Component
public class UserService {
// ...
}
// UserRepository.java
package com.example;
import org.springframework.stereotype.Component;
@Component
public class UserRepository {
// ...
}
// AppConfig.java
package com.example;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.example") // 指定掃描的基礎(chǔ)包路徑
public class AppConfig {
// 配置其他的Bean
}
@ComponentScan的原理可以從源代碼的角度來(lái)解釋。在Spring的源代碼中,@ComponentScan注解被解析為一個(gè)Bean掃描器。當(dāng)Spring容器啟動(dòng)時(shí),掃描器會(huì)根據(jù)指定的包路徑,將帶有@Component及其派生注解的類解析為BeanDefinition對(duì)象,并注冊(cè)到BeanFactory中。這樣,Spring容器就知道這些類是組件,并可以對(duì)其進(jìn)行實(shí)例化和管理。
?
@EnableAutoConfiguration:
@EnableAutoConfiguration注解用于啟用Spring Boot的自動(dòng)配置功能。它會(huì)根據(jù)項(xiàng)目的依賴和配置,自動(dòng)加載和配置一系列的Spring Bean,簡(jiǎn)化了項(xiàng)目的配置過(guò)程。
@EnableAutoConfiguration的原理可以從源代碼的角度來(lái)解釋。在Spring Boot的源代碼中,@EnableAutoConfiguration注解被解析為一個(gè)自動(dòng)配置處理器。當(dāng)Spring Boot應(yīng)用啟動(dòng)時(shí),處理器會(huì)根據(jù)classpath下的META-INF/spring.factories文件中的配置,加載并執(zhí)行一系列的自動(dòng)配置類。這些自動(dòng)配置類根據(jù)約定和條件,自動(dòng)創(chuàng)建和配置相應(yīng)的Bean對(duì)象,完成項(xiàng)目的自動(dòng)化配置。
Import(AutoConfigurationImportSelector.class)注解:
圖中看出 AutoConfigurationImportSelector 繼承了 DeferredImportSelector 繼承了 ImportSelector
ImportSelector有一個(gè)方法為:selectImports。
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return StringUtils.toStringArray(configurations);
}
AutoConfigurationImportSelector是Spring Boot內(nèi)部的一個(gè)選擇器類,它會(huì)根據(jù)項(xiàng)目的依賴和配置,選擇要自動(dòng)配置的類。該選擇過(guò)程是基于條件注解(如@ConditionalOnClass、@ConditionalOnProperty等)進(jìn)行的,只有滿足條件的自動(dòng)配置類才會(huì)被選擇。
?
@AutoConfigurationPackage
// 在包c(diǎn)om.example中定義了一個(gè)主配置類ApplicationConfig
// ApplicationConfig.java
package com.example;
import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@AutoConfigurationPackage // 標(biāo)注了@AutoConfigurationPackage注解
public class ApplicationConfig {
// 主配置類的內(nèi)容
// ...
}
當(dāng)Spring Boot啟動(dòng)時(shí),它會(huì)掃描并解析主配置類ApplicationConfig
。在解析過(guò)程中,Spring Boot會(huì)檢測(cè)到@AutoConfigurationPackage
注解,并執(zhí)行相應(yīng)的處理。
@AutoConfigurationPackage
注解被解析為一個(gè)特殊的Bean定義處理器。處理器會(huì)讀取主配置類ApplicationConfig
的包路徑(com.example
),并將該包路徑注冊(cè)到Spring的BeanFactory中。
注冊(cè)完成后,Spring容器會(huì)將com.example
包及其子包作為組件掃描的范圍。這意味著Spring會(huì)掃描該包下的所有類,并根據(jù)條件注解(如@ConditionalOnClass
、@ConditionalOnMissingBean
等)來(lái)決定是否自動(dòng)配置相應(yīng)的Bean。
通過(guò)將主配置類所在的包及其子包作為自動(dòng)配置的包,我們可以確保自動(dòng)配置類能夠正確地掃描和應(yīng)用到我們的應(yīng)用程序中。
?
?
?
到了這里,關(guān)于拆解Spring boot:Springboot為什么如此絲滑而簡(jiǎn)單?源碼剖析解讀自動(dòng)裝配的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!