인프런 커뮤니티 질문&답변

고규천님의 프로필 이미지
고규천

작성한 질문수

토비의 스프링 부트 - 이해와 원리

프로퍼티 빈의 후처리기 도입

@Import 로 Bean을 등록해야하는 기준이 뭔지 궁금합니다.

작성

·

157

0

@Import(ServerProperties.class)
public class TomcatWebServerConfig {
    @Bean("tomcatWebServerFactory")
    @ConditionalOnMissingBean
@Import(MyAutoConfigImportSelector.class)
public @interface EnableMyAutoConfiguration {
}

두 케이스의 경우 @Import를 통해 클래스를 Bean으로 등록하고 있는데 @Bean 이나 @Component로 안되는 이유가 있을까요?

@Component는 개발자가 컨트롤 가능한 클래스의 경우에 사용이 가능하고 @Bean은 그렇지 못한 경우에 사용하는 걸로 이해하고 있는데 Serverproperties 클래스는 직접 작성한 코드인데도 @Import가 아니면 Bean 등록이 안되어서 질문을 드립니다.

답변 2

0

강의자료로 사용했던 notion 은 공유 안되나요?

토비님의 프로필 이미지
토비
지식공유자

PDF 형식으로 강의자료 다운로드에서 받으실 수 있습니다.

0

토비님의 프로필 이미지
토비
지식공유자

ServerProperties가 @Import가 아니면 빈으로 등록이 안 된다는 건 어떻게 확인해보신 것인가요?


어느 단계에서 나오는 코드인지 알려주시면 좋겠네요. 제가 찾아본 예제 코드에는 예를 들어 다음과 같이 @Bean을 이용해서 등록하기도 합니다. @Bean은 직접 만든 클래스가 아닌 경우에도 사용할 수 있지만 초기화와 관련된 부가적인 작업이 있는 경우에도 필요합니다. 다음 경우처럼요.

 

@MyAutoConfiguration
public class ServerPropertiesConfig {
    @Bean
    public ServerProperties serverProperties(Environment environment) {
        return Binder.get(environment).bind("", ServerProperties.class).get();
    }
}


@Component는 생성자에 다른 빈을 주입하는 정도로 간단히 빈 오브젝트를 초기화할 수 있을 때 사용합니다. Properties와 같은 빈에는 그다지 적합하지 않아보이네요.

 

@Import는 보통 임포트하는 클래스와 임포트 되는 클래스가 긴밀한 관계에 있을 때 사용합니다. 보여주신 코드처럼 톰캣 서버를 준비하는 구성정보 클래스와 서버 프로퍼티는 항상 같이 다녀야하죠. 그래서 @Import를 쓴 예가 등장했을 것입니다.

 

혹시 원하는 방식으로 빈을 등록하는게 안 되는 경우가 있다면(초기화 작업을 해야하는데 그걸 못해서 에러가 나는게 아니라면) 해당 프로젝트를 GitHub에 올리고 공유해주시면 제가 살펴보겠습니다.

 

고규천님의 프로필 이미지
고규천
질문자

 

@MyAutoConfiguration // Included @Component
public class ServerProperties  {
....
}

이런 형태로 하면 Componet Scan이 안되는 거 같습니다.

그래서 아래 propertyPostProcessor 도 동작하지 않구요.

@MyAutoConfiguration
public class PropertyPostProcessConfig {
    @Bean BeanPostProcessor propertyPostProcessor(Environment env) {
        return new BeanPostProcessor() {
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                MyConfigurationProperties annotation = AnnotationUtils.findAnnotation(bean.getClass(), MyConfigurationProperties.class);


                if (annotation == null) return bean;
                return Binder.get(env).bindOrCreate("", bean.getClass());
            }
        };
    }
}

@Component 의 개념이 확실치 그런건지? @Import가 아니면 안되는 것일까요?

토비님의 프로필 이미지
토비
지식공유자

컴포넌트 스캔은 전체 프로젝트의 모든 클래스가 대상이 아니고 @ComponentScan이 붙은 클래스가 있는 패키지와 그 아래 패키지의 클래스만 대상입니다. 따라서 프로젝트내 다른 패키지에 있는 ServerProperties등은 스캔하지 않습니다.

일반적으로 자동구성(AutoConfiguration) 클래스와 거기서 사용하는 프로퍼티 클래스등은 스캔 대상으로 하지 않는게 원칙입니다. 기술적으로 불가능한 것은 아니나 imports 파일을 이용한 자동구성 메카니즘을 깨뜨리게 되고, 스프링 부트 답지 않은 방식이 되는 거죠.

그리고 프로퍼티 클래스에는 AutoConfiguration 같은 애노테이션을 붙이지 않습니다.

애플리케이션의 기능을 담당하는 컨트롤러, 서비스 등에서 사용하는 @Component와 @ComponentScan은 자동구성에서 쓰지 않으셔야 합니다. 억지로 적용할 수는 있겠으나 점점 이상한 결과가 나오게 될 수 있을 겁니다.

어쨌든 기대한대로 동작하지 않는 코드라면 전체 프로젝트를 공유해주세요. 그러면 보다 확실한 이유를 설명드릴 수 있습니다.

고규천님의 프로필 이미지
고규천
질문자

추가 설명해주셔서 이해되었습니다 ^^ 참고 리파지토리 남겨드립니다
https://github.com/k2c-repo/test-spring-boot.git
dev 브랜치 입니다.

감사합니다~

고규천님의 프로필 이미지
고규천

작성한 질문수

질문하기