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

코딩먹는하마님의 프로필 이미지
코딩먹는하마

작성한 질문수

스프링 핵심 원리 - 기본편

필터

내부 클래스 static 질문입니다.

작성

·

503

1

@Configuration
    @ComponentScan(
            includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = MyIncludeComponent.class),
            excludeFilters= @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = MyExIncludeComponent.class)
    )

           class ComponentFilterAppConfig{

    }
}

이 코드 static class ComponentFilterAppConfig{ }

에서 static 이 있는 이유가 궁금하여 빼서 돌려보니

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'componentFilterAppConfigTest.ComponentFilterAppConfig': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'hello.core.scan.filter.ComponentFilterAppConfigTest' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

이런 오류가 나왔습니다.

구글링을 해보니 제생각에는CommponentFilterAppConfigTest.class에서 빈을 찾지 못하여 발생한 것 같은데 보통 어노테이션을 지정하지 않으면 이런 오류가 나온다고 하더군요

https://sas-study.tistory.com/385

하지만 저는 단지 static 만 뺏을 뿐인데 이런 오류가 왜 나는지 궁금했습니다.

마우스를 올려보니

Inner class 'ComponentFilterAppConfig' may be 'static'

이런 글이 있었습니다.

그래서 찾아보니

https://siyoon210.tistory.com/141

'외부 참조'로 인한 단점때문에 내부 클래스는 가능한 static으로 만들어야 합니다. 라고 하고

'외부 참조'로 인한 2가지 단점은아래 와 같다고 하더군요

  1. 참조값을 담아야 하기 때문에, 인스턴스 생성시 시간적, 공간적으로 성능이 낮아진다.

  2. 외부 인스턴스에 대한 참조가 존재하기 때문에, 가비지 컬렉션이 인스턴스 수거를 하지 못하여 메모리 누수가 생길 수 있다.

그러면 종합에서 생각한게 빈을 찾지 못하는건 외부참조가 가능해서인가? 라는 의문이 들었습니다.

그리고 정확한 이유가 궁금해졌습니다.

<전체 코드>

public class ComponentFilterAppConfigTest {

    @Test
    void filterScan(){
        ApplicationContext ac = new AnnotationConfigApplicationContext(ComponentFilterAppConfig.class);
        BeanA beanA = ac.getBean("beanA", BeanA.class);
        assertThat(beanA).isNotNull();

        assertThrows(
                NoSuchBeanDefinitionException.class,
                () -> ac.getBean("beanB", BeanB.class));

    }
    @Configuration
    @ComponentScan(
            includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = MyIncludeComponent.class),
            excludeFilters= @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = MyExIncludeComponent.class)
    )

           static class ComponentFilterAppConfig{

    }
}

정리하자면 이 코드에서

static class ComponentFilterAppConfig{ } 가 static 이 없으면 왜 오류가 나는지 궁금합니다.

 

답변 1

1

안녕하세요. 박희재님, 공식 서포터즈 David입니다.

아래 글 답변을 참고해 주세요.

https://www.inflearn.com/questions/257297

감사합니다.

답변에서 inner class에 static이 없으면

outer class의 객체를 통해서만 inner class에 접근할 수 있습니다 라는 걸 보고

ComponentFilterAppConfig cp = new ComponentFilterAppConfig();
ApplicationContext ac = new AnnotationConfigApplicationContext(cp.ComponentFilterAppConfig.class);

(ComponentFilterAppConfig: outer class, ComponentFilterAppConfig:inner class)

위에 코드처럼 해봤더니 안되서 외부클래스도 스프링 컨테이너에 생성해야 된다는 건가?해서 (외부 클래스를 생성해야 내부 클래스를 생성할 수 있으니까(????))

ApplicationContext ac = new AnnotationConfigApplicationContext(ComponentFilterAppConfigTest.class,ComponentFilterAppConfig.class);

위에 코드처럼 해보니 잘돌아갔습니다.

  1. 처음한 코드가 왜 안되는지 궁금합니다. 저는 outer class의 객체를 통해 inner class에 접근했다고 생각했는데 말이죠...

  2. 두번째 코드는 해당 컨테이너에 동시에 외부클래스, 내부 클래스 를 스프링 빈으로 자동 등록하는 건데 왜 되는 건지 모르겠습니다. 외부클래스를 등록하면 자동으로 하위 클래스인 내부 클래스가 등록 되어서 되는 건가요?? 하지만

    ApplicationContext ac = new AnnotationConfigApplicationContext(ComponentFilterAppConfig.class);

처럼 외부클래스만 넣으면 BeanA beanA = ac.getBean("beanA", BeanA.class); 여기서 getBean이 작동을 못하더라구요

질문이 많아서 죄송합니다...

답변해주시면 정말 감사하겠습니다.

코딩먹는하마님의 프로필 이미지
코딩먹는하마

작성한 질문수

질문하기