欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring Boot 啟動(dòng)注解過(guò)程分析

 更新時(shí)間:2023年06月15日 14:29:27   作者:江南一點(diǎn)雨  
這篇文章主要為大家介紹了Spring Boot 啟動(dòng)注解過(guò)程示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

雖然我們?cè)谌粘i_(kāi)發(fā)中,Spring Boot 使用非常多,算是目前 Java 開(kāi)發(fā)領(lǐng)域一個(gè)標(biāo)配了,但是小伙伴們仔細(xì)想想自己的面試經(jīng)歷,和 Spring Boot 相關(guān)的面試題都有哪些?個(gè)人感覺(jué)應(yīng)該是比較少的,Spring Boot 本質(zhì)上還是曾經(jīng) SSM 那一套,只是通過(guò)各種 starter 簡(jiǎn)化了配置而已,其他都是一模一樣的,所以 Spring Boot 中很多面試題還是得回歸到 Spring 中去解答!當(dāng)然這并不是說(shuō) Spring Boot 中沒(méi)什么可問(wèn)的,Spring Boot 中其實(shí)也有一個(gè)非常經(jīng)典的面試題,那就是 Spring Boot 中的自動(dòng)化配置是怎么實(shí)現(xiàn)的?今天松哥就來(lái)和各位小伙伴聊一下這個(gè)問(wèn)題。

其實(shí)松哥之前和小伙伴們聊過(guò)相關(guān)的問(wèn)題,不過(guò)都是零散的,沒(méi)有系統(tǒng)梳理過(guò),之前也帶領(lǐng)小伙伴們自定義過(guò)一個(gè) starter,相信各位小伙伴對(duì)于 starter 的原理也有一定了解,所以今天這篇文章一些過(guò)于細(xì)節(jié)的內(nèi)容我就不贅述了,大家可以翻看之前的文章。

1. @SpringBootApplication

要說(shuō) Spring Boot 的自動(dòng)化配置,那必須從項(xiàng)目的啟動(dòng)類(lèi) @SpringBootApplication 說(shuō)起,這是整個(gè) Spring Boot 宇宙的起點(diǎn),我們先來(lái)看下這個(gè)注解:

@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 {
}

可以看到,@SpringBootApplication 注解組合了多個(gè)常見(jiàn)注解的功能,其中:

  • 前四個(gè)是元注解,這里我們不做討論。
  • 第五個(gè) @SpringBootConfiguration 是一個(gè)支持配置類(lèi)的注解,這里我們也不做討論。
  • 第六個(gè) @EnableAutoConfiguration 這個(gè)注解就表示開(kāi)啟自動(dòng)化配置,這是我們今天要聊得重點(diǎn)。
  • 第七個(gè) @ComponentScan 是一個(gè)包掃描注解,為什么 Spring Boot 項(xiàng)目中的 Bean 只要放對(duì)位置就會(huì)被自動(dòng)掃描到,和這個(gè)注解有關(guān)。

別看這里注解多,其實(shí)真正由 Spring Boot 提供的注解一共就兩個(gè),分別是 @SpringBootConfiguration 和 @EnableAutoConfiguration 兩個(gè),其他注解在 Spring Boot 出現(xiàn)之前就已經(jīng)存在多年了。

2. @EnableAutoConfiguration

接下來(lái)我們來(lái)看看 @EnableAutoConfiguration 是如何實(shí)現(xiàn)自動(dòng)化配置的。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}

這個(gè)注解起關(guān)鍵作用的就是兩個(gè)東西:

  • @AutoConfigurationPackage:這個(gè)表示自動(dòng)掃描各種第三方的注解,在之前的文章中松哥已經(jīng)和大家聊過(guò)這個(gè)注解的作用了,傳送門(mén):@AutoConfigurationPackage 和 @ComponentScan 有何區(qū)別?
  • @Import 則是在導(dǎo)入 AutoConfigurationImportSelector 配置類(lèi),這個(gè)配置類(lèi)里邊就是去加載各種自動(dòng)化配置類(lèi)的。

3. AutoConfigurationImportSelector

AutoConfigurationImportSelector 類(lèi)中的方法比較多,入口的地方則是 process 方法,所以我們這里就從 process 方法開(kāi)始看起:

