Spring @Configuration @Bean 메소드 의 매직?!

Spring @Configuration 이 붙은 java config 클래스에서 일어나는
마법?!같은 일에 대해 정리해본다.

위 와 같은 코드가 있다.
clientService1() 메소드와 clientService2() 메소드 각각 내부에서
clientDao() 메소드를 호출하고 있다.

음.. 이러면 ? clientDao() 메소드 가 두번 호출되어 ClientDaoImpl 인스턴스가 두개 생성되는 것 아닌가? 라는 의문이 갑자기 든다. 이래도 되나?

걱정할 필요 없다.(심지어 @Configuration 이 지원되는 spring 3.0 부터다.)

스프링 문서에 아래와 같은 내용이 있다.

clientDao() has been called once in clientService1() and once in clientService2(). Since this method creates a new instance of ClientDaoImpl and returns it, you would normally expect to have two instances (one for each service). That definitely would be problematic: In Spring, instantiated beans have a singleton scope by default. This is where the magic comes in: All @Configuration classes are subclassed at startup-time with CGLIB. In the subclass, the child method checks the container first for any cached (scoped) beans before it calls the parent method and creates a new instance.

@Configuration class 는 CGLIB 에 의해 상속되어, 자식 메소드(clientService1(), clientService2())에서
ClientDaoImpl 인스턴스를 생성하기 위해 부모메소드(clientDao()) 를 호출할때 container 에 캐시된 빈들이 있는지 찾는다.

이렇게 가능하도록

ConfigurationClassPostProcessor (BeanFactoryPostProcessor) 에서
ConfigurationClassEnhancer 를 사용하여 처리하고 있다.

원리를 이해하기 위해 아래와 같은 코드를 작성했다.

출력은

ConfigurationClassEnhancer 내에서 cglib 인터셉터로 BeanMethodInterceptor 를 등록하고 사용한다.

beanMethod 를 처음 호출시 아래와 같이 cglib 설정된 인스턴스를 인자로 넘기기에 위와 같이 상속에 대한 메소드 호출로 동작한다.

return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store