@Component 은 스프링이 관리하는 객체로 등록해달라는 어노테이션 이다.
-
@Repository
-
@Service
-
@Controller
-
@Configuration
@ComponentScan 은 @Component 에노테이션들을 스캔해 등록하는데, 구동시에 등록하기 떄문에 스캔하여 등록할 Bean 다수라면 구동시간이 걸릴 수 있다. 하지만 이것은 구동시간에만 국한된 이야기다.
-
@SpringBootApplication 에노테이션은 이미 @ComponentScan을 포함한다, 속성으로는 basePackageClasses가 basePackage 속성보다 type-safe 하며, 똑같이 해당 위치에서 스캔하여 하위 패키지 까지 스캔해낸다.
@SpringBootApplication(scanBasePackageClasses = InfeanspringApplication.class)
//@ComponentScan(basePackageClasses = InfeanspringApplication.class)
-
중요한 속성은 IncludeFilters 와 ExcludeFilter 가 있다. 해당 속성은 @Filter 의 배열을 가지며, 이를 이용해 스캔대상에 포함시키거나, 제외시킨다.
@ComponentScan(includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {ControllerAdvice.class}),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {MyService.class})
}
,excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {ExceptionHandler.class}),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {MyRunner.class})
})
@SpringBootApplication(exclude = {Repository.class}, excludeName = {"이름1","이름2"})
AutoConfigurationExcluedFiler 는 스프링 부트가 제공하는 오토 컨피규어 레이션 관련 필터이며, 자동 설정 클래스에 대한 스캔을 제외하는 것으로 보인다.
스프링 5버전으로 부터 지원하는 Functional 한 Bean 등록방법이 있어, 구동타임에 성능을 증가시켜줄 수 있다.
그 전에, 일단 스프링 부트 구동방식은 2가지이다.
-
SpringApplication의 정적 메서드 run( 구동클래스 , args );
-
SpringApplication 객체를 만들어( 매개값은 구동클래스 ) run( args );
SpringApplication.run(InfeanspringApplication.class, args);
SpringApplication app = new SpringApplication(InfeanspringApplication.class);
app.run(args);
이를 이용해 구동 사이에 Funtinal한 Bean등록을 한다.
-
SpringApplication 객체의 addInitializers( ApplicationInitializer ) 메서드를 호출하며 매개값으로
-
ApplicationContextInitializer 의 익명객체를 주어 즉, ApplicationInitializer의 initialize(ApplicationContext) 메서드의 재정의 코드에 ApplicationContext 의 regitserBean( BeanClass ); 를 호출한다.
-
참고로 ApplicationInitializer 는 <> 제네릭에 선언된 ApplicationContext 를 주입받을 수 있게 해준다.
SpringApplication.run(InfeanspringApplication.class, args);
app.addInitializers(new ApplicationContextInitializer<GenericApplicationContext>() {
@Override
public void initialize(GenericApplicationContext ctx) {
ctx.registerBean(MyService.class);
}
})
ApplicationContextInitializer 익명객체를 만들때 해당 인터페이스는 함수형인터페이스 이므로 lamda 를 이용할 수 있다.
-
장점으로는 조건문이나 흐름제어를 이용하거나 추가적인 코드를 Bean 객체 등록 시에 설정할수 있다는 점.
-
ApplicationContext 객체의 registerBean()은 매개값으로 Supplier<BeanClass> 를 주어 해당 빈의 설정을 만들어내어 리턴해줄 수도 있다.
-
그냥 빈을 만들때는 ctx.registerBean( BeanClass ) ,
-
빈을 만들때 주입이나 설정이 필요한 경우 ctx.registerBean( BeanClass , new Suplier(get 메서드 재정의) ); 를 사용하면 될 듯 하다. Suplier의 get 메서드로 설정한 빈을 받아 해당 클래스의 빈을 등록해주는 방법이다.
SpringApplication app = new SprinApplication(InfeanspringApplication.class);
app.addInitializers((ApplicationContextInitializer<GenericApplicationContext>) ctx
-> {ctx.registerBean(MyService.class);
ctx.registerBean(ApplicationRunner.class, new Supplier<ApplicationRunner>() {
@Override
public ApplicationRunner get() {
return new ApplicationRunner() {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("Functional Bean Definition !!");
}
};
}
});
});
app.run(args);
Supplier<>의 get() 도 함수형 인터페이스의 메서드 이므로 lamda 로 표현할 수 있다.
SpringApplication app = new SprinApplication(InfeanspringApplication.class);
app.addInitializers(
(ApplicationContextInitializer<GenericApplicationContext>) ctx ->
{
ctx.registerBean(MyService.class);
ctx.registerBean(ApplicationRunner.class,
(Supplier<ApplicationRunner>) () ->
runner1
-> System.out.println("Initialize Bean Definition!!"));
});
app.run(args);
- SpringApplication 객체를 구동클래스를 매개 값으로 생성
- .addInitializer( ApplicationInitializer ) 메서드로 스프링 컨테이너 초기화
- ApplicationContextInitializer 객체의 .registerBean( BeanClass , [Supplier( BeanClass )]) 메서드로 빈 등록
- 빈 등록 과정에서 SpringBoot 구동후 실행되는 ApplicationRunner 클래스의 익명객체를 등록,
- 마지막 출력문은 ApplicationRunner의 run() 메서드의 재정의 문.
BeanFactoryPostProcessor를 구현한 ConfigrationClassPostPocessor에 의해 함수적 Bean 등록이 적용된다.
-
다른 모든 빈들을 만들기 전에 BeanFactoryPostProcessor 구현체들을 적용시킨다.
-
즉, 다른 빈들을 등록하기 전에 ComponentScan 을 하여 해당 Bean을 등록한다.
@Bean 등 직접적으로 스프링 빈을 등록하는 법을 대처할 때에는 Functional한 빈 등록 방법이 좋겠으나, @Component 스캔의 대안으로는 적합하지 않다.
'springframework' 카테고리의 다른 글
Junit (0) | 2020.08.17 |
---|---|
인텔리J 기반 스프링 프로젝트 생성 (0) | 2020.08.12 |
스프링 프레임 워크 핵심 기술 - 2.@Autowired (0) | 2020.08.11 |
스프링 프레임 워크 핵심 기술 - 1.Ioc컨테이너와 Bean (0) | 2020.08.11 |
ClassPathResource 객체와 FileSystemResource 객체 (0) | 2020.08.10 |