Spring Framework

SpringApplicationRunner란? (+ 동작과정)

Junuuu 2023. 9. 8. 00:01
반응형

개요

Spring Boot를 실행했을 때 매번 특정 코드를 호출하는 방법에 대해 알아보다가 알게 된 Spring ApplicationRunner에 대해서 알아보고자 합니다.

 

 

ApplicationRunner

@FunctionalInterface
public interface ApplicationRunner {

	/**
	 * Callback used to run the bean.
	 * @param args incoming application arguments
	 * @throws Exception on error
	 */
	void run(ApplicationArguments args) throws Exception;

}

 

Bean이 SpringApplication 내에 포함될 때 실행되어야 함을 나타내는 데 사용되는 인터페이스입니다.

동일한 애플리케이션 내에서 여러 ApplicationRunner 빈을 정의해서 사용할 수 있으며 @Order 어노테이션을 사용하여 순서를 지정할 수 있습니다.

 

ApplicationRunner 활용해보기

@Component
@Order(1)
class FirstApplicationRunner(): ApplicationRunner{
	override fun run(args: ApplicationArguments?) {
		println("first")
	}
}

@Component
@Order(2)
class SecondApplicationRunner(): ApplicationRunner{
	override fun run(args: ApplicationArguments?) {
		println("second")
	}
}

//결과
first
second

@Component를 활용해 빈으로 등록하고 @Order를 활용하여 순서를 지정하여 Spring Boot가 기동 될 때 정해진 코드를 실행할 수 있습니다.

 

ApplicationRunner의 동작과정

SpringApplication 클래스

public ConfigurableApplicationContext run(String... args) {
	... 중략
    callRunners(context, applicationArguments);
}

 SpringApplication 클래스의 run 메서드 내부에서 callRunners를 호출합니다.

 

callRunner 메서드

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 applicationRunner) {
				callRunner(applicationRunner, args);
			}
			if (runner instanceof CommandLineRunner commandLineRunner) {
				callRunner(commandLineRunner, args);
			}
		}
	}

 

callRunners 메서드를 보면 ApplicationRunner 클래스를 conext에서 가져와 runners List에 추가합니다.

이후 반복문을 통하여 callRunner 메서드를 호출합니다.

 

callRunner 메서드

private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
		try {
			(runner).run(args);
		}
		catch (Exception ex) {
			throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
		}
	}

callRunner 메서드에서는 실제로 ApplicationRunner 인터페이스를 호출하여 run 메서드를 실행시킵니다.

만약 예외가 발생하는 경우에는 Failed to execute ApplicationRunner 메시지와 함께 IllegalStateException을 반환합니다.