Spring Boot fournit deux interfaces : CommandLineRunner et ApplicationRunner, qui sont utilisées pour effectuer un traitement spécial lors du démarrage de l'application. Ces codes seront exécutés avant que la méthode run() de SpringApplication ne soit terminée. Par rapport à l'écouteur personnalisé de l'interface ApplicationListener de Spring et à l'écouteur ServletContextListener de Servlet présentés dans le chapitre précédent. L'avantage d'utiliser les deux est que vous pouvez facilement utiliser les paramètres de démarrage de l'application et effectuer différentes opérations d'initialisation en fonction de différents paramètres.
Implémentez les interfaces CommandLineRunner et ApplicationRunner. Habituellement utilisé pour l'exécution de code spécial avant le démarrage de l'application, tel que :
Chargement des données système couramment utilisées en mémoire
Nettoyage des données indésirables de la dernière exécution de l'application
Envoi de notifications après le démarrage du système avec succès, etc.
J'ai implémenté l'interface CommandLineRunner et chargé les données de configuration couramment utilisées dans le système au démarrage de l'application, comme le montre la figure ci-dessous. Chargez les données de la base de données dans la mémoire Lorsque vous utiliserez les données ultérieurement, il vous suffit d'appeler la méthode getSysConfigList. Il n'est pas nécessaire de charger les données dans la base de données à chaque fois. Économisez les ressources système et réduisez le temps de chargement des données.
CommandLineRunner : le paramètre est un tableau de chaînes
@Slf4j @Component public class CommandLineStartupRunner implements CommandLineRunner { @Override public void run(String... args){ log.info("CommandLineRunner传入参数:{}", Arrays.toString(args)); } }
ApplicationRunner : les paramètres sont placés dans ApplicationArguments et les paramètres sont obtenus via getOptionNames(), getOptionValues( ), et getSourceArgs()
@Slf4j @Component public class AppStartupRunner implements ApplicationRunner { @Override public void run(ApplicationArguments args) { log.info("ApplicationRunner参数名称: {}", args.getOptionNames()); log.info("ApplicationRunner参数值: {}", args.getOptionValues("age")); log.info("ApplicationRunner参数: {}", Arrays.toString(args.getSourceArgs())); } }
Cette méthode peut spécifier l'ordre d'exécution. Notez que les deux premiers Beans sont CommandLineRunner et le dernier Bean est ApplicationRunner.
@Configuration public class BeanRunner { @Bean @Order(1) public CommandLineRunner runner1(){ return new CommandLineRunner() { @Override public void run(String... args){ System.out.println("BeanCommandLineRunner run1()" + Arrays.toString(args)); } }; } @Bean @Order(2) public CommandLineRunner runner2(){ return new CommandLineRunner() { @Override public void run(String... args){ System.out.println("BeanCommandLineRunner run2()" + Arrays.toString(args)); } }; } @Bean @Order(3) public ApplicationRunner runner3(){ return new ApplicationRunner() { @Override public void run(ApplicationArguments args){ System.out.println("BeanApplicationRunner run3()" + Arrays.toString(args.getSourceArgs())); } }; } }
Vous pouvez définir l'ordre d'exécution via @Order
Ajoutez les paramètres suivants à la configuration de démarrage d'IDEA Springboot, enregistrez et démarrez l'application
Résultat de sortie du test :
c.z. boot.launch.config .AppStartupRunner : nom du paramètre ApplicationRunner : [nom, âge]
c.z.boot.launch.config.AppStartupRunner : valeur du paramètre ApplicationRunner : [18]
c.z.boot.launch.config.AppStartupRunner : paramètre ApplicationRunner : [-- name=zimug, - -age=18]BeanApplicationRunner run3()[--name=zimug, --age=18]
c.z.b.l.config.CommandLineStartupRunner : Paramètres entrants de CommandLineRunner : [--name=zimug, --age =18]
BeanCommandLineRunner run1()[--name=zimug, --age=18]
e=18]
BeanCommandLineRunner run2()[--name=zimug, --age=18]
Après de nombreux tests , l'auteur a découvert que dans les résultats des tests, cet ordre de priorité a toujours été comme ceci, mais il n'est actuellement pas clair si c'est la norme
La priorité d'exécution d'ApplicationRunner est supérieure à celle de CommandLineRunner
La priorité de Runner s'exécutant dans la forme du Bean est inférieure à l'annotation du composant. La manière d'implémenter l'interface Runner
L'annotation d'ordre ne peut garantir que l'ordre d'exécution du même CommandLineRunner ou ApplicationRunner, et ne peut pas garantir l'ordre entre les classes
L'utilisation principale de CommandLineRunner et d'ApplicationRunner est cohérente, c'est-à-dire qu'ils sont utilisés pour l'exécution de code spécial avant le démarrage de l'application. L'ordre d'exécution d'ApplicationRunner précède CommandLineRunner ; ApplicationRunner encapsule les paramètres dans des objets et fournit des méthodes pour obtenir les noms de paramètres, les valeurs de paramètres, etc., ce qui rend l'opération plus pratique.
C'est un vrai problème que l'auteur a rencontré dans la pratique, c'est-à-dire que j'ai défini plusieurs implémentations de CommandLineRunner. Un problème étrange se pose : Lorsque vous définissez plusieurs implémentations de CommandLineRunner, une ou plusieurs d'entre elles ne s'exécuteront pas.
Analyse : Le code suivant est le code que SpringBootApplication exécutera après le démarrage du projet. Vous pouvez voir que CommandLineRunner ou ApplicationRunner est démarré via un parcours dans le code. En d'autres termes, le CommandLineRunner suivant ne sera exécuté qu'une fois l'exécution du CommandLineRunner précédent terminée, qui est exécutée de manière synchrone.
private void callRunners(ApplicationContext context, ApplicationArguments args) { List<Object> runners = new ArrayList<>(); runners.addAll(context.getBeansOfType(ApplicationRunner.class).values()); runners.addAll(context.getBeansOfType(CommandLineRunner.class).values()); AnnotationAwareOrderComparator.sort(runners); for (Object runner : new LinkedHashSet<>(runners)) { if (runner instanceof ApplicationRunner) { callRunner((ApplicationRunner) runner, args); } if (runner instanceof CommandLineRunner) { callRunner((CommandLineRunner) runner, args); } } }
Ainsi, si une API de blocage synchrone ou une boucle while(true) est appelée dans le corps de la méthode d'exécution d'une implémentation de CommandLineRunner, les autres implémentations après CommandLineRunner dans la traversée ne seront pas exécutées.
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!