[Springboot] 23. SpringApplication #3 Web Environment

2022. 10. 13. 16:10JAVA/Spring

1. Web Environment

SpringApplication은 사용자를 대신하여 ApplicationContext를 생성하려고 합니다. 이때 WebApplicationType에 따라서 ApplicationContext의 타입이 달라집니다.

 

WebApplicationType의 종류

  • WebApplicationType.NONE : 웹 응용 프로그램으로 실행되지 않아야 하며, 내장된 웹 서버를 시작하지 않아야 합니다.
  • WebApplicationType.REACTIVE : 반응형 웹 응용 프로그램으로 실행. 내장된 반응형 웹 서버를 시작해야 한다.
  • WebApplicationType.SERVLET : 서블릿 기반 웹 응용 프로그램으로 실행. 내장된 서블릿 웹 서버를 시작해야 한다.
  • Spring Web MVC가 들어있으면 SERVLET으로 동작, Spring Web Flux가 들어있다면 REACTIVE로 동작합니다. 둘 다 들어있는 경우 SERVLET으로 동작합니다.

 

WebApplicationType 결정 순서

  1. Spring MVC :  WebApplicationType은 AnnotationConfigServletWebServerApplicationContext 타입입니다.
  2. Spring WebFlux : WebApplicationType은 AnnotationConfigReactiveWebServerApplicationContext 타입입니다.
  3. 그 외의 경우 :  WebApplicationType은 AnnotationConfigApplicationContext 타입입니다.

 

WebApplicationType 확인

1. 기본적인 SpringApplication을 실행합니다. 

@SpringBootApplication
public class SpringbootUtilizationApplication {
    public static void main(String[] args) {
        new SpringApplication(SpringbootUtilizationApplication.class).run(args);
    }
}
@Component
public class AppRunner implements ApplicationRunner {
    @Autowired
    private ApplicationContext ctx;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("ctx : " + ctx);
    }
}

 

2. ApplicationContext 인스턴스의 타입을 확인합니다.

ctx : org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@53f6fd09, started on Thu Oct 13 14:56:17 KST 2022

ApplicationContext 인스턴스의 타입이 AnnotationConfigServletWebServerApplicationContext이므로 기본적인 WebApplicationType은 SERVLET인것을 확인할 수 있습니다.

 

WebApplicationType 설정 (setWebApplicationType)

1. SpringApplication 인스턴스를 생성하고 setWebApplicationType을 호출하여 웹 애플리케이션 타입을 설정합니다.

@SpringBootApplication
public class SpringbootUtilizationApplication {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(SpringbootUtilizationApplication.class);
        app.setWebApplicationType(WebApplicationType.NONE);
        app.run(args);
    }
}

 

2. SpringApplication을 실행하여 ApplicationContext 타입을 확인합니다.

ctx : org.springframework.context.annotation.AnnotationConfigApplicationContext@673be18f, started on Thu Oct 13 15:01:36 KST 2022

 

2. 애플리케이션 매개변수들에 접근하기(Accessing Application Arguments)

만약 SpringApplication.run(...) 메서드에 전달할 애플리케이션 매개변수에 접근해야 한다면 "org.springframework.boot.ApplicationArguments" 빈을 주입하여 참조할 수 있습니다. ApplicationArguments 인터페이스는 옵션과 옵션이 아닌 매개변수를 추출하는것 뿐만 아니라 String 타입의 배열 매개변수들에게도 접근하는 것을 제공합니다.

 

ApplicationArguments 접근하기

1. ApplicationArguments에 접근하기 위한 빈 생성

@Component
public class ApplicationArgumentListener {
    public ApplicationArgumentListener(ApplicationArguments arguments) {
        System.out.println("foo : " + arguments.containsOption("foo"));
        System.out.println("bar : " + arguments.containsOption("bar"));
    }
}

위와 같이 어떤 빈에 생성자가 1개이고 그 생성자의 파라미터가 빈일 경우 자동주입됩니다.

@SpringBootApplication
public class SpringbootUtilizationApplication {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(SpringbootUtilizationApplication.class);
        app.run(args);
    }
}

 

2. SpringApplication을 실행할때 다음과 같은 옵션을 넣고 실행합니다.

  • foo : VM 옵션
  • bar : 애플리케이션 파라미터 옵션
$ java -jar springboot_utilization-0.0.1-SNAPSHOT.jar -Dfoo --bar

3. 실행결과는 ApplicationArguments는 VM 옵션을 받을 수 없으므로 false가 나오고 bar는 받을 수 있으므로 true가 나오게 됩니다.

 

 

3. CommandLineRunner 또는 ApplicationRunner 사용하기

만약 SpringApplication이 시작된 후 어떤 코드를 수행시키고 싶다면 CommandLineRunner 또는 ApplicationRunner 인터페이스를 사용하는 것을 추천합니다. 두 인터페이스 모두 run 메서드를 제공하고 같은 방식으로 동작합니다.

 

CommandLineRunner, AppcationRunner 비교

  • CommandLineRunner 인터페이스는 run 메서드의 파라미터가 문자열 배열입니다. 이 문자열 배열이 애플리케이션 파라미터를 문자열 배열로 저장한 것입니다.
  • ApplicationRunner 인터페이스는 run 메서드의 파라미터 타입이 ApplicationArguments 인터페이스입니다. 따라서 좀더 많은 기능을 사용할 수 있습니다.

 

ApplicationRunner 인터페이스 구현

1. ApplicationRunner 인터페이스를 구현할 클래스 빈을 정의

@Component
public class AppRunner implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("bar="+args.getOptionValues("bar"));
    }
}

 

2. 다음과 같이 파라미터 옵션을 설정하고 애플리케이션을 실행합니다.

  • 파라미터 인수 bar = hello로 설정하였습니다.

3. 실행결과를 확인합니다.

 

@Order 애노테이션을 적용하여 순서를 정하기

만약 ApplicationRunner를 구현한 클래스간에 실행순서를 정해야한다면 다음과 같이 @Order 애노테이션을 설정하여 실행 순서를 정할 수 있습니다.

 

1. ApplicationRunner 인터페이스를 구현한 Runner 클래스 두개를 정의합니다.

@Component
@Order(1)
public class AppRunner implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("첫번째 Runner");
    }
}
@Component
@Order(2)
public class AppRunner2 implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("두번째 Runner");
    }
}

 

2. SpringApplication을 실행하여 결과를 확인합니다.

 

 

References

https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/boot-features-spring-application.html#boot-features-web-environment
[인프런] 스프링 부트 개념과 활용
[스프링 부트 개념과 활용] SpringApplication 2부