[Spring] 스프링 부트 구동 시점에 특정 코드 실행 initData

hyewon jeong·2023년 1월 18일
0

Spring

목록 보기
21/59

백엔드 코드를 테스트 하기위해 포스트맨을 사용하게 되는데 , 그때마다 매번 회원가입을 하는 것 이 불편하다고 생각 되었는데 , 팀원에 의해 알게된 좋은 방법이 있어
공부 겸 추후 필요시 참고하기 위해 정리했습니다.

CommandLineRunner & ApplicationRunner

두가지 방법이 있다.
간단히

CommandLineRunner

CommandLineRunner 인터페이스는 구동 시점에 실행되는 코드가 자바 문자열 아규먼트 배열에 접근해야할 필요가 있는 경우에 사용합니다. 다음과 같이 CommandLineRunner 인터페이스를 구현한 클래스에 @Component 어노테이션을 선언해두면 컴포넌트 스캔이되고 구동 시점에 run 메소드의 코드가 실행됩니다.

ApplicationRunner

ApplicationRunner 인터페이스도 CommandLineRunner 인터페이스와 마찬가지로 구동 시점에 run() 메소드를 실행시키지만 다른 타입의 인자를 받습니다. 단순 인자의 스트링 배열을 포함한 추상화한 ApplicationArguments 타입의 객체가 대신 run() 메소드의 인자로 넘어옵니다.

ApplicationRunner 등록 방법 정리

1. 별도의 클래스에 @Component 붙여서 등록하기

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component
public class DemoApplicationRunner implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("ApplicationRunner Args: " + Arrays.toString(args.getSourceArgs()));
    }

}

2. @Configuration 클래스에 @Bean으로 직접 등록하기

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class ExceptionhandlerExampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(ExceptionhandlerExampleApplication.class, args);
    }

    @Bean
    public ApplicationRunner applicationRunner() {
        return new ApplicationRunner() {
            @Override
            public void run(ApplicationArguments args) throws Exception {
            
            	// 코드 작성
            }
        };
    }
}

3. Lambda를 이용해서 등록하기

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class ExceptionhandlerExampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(ExceptionhandlerExampleApplication.class, args);
    }

    @Bean
    public ApplicationRunner applicationRunner() {
        return args -> {

			// 코드 작성
        };
    }
}

실행 순서

하나의 스프링 부트 애플리케이션에 여러 개의 CommandLineRunner 또는 ApplicationRunner 빈을 등록할 수 있습니다. 러너 간의 실행 순서가 문제가 되는 경우에는 러너 클래스에 @Order 어노테이션으로 실행 순서를 명시해주면 됩니다.

@Order(1)
@Component
public class DemoCommandLineRunner implements CommandLineRunner { ...

@Order(2)
@Component
public class DemoApplicationRunner implements ApplicationRunner { ...
  • 순서를 지정하지 않은 경우 ApplicationRunner가 CommandLineRunner 보다 먼저 실행된다.

먼저 실행되는 이유는 SpringApplication 클래스의 내부를 살펴보면 알 수 있다. callRunners라는 메서드에서 실행 대상을 담는 순서에 차이가 있기 때문에 그렇다. 물론 @Order를 지정했다면 우선순위가 조정된다.

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); // `@Order` 를 선언했다면 정렬된다.
		for (Object runner : new LinkedHashSet<>(runners)) {
			if (runner instanceof ApplicationRunner) {
				callRunner((ApplicationRunner) runner, args);
			}
			if (runner instanceof CommandLineRunner) {
				callRunner((CommandLineRunner) runner, args);
			}
		}
	}

프로젝트 적용

@Component
@RequiredArgsConstructor
public class InitData implements ApplicationRunner {

    private final PasswordEncoder passwordEncoder;
    private final UserRepository userRepository;

    @Override
    public void run(ApplicationArguments args){

        User admin = new User("admin", passwordEncoder.encode("admin"), "admin", "admin",UserRoleEnum.ADMIN);
        User seller = new User("seller", passwordEncoder.encode("seller"), "seller", "seller",UserRoleEnum.SELLER);
        User customer = new User("customer", passwordEncoder.encode("customer"), "customer", "customer",UserRoleEnum.CUSTOMER);
        User customer1 = new User("customer1", passwordEncoder.encode("customer"), "customer", "customer",UserRoleEnum.CUSTOMER);
        userRepository.save(admin);
        userRepository.save(seller);
        userRepository.save(customer);
        userRepository.save(customer1);

    }
}

이렇게 하면 판매자 테스트했다가 고객테스트했다가 할때마다 회원가입 없이 할 수 있어
꿀팁이당 >.<ㅎㅎ

참고
https://atoz-develop.tistory.com/entry/Spring-Boot-ApplicationRunner-%EB%93%B1%EB%A1%9D-%EB%B0%A9%EB%B2%95-%EC%A0%95%EB%A6%AC
https://www.daleseo.com/spring-boot-runners/

profile
개발자꿈나무

0개의 댓글