Maison  >  Article  >  Java  >  Analyse d'un exemple de processus d'exécution SpringBoot

Analyse d'un exemple de processus d'exécution SpringBoot

PHPz
PHPzavant
2023-05-12 15:19:061354parcourir

Chaque projet Spring Boot a une classe de démarrage du programme principal. Dans la classe de démarrage du programme principal, il existe une méthode main() pour démarrer le projet. Dans cette méthode, l'ensemble du programme Spring Boot peut être démarré en exécutant SpringApplication.run(). .

Question : Alors, comment la méthode SpringApplication.run() démarre-t-elle le projet Spring Boot ?

Regardons le code source à l'intérieur de la méthode run(). Le code de base est le suivant :

@SpringBootApplication
public class SpringbootDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootDemoApplication.class, args);
    }
}
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
    return run(new Class[]{primarySource}, args);
}
    public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
        return (new SpringApplication(primarySources)).run(args);
}

Comme le montre le code source ci-dessus, la méthode SpringApplication.run() effectue deux opérations en interne, à savoir l'opération initiale. la création et l'invocation de l'instance SpringApplication. run() démarre le projet La mise en œuvre de ces deux étapes est détaillée comme suit

1. Création initiale de l'instance SpringApplication

Affichez les informations du code source d'initialisation et de création de l'objet d'instance SpringApplication. Le code de base est le suivant

    public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
        this.sources = new LinkedHashSet();
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        this.addCommandLineProperties = true;
        this.addConversionService = true;
        this.headless = true;
        this.registerShutdownHook = true;
        this.additionalProfiles = new HashSet();
        this.isCustomEnvironment = false;
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
    // 把项目启动类.class设置为属性存储起来
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
    // 判断当前webApplicationType应用的类型
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
    // 设置初始化器(Initializer),最后会调用这些初始化器
        this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
    // 设置监听器(Listener)
        this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
    // 用于推断并设置项目main()方法启动的主程序启动类
        this.mainApplicationClass = this.deduceMainApplicationClass();

Comme le montre le code source ci-dessus, le processus d'initialisation de SpringApplication comprend principalement 4 parties, et la description spécifique est la suivante.

(1) this.webApplicationType = WebApplicationType.deduceFromClasspath()

est utilisé pour déterminer le type de l'application webApplicationType actuelle. La méthode deduceFromClasspath() est utilisée pour vérifier si une certaine classe de fonctionnalités existe sous le chemin de classe Classpath, afin de déterminer si le type webApplicationType actuel est une application SERVLET (application MVC traditionnelle avant Spring 5) ou une application REACTIVE (application interactive WebFlux qui a commencé à apparaître au printemps 5)

(2) this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class))

Pour les paramètres d'initialisation de l'application SpringApplication. Pendant le processus de configuration de l'initialiseur, le chargeur de classe Spring SpringFactoriesLoader sera utilisé pour obtenir toutes les classes d'initialisation d'application disponibles ApplicationContextInitializer à partir du fichier spring.factores sous META-INF sous le chemin de classe META-INF/spring.factories.

(3) this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class))

Utilisé pour les paramètres d'écoute de l'application SpringApplication. Le processus de configuration de l'écouteur est fondamentalement le même que le processus de configuration de l'initialiseur de l'étape précédente. SpringFactoriesLoader est également utilisé pour obtenir toutes les classes d'écoute disponibles ApplicationListener à partir du fichier spring.factores sous META-INF sous le chemin de classe META-INF/spring.factories. .

(4) this.mainApplicationClass = this.deduceMainApplicationClass()

Utilisé pour déduire et définir la classe de démarrage du programme principal démarrée par la méthode main() du projet

2. Démarrage initial du projet

Après avoir analysé la création initiale de l'objet d'instance SpringApplication dans la partie précédente du code source (new SpringApplication(primarySources)).run(args), vérifiez le processus de démarrage d'initialisation du projet exécuté par le run(args ) Le code de base est le suivant :

  public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
        this.configureHeadlessProperty();
    // 第一步:获取并启动监听器
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting();
        Collection exceptionReporters;
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
    // 第二步:根据SpringApplicationRunListeners以及参数来准备环境
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
    // 准备Banner打印器 - 就是启动Spring Boot的时候打印在console上的ASCII艺术字体
            Banner printedBanner = this.printBanner(environment);
    // 第三步:创建Spring容器
            context = this.createApplicationContext();
            exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, new Object[]{context});
    // 第四步:Spring容器前置处理
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
    // 第五步:刷新容器
            this.refreshContext(context);
    // 第六步:Spring容器后置处理
            this.afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }
    // 第七步:发出结束执行的事件
            listeners.started(context);
    // 返回容器
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            this.handleRunFailure(context, var10, exceptionReporters, listeners);
            throw new IllegalStateException(var10);
        }
        try {
            listeners.running(context);
            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners) null);
            throw new IllegalStateException(var9);
        }
    }

