Spring 05 - Spring Bean


스프링 Bean

  • 스프링 컨테이너에 의해 관리되는 자바 인스턴스 객체
  • 사용자가 직접 new로 생성하지는 않고, 스프링 컨테이너에서 알아서 관리되어 진다.

스프링 Bean 수동 등록

지난 페이지의 ‘스프링 컨테이너 수동 설정 방법’과 같은 방법이다. 그러니까 이전에 스프링 컨테이너 수동 설정하는 방법이 스프링 Bean을 수동으로 설정하는 방법인 것이다. 이를 다시 요약하면 다음과 같다.

  • @Configuration이 적용된 ApplicationContext 클래스 내 메서드에 @Bean으로 Bean을 등록할 수 있다.
  • 스프링 컨테이너가 @Configuration이 붙은 클래스를 설정 정보로 인식하여, 해당 클래스 내에서 @Bean으로 선언된 메서드들의 반환 객체가 스프링 Bean으로 등록된다.
  • @Bean은 메서드에 붙일 수 있고, 클래스에 붙이지 못한다.
// ApplicationConfig 클래스 (@Configuration)
@Configuration
public class ApplicationConfig {

    @Bean
    public ConveniencePayService conveniencePayService(){
        return new ConveniencePayService(
                new HashSet<>(Arrays.asList(moneyAdapter(), cardAdapter())),
                discountByConvenience()
        );
    }

    @Bean
    public ConveniencePayService methodPayService(){
        return new ConveniencePayService(
                new HashSet<>(Arrays.asList(moneyAdapter(), cardAdapter())),
                discountByPayMethod()
        );
    }
    ...
}

스프링 Bean 자동 등록

지난 페이지의 ‘스프링 컨테이너 자동 설정 방법’과 같은 방법이다. 그러니까 이전에 스프링 컨테이너 자동 설정하는 방법이 스프링 Bean을 자동으로 설정하는 방법인 것이다. 이를 다시 요약하면 다음과 같다.

  • ComponentScan 방식으로 @Component로 선언된 클래스들을 모두 자동으로 Bean으로 등록한다.
  • @Service, @Repository, @Controller 그리고 @Configuration도 내부적으로 @Component를 포함되어 있어 ComponentScan시 Bean으로 각자의 역할에 맞게 등록된다.
// @Service, @Repository, @Controller 내부엔 @Component가 존재
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
}

// SimpleBoardApplication 패키지 및 하위 패키지 내 @Component
// @Service, @Repository, @Controller는 @Component을 포함하고 있다.
@Service
public class BoardService {
    ...
}

빈 생성주기

스프링 빈은 스프링 컨테이너 내부에서 생성되고, 스프링이 종료되기 전까지 생명주기(Life-Cycle)을 가지고 있다. 스프링 빈의 생명 주기는 다음과 같다.

스프링 컨테이너 생성 -> 스프링 빈 생성 -> 의존 관계 주입 -> 초기화 콜백 -> 사용 -> 소멸 전 콜백 -> 스프링 종료

여기서 초기화 콜백 및 소멸 전 콜백과정을 통해 필요한 설정 및 해제를 담당하게 되는데, 스프링에서 이를 설정하는 방법은 다음과 같다.

  • InitializingBean, DisposableBean 인터페이스 상속
    • bean대상이 되는 클래스에 InitializingBean, DisposableBean 인터페이스를 상속받아 afterPropertiesSet()과 destroy()를 오버라이딩
      public class NetworkClient implements InitializingBean, DisposableBean {
          ...
          @Override
          public void afterPropertiesSet() throws Exception {
              connect();
              call("초기화 연결 메세지");
          }
      
          @Override
          public void destroy() throws Exception {
              disconnect();
          }
      }
      
  • @Bean(initMethod = “초기화메서드명”, destroyMethod=”소멸메서드명”)
    • @Bean 선언 시 bean대상이 되는 클래스의 초기화 및 소멸 메서드 지정
      public class NetworkClient{
          ...
          public void init() {
              System.out.println("NetworkClient.init");
              connect();
              call("초기화 연결 메세지");
          }
      
          public void close() {
              System.out.println("NetworkClient.close");
              disconnect();
          }
      }
      
      @Configuration
      static class LifeCycleConfig {
          @Bean(initMethod = "init", destroyMethod = "close")
          public NetworkClient networkClient() {
                  
          }
      }
      
  • @PostConstruct, @PreDestroy 지정 (현재 주 사용)
    • bean대상이 되는 클래스의 초기화 및 소멸 메서드에 각각 @PostConstruct, @PreDestroy 지정
      public class NetworkClient{
          ...
          @PostConstruct
          public void init() {
              System.out.println("NetworkClient.init");
              connect();
              call("초기화 연결 메세지");
          }
      
          @PreDestroy
          public void close() {
              System.out.println("NetworkClient.close");
              disconnect();
          }
      }
      

빈 스코프

스코프란 말은 존재하는 범위를 의미한다. 즉 빈 스코프라함은 빈이 존재하는 범위를 의미하는데, 일반적으로 스코프는 싱글톤으로 설정되어 있어 존재하는 범위는 앞서 이야기한 생명주기의 범위만큼 되어있다. 즉 싱글톤 스코프는 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프이다. 하지만, 싱글톤 외 다른 스코프로 설정하여 빈 객체의 존재 범위를 설정할 수 있다. 빈 스코프의 종류는 다음과 같다.

  • 싱글톤 스코프: Bean Container 내에서 인스턴스가 오직 하나만 생성 및 관리
  • 프로토타입 스코프: 해당 객체에 대한 요청이 있을 때마다 새로운 Bean 인스턴스를 생성, 생성 주기중 소멸자 호출 X
  • 웹 관련 스코프
    • request: 웹 요청이 들어오고 나갈때까지 유지되는 스코프
    • session: 웹 세션이 생셩되고 종료될 때까지 유지되는 스코프
    • application: 웹의 서블릿 컨텍스트와 같은 범위로 유지되는 스코프

설정 방법은 아래 코드로 설정할 수 있다.

@Scope("prototype")
@Component
public class NetworkClient {
}

@Configuration
class LifeCycleConfig {
    @Scope("prototype")
    @Bean
    public NetworkClient networkClient() {
        final NetworkClient networkClient = new NetworkClient();
        return networkClient;
    }
}