본문 바로가기

SPRING

[SPRING] 싱글톤 패턴, 싱글톤 컨테이너와 Bean

싱글톤 패턴 Singleton pattern

여러 소프트웨어 디자인 패턴 중 하나로, 싱글톤 패턴을 따르는 클래스는 생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성한 객체를 리턴하는 디자인 패턴이다.

 

사용이유

메모리 낭비를 줄이기 위해 

 

순수 DI(Dependency Injection 의존성주입) 컨테이너

여기서 m1과 m2는 서로 다른 객체이다

void test(){
	AppConfig appConfig = new AppConfig();
    
    MemberService m1 = appConfig.memberService();
    MemberService m2 = appConfig.memberService();
    
    // m1 != m2
}

 

 

싱글톤 패턴

public class SingletonService {

    // static 영역에 객체 딱 1개만 생성
    private static final SingletonService instance = new SingletonService();

    // static method를 통해 객체 생성하도록 함
    public static SingletonService getInstance(){
        return instance;
    }

    // private 생성자 통해 외부에서 new로 객체 생성되는 것을 막음
    // 즉 외부에서는 SingletonService.getInstance()를 통해서만 호출가능함
    // 이렇게되면 호출하는 모든 singletonService 가 동일한 객체가 되는것임
    private SingletonService();
    
}

 

하지만 이렇게 싱클톤 패턴을 사용하면 유연성이 떨어진다 (내부 속성을 변경하기 어려움..)

스프링 싱글톤 컨테이너를 사용하면 싱글톤패턴을 직접 구현하지 않아도 객체 인스턴스를 싱글톤으로 관리해준다 !!

 

 

스프링 싱글톤 컨테이너(IoC 컨테이너)

Inversion Of Control Contatiner : 객체 관리, 생성, 의존성 관리까지 해줌 (객체의 생명주기 관리)

 

 

스프링 빈(Bean)

- 스프링 컨테이너가 관리하는 자바 객체

- 사용자가 직접 new를 이용하여 생성한 객체가 아니라 spring에 의해 생성되고 관리되는 자바 객체

- 자주 사용하는 객체를 싱글톤 패턴으로 생성해두면 서버 성능에 크게 도움이 된다

 

스프링빈 생성방법

1. @Component 사용

  - @ConponetScan 어노테이션이 붙은 클래스의 하위 클래스들을 스캔하여 @Component 어노테이션이 붙은 클래스를 확인한다

  - 기본적으로 @SpringBootApplication 어노테이션 안에 @ConponetScan이 있다

  - @Configuration, @Controller, @Serve, @Repository 들은 모두 @Component를 포함하고 있다

 

2. 빈 설정파일에 직접 빈을 등록

@Configuration
public class SpringConfig {

	@Bean
    public MemberService memberService() {
    	return new MemberService();
    }
}

 

  - 메소드의 리턴 객체를 IoC의 빈으로 등록

  - 빈의 이름은 기본적으로 메소드 이름을 따름

  - 만약 같은 인터페이스의 구현체 클래스 두개 이상이 빈으로 등록되면 NoUniqueBeanDefinitionException 오류가 발생함

    : 이럴경우 어떤 빈을 주입해야하는지 알려줘야한다

    : 서브 기능의 빈에는 @Qualifier를 적용하고 메인 기능으로 사용하는 빈에는 @Primary를 적용해서 주입하면 좋다

    : @Primary과 @Qualifier를 동시에 사용하면 @Qualifier를 우선적으로 적용한다

        (스프링은 기본적으로 자동보다 수동으로 지정한것에 우선순위를 높게 가지므로)

1) @Qualifier 사용
 : 구분자를 통해 빈을 구분해준다 (빈의 이름이 변경되는 것은 아님)
 : @Qualifier("myBeanAliasName")
 
2) @Primary 사용
 : 여러 빈이 있을 때 기본적으로 선택될 빈에 @Primary 를 붙여준다

   

하지만 저렇게 빈을 설정한다고 해서 자동으로 의존성이 주입되진 않는다

 

의존성 주입 방법 

1. @Autowired

@Autowired 어노테이션을 특정 필드에 부여하면 loC 컨테이너 안에 존재하는 특정 필드와 같은 타입의 bean을 찾아 자동으로 의존성을 주입해준다

public class AutowiredController {

    @Autowired
    private AutowiredService autowiredService;

}

 

하지만 이 방법은 이제 지양된다

대신 @RequiredArgsConstructor를 사용하자

- 생성자를 자동으로 생성해주는 어노테이션

- final 키워드가 붙은 멤버변수를 생성자 파라미터로 알아서 넣어준다

- 사용이유

  : 순환참조 방지

  : final 선언이 가능해짐(객체 불변성 보장)

  : 테스트 코드 작성 용이

 

2. @Resource

- @Autowired와 마찬가지로 빈을 자동으로 주입해준다

- @Autowired와 다르게 필드 이름을 기준으로 빈을 찾는다 (@Autowired는 필드 타입을 기준으로 빈을 찾음)

@Resource(name = "memberService")
private MemberService memberService;

 

 

 

끄읏 -!