[스프링 3.0] 스프링 bean과 일반 자바 객체가 호출하는 @Bean 메서드의 차이

public class JavaConfigTest {

    AnnotationConfigApplicationContext ac;

    @Before
    public void setUp(){
        ac = new AnnotationConfigApplicationContext(AppConfig.class);
        assertThat(ac, is(notNullValue()));
    }

    @Test
    public void getBean(){
        SampleBean bean1 = ac.getBean(“sampleBean”, SampleBean.class);
        SampleBean bean2 = ac.getBean(“sampleBean”, SampleBean.class);
        assertThat(bean1, is(notNullValue()));
        assertThat(bean2, is(notNullValue()));
        assertThat(bean1, is(bean2));

        AppConfig config1 = new AppConfig();
        SampleBean bean3 = config1.sampleBean();
        assertThat(bean3, is(not(bean2)));

        AppConfig config2 = ac.getBean(“appConfig”, AppConfig.class);
        SampleBean bean4 = config2.sampleBean();
        assertThat(bean4, is(bean2));
    }

}

스프링 3.0 애노테이션 기반 설정을 익히기 위해서 처음 만들어본 테스트입니다. 이 테스트에서 알 수 있는 건 바로 이 글의 제목에서처럼 @Bean이 붙어있는 메서드를 어떤 객체를 이용해서 호출하느냐에 따라 그 결과가 다를 수 있다는 겁니다.

@Configuration
public class AppConfig {

    @Bean
    public SampleBean sampleBean(){
        return new SampleBean();
    }
}

이건 설정한 빈이고 SampleBean은 뭐 암거나;; @_@;

결론은 new 로 만든 AppConfig와 스프링에서 가져온 AppConfig의 @Bean이 붙은 메서드가 반환해주는 값이다르다는 겁니다. 전자는 일반적인 Java 문맥대로 sampleBean()에서 new SampleBean()으로 새로운 객체를 만들어서 받은 것이고, 후자는 sampleBean() 메서드 호출을 가로채서 기존의 bean을 반환해준 겁니다.

이 경우는 매우 간단한 경우에 속합니다. 하나는 스프링이 관리하는 빈이었고, 하나는 일반 자바 객체였으니까요. 그런데 만약에 둘 다 스프링의 빈이라면? 그 중에 하나는 @Configuration, 다른 하나는 @Component라면?

@Component로 설정한 빈 내부에 위와 똑같은 설정이 들어있다면? 반환하는 객체의 값이 조금 다르나면??

빈 스캔은 어찌하나?

정말 복잡하군요;; 하나씩 차근 차근 해보겠습니다.

static inner class를 Spring에 bean으로 등록하기

public class Foo {
    static class Bar {
        static String say() {
            return “Bar-Bar-Bar”;
        }
    }
}

요런 클래스가 있습니다. static inner class는 일반 inner class완 다르게 outter 객체가 없이도 접근할 수 있습니다. 사실상 outter 클래스를 통해서 접근할 뿐 보통 static 클래스랑 다를게 없습니다. inner class는 다르죠. outter 클래스의 인스턴스(객체)를 통해서만 접근할 수 있습니다.

따라서 일반 inner class를 bean으로 등록한다는 건 좀 이상합니다. outter 객체에 종속되어 있는 inner class만 독립적으로 사용할 수 없으니까요. 그걸 bean으로 등록하는 방법도 모르겠을 뿐더러, 등록한다고 해도.. 어떻게 쓸까요? 그 녀석들 만들려면 outter 객체를 항상 만들어서 inner class의 객체를 만들어서 반환하도록??.. 흠.. 좀 아닌거 같습니다. 그렇게 독립적으로 사용할 녀석이었다면 inner class가 아니였겠죠.

그렇다면, static inner class는 어떨까요? 얘는 bean으로 등록할 수 있더군요!! 왜냐면, 단순히 outter 클래스를 통해서만 접근할 뿐 일반 static 클래스와 다를것이 없거든요. 마치 outter 클래스 이름이 네임스페이스처럼 느껴질 뿐입니다.

등록하는 방법은 간단합니다. “$”를 사용해서

<bean id=”bar” class=”net.openseed.sandbox.innerclass.Foo$Bar” />

요런식으로 등록하면 됩니다. $를 사용해서 Bar 클래스가 Foo 클래스 안에 있다는 것을 알려줍니다. 간단하죠. 캬;; 스프링엔 참 별에 별게 많아요.

ps : 알려주신 사부님께 쌩큐.