Comme le montre le code source ci-dessus, le processus d'initialisation et de démarrage du projet comprend grossièrement les parties suivantes :

Étape 1 : Obtenir et démarrer l'écouteur

This.getRunListeners. Les méthodes (args) et Listeners.starting() sont principalement utilisées pour obtenir des instances SpringApplication. L'écouteur SpringApplicationRunListener est initialisé et exécuté pendant le processus d'initialisation.

Étape 2 : Préparez l'environnement en fonction des SpringApplicationRunListeners et des paramètres

Cette méthode.prepareEnvironment(listeners, applicationArguments) est principalement utilisée pour prédéfinir l'environnement d'exécution du projet, et en même temps exclure certaines opérations inutiles via this.configureIgnoreBeanInfo(environment) méthode Environnement

Étape 3 : Créer un conteneur Spring

Juge basé sur webApplicationType pour déterminer le type de conteneur. Si le type est SERVLET, le bytecode correspondant sera chargé par réflexion, qui est AnnotationConfigServletWebServerApplicationContext, puis utilisera l'ensemble de contexte précédemment initialisé. (Contexte de l'application), environnement (environnement d'exécution du projet), écouteurs (écouteurs en cours d'exécution), applicationArguments (paramètres du projet) et impriméBanner (informations sur l'icône du projet) assemblent et configurent le contexte de l'application et actualisent la configuration

Étape 4 : avant la configuration du conteneur Spring traitement

Cette étape est principalement une action préparatoire avant le rafraîchissement du contenant. Configurez l'environnement du conteneur, y compris diverses variables, etc., y compris une opération très critique : injectez la classe de démarrage dans le conteneur pour jeter les bases d'une configuration automatisée ultérieure. Étape 5 : Actualisez le conteneur Spring via l'actualisation. Initialisez l'intégralité du conteneur IOC (y compris le positionnement des ressources du bean, l'analyse, l'enregistrement, etc.) et enregistrez un hook d'arrêt avec le runtime JVM. Ce contexte sera fermé à l'arrêt de la JVM, à moins qu'il n'ait déjà été fermé. à ce moment-là

Étape 6 : post-traitement du conteneur Spring

interface d'extension, méthode de modèle dans le modèle de conception, implémentation vide par défaut. Si vous avez des exigences personnalisées, vous pouvez remplacer cette méthode. Par exemple, l'impression de certains journaux de démarrage et d'achèvement, ou un autre post-traitement.

Étape 7 : Émettez un événement qui termine l'exécution

Obtenez l'écouteur EventPublishingRunListener et exécutez sa méthode démarrée, puis transmettez le conteneur Spring créé, créez un événement ApplicationStartedEvent et exécutez la méthode

publishEvent de ConfigurableApplicationContext, c'est-à-dire qu'il est a déclaré que les événements sont publiés dans le conteneur Spring, pas dans SpringApplication. Ceci est différent du démarrage précédent qui publie l'événement de démarrage directement dans l'écouteur dans SpringApplication.

Étape 8 : Exécuter les coureurs

Utilisé pour appeler la classe d'exécuteur personnalisée XxxRunner dans le projet pour exécuter certains programmes spécifiques immédiatement après le démarrage du projet. Parmi elles, les interfaces d'exécution fournies par Spring Boot incluent ApplicationRunner et CommandLineRunner. Lors de son utilisation, il vous suffit de personnaliser une classe d'exécuteur pour implémenter l'une des interfaces et de réécrire l'interface de la méthode run() correspondante. démarré immédiatement. Exécutez ces programmes spécifiques

Ci-dessous, grâce à un organigramme d'exécution de Spring Boot, faites connaître plus clairement à chacun le processus d'exécution global et les principales étapes de démarrage de Spring Boot :

Analyse dun exemple de processus dexécution SpringBoot

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer