3. 스프링 DI(Dependency Injection) #4 @Configuration 설정 클래스의 @Bean 설정과 싱글톤

2021. 7. 2. 17:15JAVA/Spring

본 글은 최범균 저자의 초보 웹 개발자를 위한 스프링5 프로그래밍 입문 도서의 내용의 복습을 위해 작성된 글입니다.

7. @Configuration 설정 클래스의 @Bean 설정과 싱글톤

앞서 작성한 AppCtx 클래스의 일부는 다음과 같다.

@Configuration
public class AppCtx{
	
	@Bean
	public MemberDao memberDao() 
	{
		return new MemberDao();
	}
	
	@Bean
	public MemberRegisterService memberRegSvc()
	{
		return new MemberRegisterService(memberDao());
	}
	
	@Bean
	public ChangePasswordService changePwdSvc()
	{
		ChangePasswordService pwdSvc = new ChangePasswordService();
		pwdSvc.setMemberDao(memberDao());
		return pwdSvc;
	}
 }

memberRegSvc() 메서드와 changePwdSvc() 메서드는 둘 다 memberDao() 메서드를 실행하고 있다. 그리고 memberDao() 메서드는 매번 새로운 MemberDao 객체를 생성해서 리턴한다. 하지만 여기서 궁금증이 생긴다.

  • memberDao() 메서드가 새로운 MemberDao 객체를 생성해서 리턴하므로 memberRegSvc()에서 생성한 MemberRegisterService 객체와 changePwdSvc()에서 생성한 ChangePasswordService 객체는 서로 다른 MemberDao 객체를 사용하는 것이 아닌가?
  • 서로 다른 객체를 사용한다면 MainForSpring에서 new 명령어로 등록한 회원 정보를 저장할 때 사용하는 MemberDao와 change 명령어로 수정할 회원 정보를 찾을 때 사용하는 MemberDao는 다른 객체가 아닌가?

정답은 MemberRegisterService 객체와 ChangePasswordService 객체는 서로 같은 MemberDao 객체를 사용한다.

 

스프링 컨테이너는 @Bean이 붙은 메서드에 대해 한 개의 객체만 생성한다. 이는 다른 설정 메서드에서 memberDao()를 몇 번을 호출하더라도 항상 같은 객체를 리턴한다는 것을 의미한다.

 

이렇게 할 수 있는 이유는 스프링은 설정 클래스를 그대로 사용하지 않기 때문이다. 대신 설정 클래스를 상속한 새로운 설정 클래스를 만들어서 사용한다. 스프링이 런타임에 생성한 설정 클래스는 다음과 유사한 방식으로 동작한다. (이 코드는 어디가지나 이해를 돕기 위해서 만든 가상의 코드이다. 실제 스프링의 코드는 이보다 훨씬 복잡하다.)

public class AppCtxExt extends AppCtx{
	private Map<String, Object> beans = ...;
    
    @Override
    public MemberDao memberDao(){
    	if(!beans.containsKey("memberDao"))
        	beans.put("memberDao",super.memberDao());
            
        return (MemberDao) beans.get("memberDao");
    }
}

 

결론

스프링이 런타임에 생성한 설정 클래스의 memberDao() 메서드는 매번 새로운 객체를 생성하지 않는다.

대신 한번 생성한 객체를 보관했다가 이후에는 동일한 객체를 리턴한다.

따라서 memberRegSvc() 메서드와 changePwdSvc() 메서드에서 memberDao() 메서드를 각각 실행해도 동일한 MemberDao 객체를 사용한다.

 

초보 웹 개발자를 위한 스프링5 프로그래밍 입문, 최범균 저