2 minute read

1. BeanFactory

팩토리 디자인 패턴을 구현한 것으로, 빈을 생성하고 관리한다.

컨테이너가 구동될 때, Bean을 생성하는 것이 아니라, 클라이언트의 요청에 의해서 Bean이 사용될때 생서하는 Lazy Loading 방식을 사용한다.

2-1. ApplicationContext란?

ApplicationContext는 해당 Application에 대한 구성정보를 제공하는 인터페이스 이다.

스프링에서는 빈의 생성과 관계설정 같은 제어를 담당하는 Bean Factory 가 존재한다. 하지만 실제로는 빈의 생성과 관계설정 외에 추가적인 기능들이 필요한다. 이러한 이유로 Spring 에서는 빈 팩토리를 상속받아 확장한 Application Context 를 주로 사용한다. Application Context 는 별도의 설정 정보를 참고하고 IoC 를 적용하여 빈의 생성, 관계설정 등의 제어 작업을 총괄한다. Application Context 는 직접 오브젝트를 생성하고 관계를 맺어주는 코드는 존재 하지 않고, 이러한 생성 정보와 연관관계 정보에 대한 설정을 읽어 처리한다. ex) @Configuration

2-2. Bean 요청시 처리 과정

클라이언트에서 해당 빈을 요청하면 Application Context는 다음과 같은 과정을 거쳐 빈을 반환한다.

  1. ApplicationContext는 @Configuration이 붙은 클래스들을 설정 정보로 등록하고, @Bean이 붙은 메소드의 이름으로 빈 목록을 생성한다.
  2. 클라이언트가 해당빈을 요청한다.
  3. ApplicationContext는 자신의 빈 목록에 요청한 이름이 있는지 찾는다.
  4. ApplicationContext는 설정 클래스로부터 빈 생성을 요청하고, 생성된 빈을 돌려준다.

2-3. ApplicationContext의 다양한 기능

2-3-1. EnvironmentCapable

Profile과 Property를 관리한다.

Profile이란, 특정 환경에서 실행할 빈들의 그룹이다. 예를 들어 프로젝트를 진행할 떄 로컬, 개발, 운영 서버의 설정 환경들이 각각 다를수 있는데, 이를 나눠서 관리할 수 있도록 해주는 Profile 이다. 각각의 환경에서 다른 빈을 사용하거나 특정 환경에서만 사용하는 빈을 등록하는 경우에 사용한다.

Property란, 애플리케이션 구동 시 필요한 정보를 key-value 형태로 관리하며 각 Property 에는 우선순위가 존재한다. application.properties 에 등록하는 것들

2-3-2. HierachicalBeanFactory

BeanFactory를 상속받고 있으며, 상위 빈 팩토리를 반환하는 역할을 한다.

2-3-3. MessageSource

스프링은 다국어 처리를 위해 MessageSource 인터페이스를 제공한다. 예를 들어 서비스를 사용하는 지역별로 메세지를 해당 국가의 언어로 제공하고 싶을때 사용

2-3-4. ApplicationEventPublisher

스프링에서 이벤트 프로그래밍에서 필요한 인터페이스를 제공한다. Context가 생성되는 시점 소멸되는 시점 등에 행할 이벤트들을 설정할 수 있다.

2-3-5. ResourcePatternResolver

ResiurcePatternResolversms ResourceLoader 인터페이스를 상속한다. ResouceLoader는 classPath에서 리소스를 일거오거나, 상대경로, 절대경로를 일거오거나 URL 로 읽어오거나 등의 리소스를 읽어오는 인터페이스이다.

2-4. 다양한 종ㅠㅢ ApplicationContext 구현체

application context 는 interface 의 형태로, 다양한 구현체를 제공한다. 그중에서 아래 표 정도는 알아두도록 하자

XML 로 할지 자바 코드로 할지, 결정해보록 하자 (Java 코드를 통해 하면 컴파일 단에서 에러를 찾을수 있음) |AC의 종류|XML|Java Config| |——|—|—| |non-Web|GenericXmlApplicationContext|AnnotationConfigApplicationContext| |Web|XmlWebApplicationContextß|AnnotationConfigWebApplicationContext|

2-5. BeanFactort VS ApplicationContext

특별한 이유가 없는한 ApplicationContext 를 사용한다.

다음 기능들중 ‘Bean 객체화/엮음’ 부분을 제외하고는 BeanFactory는 모든 부분을 지원하지 않고 ApplicationContext은 모든 기능을 제공한다.

  • Bean 객체화/엮음
  • BeanPostProcessor 자동 등록
  • BeanFactoryPostProcessor 자동 등록
  • 편리한 MessageSource접근 (for i18n)
  • ApplicationEvent 발송

ApplicationContextAware

ApplicationContextAware 인터페이스를 구현하면 빈이 실행되는 환경인 ApplicationContext 인스턴스에 접근이 가능해진다

  • 용도 ApplicationContext에 직접 접근 시 사용, 많이 사용되는 것은 아니고 ApplicationContext 세부 설정을 XML 파일 로딩 시점에 특정 bean 에 위임할때 사용된다.
  • 사용방법 ApplicationContextAware Interface 구현하고 setApplicationContext(ApplicationContext appCtx) 매개변수를 통해 접근 bean이 ApplicationContextAware 인터페이스를 구현하면 bean 생성 및 property 의존성 주입 완료 후 init 메소드 실행전에 setApplicationContext()를 호출한다. 이를 통해 bean은 자신의 인스턴스를 생성관리 하는 ApplicationContext가 어떤 인스턴스인지 확인하고 접근할수 있다. 쉽게 말해 bean을 관리하는 ApplicationContext 인스턴스에 직접 접근이 필요한 경우 사용하는 Interface 이다.

  • 코드
    public class MyPrototypeBean {
    
    private String dateTimeString = LocalDateTime.now().toString();
    
    public String getDateTime() {
      return dateTimeString;
    }
    }
    
public class MySingletonBean implements ApplicationContextAware {

  private ApplicationContext applicationContext;

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
      this.applicationContext = applicationContext;
  }

  public void showMessage() {
      MyPrototypeBean bean = applicationContext.getBean(MyPrototypeBean.class);
      System.out.println("Hi, the time is " + bean.getDateTime());
  }
}
@Configuration
public class AppConfig {

  @Bean
  @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  public MyPrototypeBean prototypeBean() {
      return new MyPrototypeBean();
  }

  @Bean
  public MySingletonBean singletonBean() {
      return new MySingletonBean();
  }

  public static void main(String[] args) throws InterruptedException {
      AnnotationConfigApplicationContext context =
              new AnnotationConfigApplicationContext(AppConfig.class);
      MySingletonBean bean = context.getBean(MySingletonBean.class);
      bean.showMessage();
      Thread.sleep(1000);

      bean = context.getBean(MySingletonBean.class);
      bean.showMessage();
  }
}

Categories:

Updated: