728x90
1. bootApplication 설정
- configFile : 수동 bean 등록 file
- testDataInit : 초기 test file
- @EventListener(ApplicationReadyEvent.class)
- @PostConstruct
- bootApplication
- @Import
- @SpringBootApplication(scanBasePackages = "")
- app 내부 @Bean, @Profile("")
- application.properties
- main : local
- test : test
- 해당 파일 code
package hello.itemservice.config;
@Configuration
public class MemoryConfig {
@Bean
public ItemService itemService() { return new ItemServiceV1(itemRepository()); } // bean 등록 + 의존관계 주입
@Bean
public ItemRepository itemRepository() { return new MemoryItemRepository(); } // bean 등록
}
package hello.itemservice;
@Slf4j
@RequiredArgsConstructor
public class TestDataInit {
private final ItemRepository itemRepository;
/**
* 확인용 초기 데이터 추가
*/
@EventListener(ApplicationReadyEvent.class)
public void initData() {
log.info("test data init");
itemRepository.save(new Item("itemA", 10000, 10));
itemRepository.save(new Item("itemB", 20000, 20));
}
}
package hello.itemservice;
// 현재 componentScan의 영역이 web 이하이므로 @Import로 수동 bean 등록 내용을 받아야 springContainer가 받아와야하는 bean을 받아올 수 있다.
@Import(MemoryConfig.class)
@SpringBootApplication(scanBasePackages = "hello.itemservice.web")
public class ItemServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ItemServiceApplication.class, args); //web 내부 @Component만 bean으로 등록한다는 의미
}
@Bean // 수동 bean 등록 방법 중 직접 등록 방법
@Profile("local") // application.properties의 설정 중 local 환경일 경우 @Bean으로 등록
public TestDataInit testDataInit(ItemRepository itemRepository) { // 의존관계 주입도 들어감 - ItemRepository
return new TestDataInit(itemRepository);
}
}
# main/resources/application.properties
# 해당 설정이 없을 경우, profiles는 default로 지정된다.
spring.profiles.active=local
# test/resources/application.properties
# test package에 지정한 profiles로 boot test 실행시, 해당 profiles가 우선시 된다.
#설정이 없으면 main profiles를 따른다.
spring.profiles.active=test
1.1. ConfigFile
package hello.itemservice.config;
@Configuration
public class MemoryConfig {
@Bean
public ItemService itemService() { return new ItemServiceV1(itemRepository()); } // bean 등록 + 의존관계 주입
@Bean
public ItemRepository itemRepository() { return new MemoryItemRepository(); } // bean 등록
}
- @springBootApplication의 componentScan 범위가 Controller pacakge로 한정이 되어있어서 수동 config파일을 통해서 @Import @Bean 등록을 수행
1.2. TestDataInit
package hello.itemservice;
@Slf4j
@RequiredArgsConstructor
public class TestDataInit {
private final ItemRepository itemRepository;
@EventListener(ApplicationReadyEvent.class)
public void initData() {
log.info("test data init");
itemRepository.save(new Item("itemA", 10000, 10));
itemRepository.save(new Item("itemB", 20000, 20));
}
}
- @EventListener(ApplicationReadyEvent.class)
- AOP를 포함한 spring container가 완전히 초기화를 다 끝내고, 실행 준비가 됬을 경우 해당 어노테이션이 붙은 메서드가 호출
- AOP설정 초기화는 @Transactional 읽고 proxy 객체 만드는 과정을 의미
- @PostConstruct
- @EventListener(ApplicationReadyEvent.class)와 유사한 기능이지만, AOP 같은 부분이 아직 다 처리되지 않은 시점에 호출될 수 있기 때문에, 간혹 문제가 발생
1.3. SpringBootApplication
package hello.itemservice;
// 현재 componentScan의 영역이 web 이하이므로 @Import로 수동 bean 등록 내용을 받아야 springContainer가 받아와야하는 bean을 받아올 수 있다.
@Import(MemoryConfig.class)
@SpringBootApplication(scanBasePackages = "hello.itemservice.web")
public class ItemServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ItemServiceApplication.class, args); //web 내부 @Component만 bean으로 등록한다는 의미
}
@Bean // 수동 bean 등록 방법 중 직접 등록 방법
@Profile("local") // application.properties의 설정 중 local 환경일 경우 @Bean으로 등록
public TestDataInit testDataInit(ItemRepository itemRepository) { // 의존관계 주입도 들어감 - ItemRepository
return new TestDataInit(itemRepository);
}
}
- @SpringBootApplication(scanBasePackages = "hello.itemservice.web")
- scanBasePackages : 해당 pacakge부터 componentScan을 해서 bean을 등록하겠다는 의미
- scanBasePackages : 해당 pacakge부터 componentScan을 해서 bean을 등록하겠다는 의미
- @Import("CLASS")
- 해당 class를 설정파일로 사용한다는 뜻
- @Configuration, @Bean으로 수동 주입하는 방법과 동일한 역할
- @Import하면 해당 class를 빈으로 등록해주어서 수동 주입 할 필요없이 깔끔하게 처리된다.
- @Bean
- Application 에 직접적으로 @bean 등록하는 직접 수동 방법
- @Configuration 없이 (@SpringBootApplication 내부에 있으므로) 자동으로 springContainer에 bean 등록 됨
- bean 등록 방법 3가지
- 자동 등록 - @ComponentScan - @Controller, @Service, @Repository - @Autowired
- 수동 등록 (Config file 이용) - @Configuration @Bean
- 수동 등록 (boot file에 직접 등록) - @Bean
- @Profile
- spring은 로딩 시점에 application.properties의 spring.profiles.active 을 읽어서 프로필로 사용
- @Profile("local")이 설정된 method나 설정, class는 application.properties가 local인 경우 작동
2. Profile
# main/resources/application.properties
# 해당 설정이 없을 경우, profiles는 default로 지정된다.
spring.profiles.active=local
# test/resources/application.properties
# test package에 지정한 profiles로 boot test 실행시, 해당 profiles가 우선시 된다.
#설정이 없으면 main profiles를 따른다.
spring.profiles.active=test
- Profile
- application.properties의 spring.profiles.active = "" 로 profile 지정이 가능
- 따로 지정을 하지 않을 시, profile은 (default)로 설정
- 관습적 분류 : dev, local, prod, test(test패키지에서 사용)
- profile별 사용 방식
- @profile
- application-{profile}.properties || application-{profile}.yml
- 동작 방식
- 공통설정은 application.properties 에서 수행
- 이후 profilte 지정 시,
1) 해당 application-{profile}.yml 설정 내용 수행
2) @Profile("{profile}")에 부합한 method 수행 - 단, 중복 코드 발생시, 우선권은 application.properties에서 지정한 profile 파일의 설정이 우선권을 가진다.
= profile설정으로 code를 덮어씌운다.
- 공통설정은 application.properties 에서 수행
- test package의 경우
- test package 내부에 resources/application.properties를 생성 가능
- test package에 application.properties 파일 자체가 없는 경우에는 main/resources/application.properties를 따름
- test package에 applcation.properties가 생기는 순간 부터, test file은 application.properties에 profiles의 존재 유무에 관계없이 해당 application.properties를 따른다.
- main/resources/application.properties와 test/resources/application.properties에 profile 설정을 안해서 둘다 default를 가지더라도 각각 다른 default임을 헷갈리지 말자
- test package 내부에 resources/application.properties를 생성 가능
- 참고 doc
https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.profiles