위 와 같은 코드가 있다.
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);
끝