ApplicationContext

이한주·2023년 3월 8일
0

IoC 컨테이너는 객체에 대한 생성과 조합이 가능하게하는 프레임워크다.

스프링에서는 IoC 컨테이너를 ApplicationContext인터페이스로 제공한다.

ApplicationContext는 BeanFactory를 상속한다.

객체에 대한 생성, 조합, 의존관계 설정 등을 제어하는 IoC 기본기능은 BeanFactory에서 담당한다.

Bean은 IoC 컨테이너에 의해 관리되는 객체다.

ApplicationContext는 BeanFactory에서 다음과 같은 기능을 추가한다.

  • Easier integration with Spring’s AOP features
  • Message resource handling (for use in internationalization)
  • Event publication
  • Application-layer specific contexts such as the WebApplicationContext for use in web applications.

https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-introduction

다음은 표로 비교하는 BeanFactory, ApplicationContext다.

ApplicationContext는 BeanFactory의 모든 기능을 포함한다.

https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-beanfactory

Configuration Metadata

ApplicationContext는 실제 만들어야할 빈 정보를 Configuration Metatdata로부터 받아온다.

이 메타데이터를 이용해 IoC 컨테이너에 의해 관리되는 객체들을 생성하고 구성한다.

Configuration Metadata는 XML, Java 파일을 기반으로 작성할 수 있다.

XML 기반으로 할 경우 GenericXmlApplicationContext를 구현체로 사용하고 Java 기반의 설
정을 이용할 경우 AnnotationConfigApplicationContext 구현체를 사용한다.

https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-java

예제

기존 OrderContext를 AppConfiguration으로 바꿔본다.

public class OrderContext {

    public VoucherRepository voucherRepository() {
        return new VoucherRepository() {
            @Override
            public Optional<Voucher> findById(UUID voucherId) {
                return Optional.empty();
            }
        };
    }

    public OrderRepository orderRepository() {
        return new OrderRepository() {
            @Override
            public void insert(Order order) {

            }
        };
    }

    public VoucherService voucherService() {
        return new VoucherService(voucherRepository());
    }

    public OrderService orderService() {
        return new OrderService(voucherService(), orderRepository());
    }

}

메타데이터를 알려주기 위해 @Configuration 어노테이션을 사용한다.

각 메소드도 @Bean 어노테이션을 사용해 Bean을 정의한 메타데이터로 등록한다.

@Configuration
public class AppConfiguration {

	@Bean
  public VoucherRepository voucherRepository() {
      return new VoucherRepository() {
          @Override
          public Optional<Voucher> findById(UUID voucherId) {
              return Optional.empty();
          }
      };
  }

	@Bean
	public OrderRepository orderRepository() {
        return new OrderRepository() {
            @Override
            public void insert(Order order) {

            }
        };
    }

	@Bean
  public VoucherService voucherService() {
      return new VoucherService(voucherRepository());
  }

	@Bean
  public OrderService orderService() {
      return new OrderService(voucherService(), orderRepository());
  }

}

실행 클래스도 ApplicationContext에서 Bean들을 가져오도록 바꾼다

public class OrderTester {

	public static void main(String[] args) {
		var applicationContext = new AnnotationConfigApplicationContext(AppConfiguration.class);

		var customerId = UUID.randomUUID();
		var orderService = applicationContext.getBean(OrderService.class);
		Order order = orderService.createOrder(customerId, new ArrayList<>() {{
			add(new OrderItem(UUID.randomUUID(), 100L, 1));
		}});

		Assert.isTrue(order.totalAmount() == 100L, MessageFormat.format("totalAmount {0} is not 100L", order.totalAmount()));
	}

}

자바 코드 기반의 메타데이터이므로 AnnotationConfigApplicationContext 클래스를 사용한다.

다음 코드처럼 등록된 빈을 가져올 때는 getBean 메소드를 사용한다.

var orderService = applicationContext.getBean(OrderService.class);

실행을 하면 다음처럼 빈을 등록하는 로그를 볼 수 있다.

코드

https://github.com/yanJuicy/kdt-spring-order/tree/6861b83015586c4483aa8fdc6abf9c95c5909e56

0개의 댓글