우리는 프로그램을 만들면서 필요에 따라 빈을 등록한다.
@Component, @Service, @Repository, @Controller, @Configuration 등등이 있다.
그렇다면 우리가 등록한 것들을 어떻게 찾아서 빈으로 등록을 해줄까?
우리가 등록하고 싶다고 설정한 빈들을 찾아서 빈으로 만들어 주는 친구가 바로 @ComponentScan 이다.
@ComponentScan은 해당 애너테이션이 작성된 패키지 이하의 클래스들을 순회하며 빈으로 등록될 객체들을 탐색한다.
아래와 같이 기준이 될 패키지를 지정할 수도 있다.
@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig {
// ...
}
SpringBoot를 사용한다면 우리가 따로 설정하지 않는이상 @ComponentScan을 보기가 힘들다.
그 이유는 @SpringBootApplication이 @ComponentScan을 들고있기 때문이다.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// ...
}
위에서 볼 수 있듯이 포함시키지 않을 것들을 따로 설정을 할 수 있다.
혹은 따로 스캔하지 않을 부분에 @IgnoreDuringScan을 붙여서 처리할 수도 있다.
@Service
@IgnoreDuringScan
public class ActorService {
// ..
}
이와 반대로 포함 시킬것들을 설정하는 방법도 있으며 패턴적용까지 가능하다.
ComponentScan(basePackages = "org.example",
includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"),
excludeFilters = @Filter(Repository.class))
public class AppConfig {
...
}
어차피 등록될 부분은 등록될텐데 includeFilter를 왜 적용하는지 필요성을 아직 느끼지는 못했다.
그래서 여러가지 테스트를 해보았다.
exclude를 패턴으로 적용하고 거기서 걸리는 부분을 include로 포함시키지 않을까? 라고 생각해보았는데 아래와 같이 실행하니 되지 않았다.
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class),
@Filter(type = FilterType.REGEX, pattern = ".*[vice]")},
includeFilters = {@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = LineService.class)})
public class HelloApplication {
public static void main(String[] args) {
SpringApplication.run(HelloApplication.class, args);
}
}
@Test
void componentScan() {
ApplicationContext context = getApplicationContext();
LineService service = context.getBean("lineService", LineService.class);
assertThat(service).isNotNull();
}
해당 패키지가 아닌 다른 패키지에 있는 친구들을 등록할 수 있는지 테스트를 해보았는데 실패하였다.
public class TestService {
// 다른 패키지의 서비스
}
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class),},
includeFilters = {@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = TestService.class)})
public class HelloApplication {
public static void main(String[] args) {
SpringApplication.run(HelloApplication.class, args);
}
}
컴포넌트가 붙어있지 않아도 되는지 테스트를 해보았다.
public class LineService {
}
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class),},
includeFilters = {@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = LineService.class)})
public class HelloApplication {
public static void main(String[] args) {
SpringApplication.run(HelloApplication.class, args);
}
}
등록이 잘 되었다.
해당 패키지에서 지정한 친구들만 등록된다.
-> 포함되어 있는 모든 빈들이 등록된다.
'프레임워크 > Spring' 카테고리의 다른 글
[Spring] RestDocs와 Swagger (0) | 2021.08.24 |
---|---|
[Spring] RestTemplate와 webClient (0) | 2021.08.23 |
[Spring] @SpringBootApplication이란 무엇인가? (0) | 2021.06.23 |
[Spring] SimpleJdbcInsert란 무엇인가? (0) | 2021.06.22 |
[Spring] NamedParameterJdbcTemplate 이란 무엇인가? (0) | 2021.06.22 |
댓글