您好,登錄后才能下訂單哦!
小編給大家分享一下@SpringBootApplication與@SpringBootTest的區(qū)別有哪些,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
一般情況我們使用 @SpringBootApplication 注解來(lái)啟動(dòng) SpringBoot 項(xiàng)目
它其實(shí)只相當(dāng)于 @Configuration、@EnableAutoConfiguration、@ComponentScan(包含了兩個(gè)filter)
@SpringBootApplication public class FrameworkUnitRealTestApp { public static void main(String[] args) { SpringApplication.run(FrameworkUnitRealTestApp.class, args); } }
一般情況我們使用 @SpringBootTest 和 @RunWith(SpringRunner.class) 注解來(lái)啟動(dòng) SpringBoot 測(cè)試項(xiàng)目
@RunWith(SpringRunner.class) @SpringBootTest public class FrameworkUnitRealTestApp { @Test public void test() {} }
這兩個(gè)注解的區(qū)別的核心在于兩個(gè)注解:@EnableAutoConfiguration、@ComponentScan(包含了兩個(gè)filter)
@EnableAutoConfiguration 啟動(dòng)了所有的自動(dòng)配置類(lèi)
@ComponentScan(包含了兩個(gè)filter):在掃描階段過(guò)濾掉 @TestComponent 等專(zhuān)屬于測(cè)試的類(lèi)和過(guò)濾掉被 @Configuration 注解的自動(dòng)配置類(lèi)(使得自動(dòng)配置類(lèi)不會(huì)在掃描階段就被注冊(cè) beanDefinition,因?yàn)?自動(dòng)配置類(lèi)的優(yōu)先級(jí)應(yīng)該是最低的)
可以看出 @SpringBootTest 并沒(méi)有啟用任何自動(dòng)配置類(lèi),所以就不需要加 AutoConfigurationExcludeFilter 了
springboot 通過(guò)引入 @Test** 注解來(lái)在 測(cè)試環(huán)境下 引入不同的自動(dòng)配置類(lèi)!
詳細(xì)的代碼如下:添加了 TypeExcludeFilter 和 AutoConfigurationExcludeFilter 兩個(gè) excludeFilter
作用:掃描包的時(shí)候過(guò)濾掉被這兩個(gè) Filter 匹配的類(lèi)!
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
4.1 TypeExcludeFilter 解析
主要移除測(cè)試相關(guān)的類(lèi)
public class TypeExcludeFilter implements TypeFilter, BeanFactoryAware { @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { if (this.beanFactory instanceof ListableBeanFactory && getClass() == TypeExcludeFilter.class) { Collection<TypeExcludeFilter> delegates = ((ListableBeanFactory) this.beanFactory) .getBeansOfType(TypeExcludeFilter.class).values(); for (TypeExcludeFilter delegate : delegates) { if (delegate.match(metadataReader, metadataReaderFactory)) { return true; } } } return false; } } //delegate.match 走這個(gè)類(lèi)的 match 方法 class TestTypeExcludeFilter extends TypeExcludeFilter { private static final String[] CLASS_ANNOTATIONS = { "org.junit.runner.RunWith", "org.junit.jupiter.api.extension.ExtendWith" }; private static final String[] METHOD_ANNOTATIONS = { "org.junit.Test", "org.junit.platform.commons.annotation.Testable" }; @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { //是否被 @TestComponent 及其父注解注釋 if (isTestConfiguration(metadataReader)) {return true;} //類(lèi)上或類(lèi)中方法上有沒(méi)有 CLASS_ANNOTATIONS、METHOD_ANNOTATIONS 中的注解 if (isTestClass(metadataReader)) {return true;} String enclosing = metadataReader.getClassMetadata().getEnclosingClassName(); if (enclosing != null) { //遞歸內(nèi)部類(lèi)、父類(lèi) if (match(metadataReaderFactory.getMetadataReader(enclosing), metadataReaderFactory)) { return true; } } return false; } }
4.2 AutoConfigurationExcludeFilter 解析
主要移除被 @Configuration 修飾的 自動(dòng)配置類(lèi)
public class AutoConfigurationExcludeFilter implements TypeFilter, BeanClassLoaderAware { @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { //如果被 @Configuration 注解,并且是 自動(dòng)配置類(lèi)就返回 true,即匹配成功 //注:被 @Component 等注解并不匹配 return isConfiguration(metadataReader) && isAutoConfiguration(metadataReader); } }
作用:?jiǎn)⒂米詣?dòng)配置類(lèi)
@AutoConfigurationPackage //啟用 AutoConfigurationImportSelector 配置類(lèi):掃描得到所有自動(dòng)配置類(lèi) @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; //定義不啟用的 自動(dòng)配置類(lèi) Class<?>[] exclude() default {}; //同上 String[] excludeName() default {}; } //這個(gè)注解主要是向容器中注冊(cè) AutoConfigurationPackages.Registrar 類(lèi)用來(lái)存儲(chǔ)自動(dòng)配置包 @Import(AutoConfigurationPackages.Registrar.class) public @interface AutoConfigurationPackage {} //關(guān)鍵:這個(gè)類(lèi)繼承了 DeferredImportSelector 接口,所以是到最后才解析的?。? public class AutoConfigurationImportSelector implements DeferredImportSelector{ @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader .loadMetadata(this.beanClassLoader); AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry( autoConfigurationMetadata, annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); } }
Spring Boot 中文文檔 對(duì)每個(gè) @…Test 注解導(dǎo)入的自動(dòng)配置類(lèi)做了詳細(xì)的說(shuō)明
SpringBootTest 是測(cè)試使用類(lèi)的注解,標(biāo)志這個(gè)類(lèi)是測(cè)試用例。
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @BootstrapWith(SpringBootTestContextBootstrapper.class) @ExtendWith({SpringExtension.class}) public @interface SpringBootTest {
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} ) public @interface SpringBootApplication {
對(duì)比顯示都是復(fù)合注解,并且前四個(gè)注解是一樣的,后面區(qū)分BootstrapWith和ExtendWith這兩個(gè)是測(cè)試中包含的
BootstrapWith這個(gè)注解中有一個(gè)參數(shù)為SpringBootTestContextBootstrapper
這里面申明了一些程序運(yùn)行所在包的路徑,在去查看繼承的頂級(jí)類(lèi)可以追溯到TestContextBootstrapper 這個(gè)接口 :
從里面的方法可以看到是在運(yùn)行的時(shí)候設(shè)置上下文 以及如何獲取上下文,來(lái)提供測(cè)試啟動(dòng)的必須值。
可以看出這個(gè)實(shí)現(xiàn)了很多接口,來(lái)處理測(cè)試需要的各種通知處理,以及在測(cè)試接口時(shí)可以提前處理請(qǐng)求參數(shù)。
SpringBootApplication中的復(fù)合注解則是掃描一些包和配置。雖然測(cè)試也是項(xiàng)目啟動(dòng)的一種,可以看到里面實(shí)現(xiàn)還是有些區(qū)別的。
看完了這篇文章,相信你對(duì)“@SpringBootApplication與@SpringBootTest的區(qū)別有哪些”有了一定的了解,如果想了解更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。