@Override
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
    Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
            () -> String.format("Only %s implementations are supported, got %s",
                    AutoConfigurationImportSelector.class.getSimpleName(),
                    deferredImportSelector.getClass().getName()));
    AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
        .getAutoConfigurationEntry(annotationMetadata);
    this.autoConfigurationEntries.add(autoConfigurationEntry);
    for (String importClassName : autoConfigurationEntry.getConfigurations()) {
        this.entries.putIfAbsent(importClassName, annotationMetadata);
    }
}

從類(lèi)名就可以看出來(lái),跟自動(dòng)化配置相關(guān)的對(duì)象是由 AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector).getAutoConfigurationEntry(annotationMetadata); 進(jìn)行加載的。

當(dāng)然這里的 getAutoConfigurationEntry 方法實(shí)際上就是當(dāng)前類(lèi)提供的方法,我們來(lái)看下該方法:

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
        return EMPTY_ENTRY;
    }
    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 = getConfigurationClassFilter().filter(configurations);
    fireAutoConfigurationImportEvents(configurations, exclusions);
    return new AutoConfigurationEntry(configurations, exclusions);
}

這里源碼的方法命名都做的不錯(cuò),基本上都能做到見(jiàn)名知意,小伙伴們?nèi)粘i_(kāi)發(fā)中,應(yīng)該向這樣的命名思路看齊。接下來(lái)我們就來(lái)挨個(gè)看一下這里的關(guān)鍵方法。

3.1 isEnabled

首先調(diào)用 isEnabled 方法去判斷自動(dòng)化配置到底有沒(méi)有開(kāi)啟,這個(gè)主要是因?yàn)槲覀兗皶r(shí)在項(xiàng)目中引入了 spring-boot-starter-xxx 之后,我們也可以通過(guò)在 application.properties 中配置 spring.boot.enableautoconfiguration=false 來(lái)關(guān)閉所有的自動(dòng)化配置。

相關(guān)源碼如下:

protected boolean isEnabled(AnnotationMetadata metadata) {
    if (getClass() == AutoConfigurationImportSelector.class) {
        return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, true);
    }
    return true;
}

3.2 getCandidateConfigurations

接下來(lái)調(diào)用 getCandidateConfigurations 方法去獲取所有候選的自動(dòng)化配置類(lèi),這些候選的自動(dòng)化配置類(lèi)主要來(lái)自兩個(gè)地方:

  • 在之前的自定義 starter 中松哥和大家聊過(guò),我們需要在 claspath\:META-INF/spring.factories 中定義出來(lái)所有的自動(dòng)化配置類(lèi),這是來(lái)源一。
  • Spring Boot 自帶的自動(dòng)化配置類(lèi),這個(gè)在之前的 vhr 視頻中也和小伙伴們多次講過(guò),Spring Boot 自帶的自動(dòng)化配置類(lèi)位于 spring-boot-autoconfigure-3.0.6.jar!\META-INF\spring\org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中。

相關(guān)源碼如下:

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = new ArrayList<>(
            SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));
    ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);
    Assert.notEmpty(configurations,
            "No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
                    + "are using a custom packaging, make sure that file is correct.");
    return configurations;
}

這里加載到的自動(dòng)化配置類(lèi)的全路徑被存入到 configurations 對(duì)象中,該對(duì)象有兩個(gè)獲取的地方:

  • 調(diào)用 SpringFactoriesLoader.loadFactoryNames 方法獲取,這個(gè)方法細(xì)節(jié)我就不帶大家看了,比較簡(jiǎn)單,本質(zhì)上就是去加載 META-INF/spring.factories 文件,這個(gè)文件中定義了大量的自動(dòng)化配置類(lèi)的全路徑。
  • 調(diào)用 ImportCandidates.load 方法去加載,這個(gè)就是加載 spring-boot-autoconfigure-3.0.6.jar!\META-INF\spring\org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中的自動(dòng)化配置類(lèi)。

如果這兩個(gè)地方都沒(méi)有加載到任何自動(dòng)化配置類(lèi),那么就會(huì)拋出一個(gè)異常。

3.3 removeDuplicates

removeDuplicates 方法表示移除候選自動(dòng)化配置類(lèi)中重復(fù)的類(lèi),移除的思路也很有意思,就用一個(gè) LinkedHashSet 中轉(zhuǎn)一下就行了,源碼如下:

protected final <T> List<T> removeDuplicates(List<T> list) {
    return new ArrayList<>(new LinkedHashSet<>(list));
}

可以看到這些源碼里有時(shí)候一些解決思路也很有意思。

3.4 getExclusions

