일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- kafkastream
- play framework
- Elk
- spring-cloud-stream
- aws
- statestore
- RabbitMQ
- gradle
- Kafka
- 한빛미디어
- springboot
- kafkastreams
- scala 2.10
- schema registry
- 플레이 프레임워크
- Slick
- Spring
- coursera
- confluent
- spring-kafka
- spring-batch
- avo
- kafka interactive query
- 카프카
- kafka streams
- Elasticsearch
- reactive
- enablekafkastreams
- scala
- Logstash
- Today
- Total
b
Spring Boot 가 실행될 때의 메소드를 실행하는 여러가지 방법과 Started ... 로깅의 위치 본문
오래된 배치를 마이그레이션하고 있다. SpringBatch 를 쓰지 않고 여러개의 SpringBootApplication 을 하나의 프로젝트에 만들어
manifest {
attributes(
'Main-Class': 'org.springframework.boot.loader.PropertiesLauncher'
)
}
PropertiesLauncher를 이용해 java -Dloader.main=BatchName -jar jarName.jar 이렇게 실행하고 있다.
이렇게 실행하면 배치Job 에 해당하는 Class를 실행하기 위해서는 @PostConstruct가 가장 간편하고 요즘 개발에게 익숙한 방법이다.
SpringBatch는 JobLauncherCommandLineRunner 를 이용해서 Job을 수행해주지만,
SpringBoot Application은 여러가지 방법이 있으므로, 그 중 하나인 @PostConstruct를 이용해서 배치 메인 로직이 수행되게 하였다.
이렇게 실행해보면 아래처럼, @PostConstruct 에 해당하는 부분이 모두 실행되고 나서야, Application 이 시작되었다고 로깅이 남는다.
2020-04-28 09:18:28.036 WARN 72741 --- [ main] o.m.s.mapper.ClassPathMapperScanner : No MyBatis mapper was found in '[com.elevenst.push.batch.job.duplicate_msg_delete]' package. Please check your configuration.
Main
2020-04-28 09:18:28.643 INFO 72741 --- [ main] e.p.b.j.d.DuplicateMessageDeleteBatchApp : Started DuplicateMessageDeleteBatchApp in 1.316 seconds (JVM running for 1.608)
로그를 어느 단계에서 찍길래 @PostConstruct 실행 이후에 저런 로그가 남는 것일까?
"Started " 이라는 문자열을 찾아서 검색해보면 Info Level 일 경우에 https://git.io/JfqNE 부분에서 StringBuilder를 이용해서 로그가 찍히는 걸 볼 수 있다.
Intellij hierarchy 기능을 이용해서 누가 호출했는지를 따라가보면 아래와 같은 로직을 볼 수 있다.
로그를 찍는 바로 아래 부분에 listeners 를 이용할 수 있을까 봤더니, SpringApplicationRunListeners class 는 접근자도 없이, 재사용을 위한 클래스가 아니다 https://git.io/JfqNi
물론 같은 패키징안에 클래스를 만들어 extends 할 수는 있지만 그렇게까지 할 이유는 없다. 하지만 이 클래스 안에서는 SpringApplicationRunListener 라는 인터페이스를 member로 가지고 메소드를 위임해서 호출 하는 것을 볼 수 있다. 그리고 그 유일한 구현체는 그 유명한 EventPublishingRunListener https://git.io/JfqNj
사족이지만 그 다음에 위치한 callRunners 를 보면, ApplicationRunner 인터페이스를 추적해서 먼저 실행 하고 그 다음 CommandLineRunner 를 실행 한다. 이 순서는 처음 알았네.
결론적으로는 @PostConstruct보다는 listeners.running(context) 에서 수행 될 수 있는 형식이 더 올바른 것 같다.
// @PostConstruct 보다는
@EventListener(ApplicationReadyEvent.class)
public void run() {
System.out.println("Main");
}
--output--
2020-04-28 09:17:42.874 INFO 72718 --- [ main] e.p.b.j.d.DuplicateMessageDeleteBatchApp : Started DuplicateMessageDeleteBatchApp in 1.607 seconds (JVM running for 1.974)
Main
한 줄 요약 : Spring Boot Application 에서 Context가 전체 로딩된 이후에 실행하려면 @PostConstruct 보다는 @EventListener or ApplicationListener<ApplicationReadyEvent> 를 쓰자.