Open gmelon opened 1 month ago
답변을 찾아보긴 했는데... 완벽히 이해된 게 아니라서, 일단 내용 전달만 하겠습니다.
Config
클래스를 스캔할 때, 프록시 클래스를 생성합니다. Config
클래스를 상속받아 모든 @Bean
메서드를 오버라이드합니다.@Configuration
public class Config {
@Bean
public SomeService someService() {
return new SomeService();
}
@Bean
public OtherService otherServiceA() {
return new OtherService(someService());
}
@Bean
public OtherService otherServiceB() {
return new OtherService(someService());
}
}
Config
클래스를 스캔하면 다음과 같은 프록시 클래스를 생성합니다.public class Config$$EnhancerBySpringCGLIB extends Config {
private SomeService someService;
@Override
public SomeService someService() {
if (this.someService == null) {
this.someService = super.someService();
}
return this.someService;
}
@Override
public OtherService otherServiceA() {
return new OtherService(someService());
}
@Override
public OtherService otherServiceB() {
return new OtherService(someService());
}
}
someService()
메서드가 호출되면, 프록시는 내부적으로 캐싱된 SomeService
객체가 있는지 확인합니다.
만약 캐싱된 객체가 없다면, super.someService()
를 호출하여 실제 SomeService
객체를 생성하고 이를 캐싱합니다.
이후 someService()
메서드가 다시 호출되면, 프록시는 캐싱된 SomeService
객체를 반환합니다.
Config config = new Config$$EnhancerBySpringCGLIB();
OtherService serviceA = config.otherServiceA();
OtherService serviceB = config.otherServiceB();
otherServiceA()
를 호출할 때, 프록시는 someService()
를 호출하여 SomeService
객체를 생성하고 이를 OtherService
의 생성자에 전달합니다.
otherServiceB()
를 호출할 때, 프록시는 이미 생성된 SomeService
객체를 반환하여 동일한 인스턴스를 OtherService
의 생성자에 전달합니다.
책에서 설명하고 있는대로 아래와 같이 config 파일을 작성하면, OtherService를 생성할 때
someService()
를 직접 호출함에도 불구하고 OtherService에 싱글톤 빈이 주입됩니다.Config
반면 Configuration 어노테이션의 속성을 아래와 같이 변경하면
코드 그대로 매번 새롭게 생성된 인스턴스가 생성자로 전달된 것을 확인할 수 있습니다.
이러한 현상은 스프링이 Config 클래스에 프록시를 씌워 이미 생성된 빈은 다시 생성하지 않고 기존 빈을 재사용하기 때문이라고 알고 있습니다. 스프링이 프록시를 적용하고 사용하는 보다 자세한 과정이 궁금합니다.