getExclusions 方法表示需要獲取到所有被排除的自動(dòng)化配置類(lèi),這些被排除的自動(dòng)化配置類(lèi)可以從三個(gè)地方獲?。?/p>

  • 當(dāng)前注解的 exclude 屬性。
  • 當(dāng)前注解的 excludeName 屬性。
  • application.properties 配置文件中的 spring.autoconfigure.exclude 屬性。

來(lái)看一下相關(guān)源碼:

protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    Set<String> excluded = new LinkedHashSet<>();
    excluded.addAll(asList(attributes, "exclude"));
    excluded.addAll(asList(attributes, "excludeName"));
    excluded.addAll(getExcludeAutoConfigurationsProperty());
    return excluded;
}

跟上面講解的三點(diǎn)剛好對(duì)應(yīng)。

3.5 checkExcludedClasses

這個(gè)方法是檢查所有被排除的自動(dòng)化配置類(lèi),由于 Spring Boot 中的自動(dòng)化配置類(lèi)可以自定義,并不需要統(tǒng)一實(shí)現(xiàn)某一個(gè)接口或者統(tǒng)一繼承某一個(gè)類(lèi),所以在寫(xiě)排除類(lèi)的時(shí)候,如果寫(xiě)錯(cuò)了編譯是校驗(yàn)不出來(lái)的,像下面這種:

@SpringBootApplication(exclude = HelloController.class)
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

由于 HelloController 并不是一個(gè)自動(dòng)化配置類(lèi),所以這樣寫(xiě)項(xiàng)目啟動(dòng)的時(shí)候就會(huì)報(bào)錯(cuò),如下:

這個(gè)異常從哪來(lái)的呢?其實(shí)就是來(lái)自 checkExcludedClasses 方法,我們來(lái)看下該方法:

private void checkExcludedClasses(List<String> configurations, Set<String> exclusions) {
    List<String> invalidExcludes = new ArrayList<>(exclusions.size());
    for (String exclusion : exclusions) {
        if (ClassUtils.isPresent(exclusion, getClass().getClassLoader()) && !configurations.contains(exclusion)) {
            invalidExcludes.add(exclusion);
        }
    }
    if (!invalidExcludes.isEmpty()) {
        handleInvalidExcludes(invalidExcludes);
    }
}
protected void handleInvalidExcludes(List<String> invalidExcludes) {
    StringBuilder message = new StringBuilder();
    for (String exclude : invalidExcludes) {
        message.append("\t- ").append(exclude).append(String.format("%n"));
    }
    throw new IllegalStateException(String.format(
            "The following classes could not be excluded because they are not auto-configuration classes:%n%s",
            message));
}

可以看到,在 checkExcludedClasses 方法中,會(huì)首先找到所有位于當(dāng)前類(lèi)路徑下但是卻不包含在 configurations 中的所有被排除的自動(dòng)化配置類(lèi),由于 configurations 中的就是所有的自動(dòng)化配置類(lèi)了,所以這些不存在于 configurations 中的類(lèi)都是有問(wèn)題的,都不是自動(dòng)化配置類(lèi),將這些有問(wèn)題的類(lèi)收集起來(lái),存入到 invalidExcludes 變量中,然后再進(jìn)行額外的處理。

所謂額外的處理就是在 handleInvalidExcludes 方法中拋出異常,前面截圖中的異常就是來(lái)自這里。

3.6 removeAll

這個(gè)方法就一個(gè)任務(wù),就是從 configurations 中移除掉那些被排除的自動(dòng)化配置類(lèi)。configurations 本身就是 List 集合,exclusions 則是一個(gè) Set 集合,所以這里直接移除即可。

3.7 filter

現(xiàn)在我們已經(jīng)加載了所有的自動(dòng)化配置類(lèi)了,但是這些配置類(lèi)并不是都會(huì)生效,具體是否生效,還要看你的項(xiàng)目是否使用了具體的依賴。

例如,現(xiàn)在加載的自動(dòng)化配置里里邊就包含了 RedisAutoConfiguration,這個(gè)是自動(dòng)配置 Redis 的,但是由于我的項(xiàng)目中并沒(méi)有使用 Redis,所以這個(gè)自動(dòng)化配置類(lèi)并不會(huì)生效。這個(gè)過(guò)程就是由 getConfigurationClassFilter().filter(configurations); 來(lái)完成的。

先說(shuō)一個(gè)預(yù)備知識(shí):

由于我們項(xiàng)目中的自動(dòng)化配置類(lèi)特別多,每一個(gè)自動(dòng)化配置類(lèi)都會(huì)依賴別的類(lèi),當(dāng)別的類(lèi)存在時(shí),這個(gè)自動(dòng)化配置類(lèi)才會(huì)生效,這一堆互相之間的依賴關(guān)系,存在于 spring-boot-autoconfigure-3.0.6.jar!/META-INF/spring-autoconfigure-metadata.properties 文件之中,我隨便舉一個(gè)該文件中的配置:

  • org.springframework.boot.autoconfigure.amqp.RabbitAnnotationDrivenConfiguration.ConditionalOnClass=org.springframework.amqp.rabbit.annotation.EnableRabbit 表示 RabbitAnnotationDrivenConfiguration 類(lèi)要生效有一個(gè)必備條件就是當(dāng)前項(xiàng)目類(lèi)路徑下要存在 org.springframework.amqp.rabbit.annotation.EnableRabbit。

我們來(lái)看看 RabbitAnnotationDrivenConfiguration 類(lèi)的注解:

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(EnableRabbit.class)
class RabbitAnnotationDrivenConfiguration {
}

這個(gè)類(lèi)和配置文件中的內(nèi)容一致。

這個(gè)預(yù)備知識(shí)搞懂了,接下來(lái)的內(nèi)容就好理解了。

先來(lái)看 getConfigurationClassFilter 方法,這個(gè)就是獲取所有的過(guò)濾器,如下:

private ConfigurationClassFilter getConfigurationClassFilter() {
    if (this.configurationClassFilter == null) {
        List<AutoConfigurationImportFilter> filters = getAutoConfigurationImportFilters();
        for (AutoConfigurationImportFilter filter : filters) {
            invokeAwareMethods(filter);
        }
        this.configurationClassFilter = new ConfigurationClassFilter(this.beanClassLoader, filters);
    }
    return this.configurationClassFilter;
}

可以看到,這里獲取到的過(guò)濾器都是 AutoConfigurationImportFilter 類(lèi)型的,這個(gè)類(lèi)型的過(guò)濾器只有三個(gè)實(shí)例,如下圖:

從這三個(gè)實(shí)例的名字中,基本上就能看出來(lái)各自的作用:

  • OnClassCondition:這個(gè)就是條件注解 @ConditionalOnClass 的判定條件,看名字就知道用來(lái)判斷當(dāng)前 classpath 下是否存在某個(gè)類(lèi)。
  • OnWebApplicationCondition:這個(gè)是條件注解 ConditionalOnWebApplication 的判定條件,用來(lái)判斷當(dāng)前系統(tǒng)環(huán)境是否是一個(gè) Web 環(huán)境。
  • OnBeanCondition:這個(gè)是條件注解 @ConditionalOnBean 的判定條件,就是判斷當(dāng)前系統(tǒng)下是否存在某個(gè) Bean。

這里獲取到的三個(gè) AutoConfigurationImportFilter 過(guò)濾器其實(shí)就是上面這三個(gè)。接下來(lái)執(zhí)行 filter 方法,如下:

List<String> filter(List<String> configurations) {
    long startTime = System.nanoTime();
    String[] candidates = StringUtils.toStringArray(configurations);
    boolean skipped = false;
    for (AutoConfigurationImportFilter filter : this.filters) {
        boolean[] match = filter.match(candidates, this.autoConfigurationMetadata);
        for (int i = 0; i < match.length; i++) {
            if (!match[i]) {
                candidates[i] = null;
                skipped = true;
            }
        }
    }
    if (!skipped) {
        return configurations;
    }
    List<String> result = new ArrayList<>(candidates.length);
    for (String candidate : candidates) {
        if (candidate != null) {
            result.add(candidate);
        }
    }
    return result;
}

這里就是遍歷這三個(gè)過(guò)濾器,然后分別調(diào)用各自的 match 方法和 144 個(gè)自動(dòng)化配置類(lèi)進(jìn)行匹配,如果這些自動(dòng)化配置類(lèi)所需要的條件得到滿足,則 match 數(shù)組對(duì)應(yīng)的位置就為 true,否則就為 false。

然后遍歷 match 數(shù)組,將不滿足條件的自動(dòng)化配置類(lèi)置為 null,最后再把這些 null 移除掉。

這樣就獲取到了我們需要進(jìn)行自動(dòng)化配置的類(lèi)了。

最后一句 fireAutoConfigurationImportEvents 則是觸發(fā)自動(dòng)化配置類(lèi)導(dǎo)入事件,這個(gè)沒(méi)啥好說(shuō)的~

當(dāng)這些自動(dòng)化配置類(lèi)加載進(jìn)來(lái)之后,接下來(lái)就是各種條件注解來(lái)決定這些配置類(lèi)是否生效了,這些都比較簡(jiǎn)單了,之前在 vhr 種也和小伙伴們講過(guò)多次了,這里就不再啰嗦了~

好啦,經(jīng)過(guò)上面的梳理相信小伙伴們對(duì) Spring Boot 自動(dòng)化配置類(lèi)的加載有一個(gè)大概的認(rèn)知了吧~

以上就是Spring Boot 啟動(dòng)注解過(guò)程分析的詳細(xì)內(nèi)容,更多關(guān)于Spring Boot 啟動(dòng)注解的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 利用java反射機(jī)制調(diào)用類(lèi)的私有方法(推薦)

    利用java反射機(jī)制調(diào)用類(lèi)的私有方法(推薦)

    下面小編就為大家?guī)?lái)一篇利用java反射機(jī)制調(diào)用類(lèi)的私有方法(推薦)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-08-08
  • idea批量啟動(dòng)多個(gè)微服務(wù)具體實(shí)現(xiàn)

    idea批量啟動(dòng)多個(gè)微服務(wù)具體實(shí)現(xiàn)

    這篇文章主要給大家介紹了關(guān)于idea批量啟動(dòng)多個(gè)微服務(wù)的具體實(shí)現(xiàn),在微服務(wù)開(kāi)發(fā)過(guò)程中,我們經(jīng)常要在本地啟動(dòng)很多個(gè)微服務(wù),文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • Java如何基于反射機(jī)制獲取不同的類(lèi)

    Java如何基于反射機(jī)制獲取不同的類(lèi)

    這篇文章主要介紹了Java如何基于反射機(jī)制獲取不同的類(lèi),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • 一篇文章帶你Java Spring開(kāi)發(fā)入門(mén)

    一篇文章帶你Java Spring開(kāi)發(fā)入門(mén)

    這篇文章主要為大家詳細(xì)介紹了Java Spring開(kāi)發(fā)入門(mén)學(xué)習(xí)教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2021-09-09
  • Java實(shí)現(xiàn)摳圖片文字或簽名的完整代碼

    Java實(shí)現(xiàn)摳圖片文字或簽名的完整代碼

    這篇文章主要介紹了java摳圖片文字或簽名的運(yùn)行原理,本文分步驟通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • 詳解spring cloud分布式整合zipkin的鏈路跟蹤

    詳解spring cloud分布式整合zipkin的鏈路跟蹤

    這篇文章主要介紹了詳解spring cloud分布式整合zipkin的鏈路跟蹤,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • java發(fā)送kafka事務(wù)消息的實(shí)現(xiàn)方法

    java發(fā)送kafka事務(wù)消息的實(shí)現(xiàn)方法

    本文主要介紹了java發(fā)送kafka事務(wù)消息的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • 關(guān)于MVC設(shè)計(jì)模式及流程解析

    關(guān)于MVC設(shè)計(jì)模式及流程解析

    這篇文章主要介紹了關(guān)于MVC設(shè)計(jì)模式及流程解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • idea中斷點(diǎn)類(lèi)型之All和Thread的區(qū)別介紹

    idea中斷點(diǎn)類(lèi)型之All和Thread的區(qū)別介紹

    使用all模式對(duì)于程序中含有多個(gè)線程來(lái)說(shuō),會(huì)將多個(gè)線程都阻塞在斷點(diǎn),此時(shí)所有的線程都執(zhí)行到此處,在最后一個(gè)線程執(zhí)行到此處是會(huì)發(fā)生暫停,在這之前的線程會(huì)繼續(xù)執(zhí)行到任意位置,本文給大家詳細(xì)介紹下idea中斷點(diǎn)類(lèi)型之All和Thread的區(qū)別,感興趣的朋友一起看看吧
    2022-03-03
  • JUnit5相關(guān)內(nèi)容簡(jiǎn)介

    JUnit5相關(guān)內(nèi)容簡(jiǎn)介

    這篇文章主要介紹了JUnit5相關(guān)內(nèi)容簡(jiǎn)介,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01

最新評(píng)論