ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • DDD - Dependency Injection과 AOP 6부 7부
    JAVA/DDD 2021. 1. 23. 12:40

    관점을 바꾸자


    • ProductRepository 경우와 마찬가지로 CustomerRepository OrderRepository EXTRACT INTERFACE리팩토링을 수행하자.
    • 즉 CustomerRepository, OrderRepository 인터페이스와 CollectionCustomerRepository, CollectionOrderRepository 클래스로 분리하자.
    • Registrar 대한 setter 메소드를 추가한  이들을 Spring 컨텍스트에 정의한다.

     

     

    • 기존의 테스트 케이스들이 Spring 경량 컨테이너의 지원을 받을  있도록 테스트 케이스를 수정하자
    • 우선 OrderTest 클래스를 ProductRepositoryTest 동일한 방식으로 getConfigLocations() onSetUp() 메소드를 오버라이딩한다.

     

     

    • OrderLineItem Order에서 직접 new연산자를 사용하여 인스턴스를 생성했었다
    • , OrderLineItem Spring  컨텍스트에 의해 관리되지 않는 객체이므로  컨텍스트로부터 획득되는 다른REPOSITORY들처럼 Spring 의존성 주입 서비스를 받을  없다
    • 따라서 Spring 컨테이너 외부에서 생성되는 OrderLineItem ProductRepositoty null 밖에 없다.

     

     

     

    • Spring 컨테이너 외부에서 생성되는 객체에 대해 의존성 주입을 제공하는 가장 효과적인 방법은 AOP(Aspect-Oriented Programming)를 적용하는 것이다.
    • AOP란 시스템 내의 관심사를 분리하는 프로그래밍 기법이다.
    • AOP를 사용하면 시스템의 핵심 관심사(Core Concerns)와 횡단 관심사(Cross-Cutting Concerns)의 분리를 통해 결합도가 낮고 재사용이 가능한 시스템을 개발할 수 있다.

     

     

     

    • Spring 2.x부터 기존의 프록시 기반 메커니즘에 AspectJ를 통합하여 더 강력하고 유연한 AOP 기능을 지원하게 되었다. 
    • 그 대표적인 것이 Spring 컨테이너 외부에서 생성되는 도메인 객체에 Spring 컨테이너에서 관리하는 빈을 의존 삽입할 수 있도록 해주는 기능이다. 
    • 이것은 AspectJ 5부터 지원되는 LTW(Load-Time Weaving) 기능을 사용하는 것으로 클래스 로더가 클래스를 로드 할 때 바이트 코드를 수정하여 Spring 빈을 삽입하는 것이다. 
    • 따라서 Order에서 new 연산자를 사용하여 OrderLineItem을 생성하더라도 CollectionProductRepository를 의존 삽입하는 것이 가능해 진다.

     

     

     

    • <include> 엘리먼트를 사용하여 org/eternity 클래스 패스 하위에 포함된 클래스들에 대해서만 애스펙트를 적용하도록 설정한다.
    • CGLIB에 의해 생성된 프록시 객체들은 애스펙트를 적용할 필요가 없으므로 <exclude> 엘리먼트를 사용하여 제외시킨다.

     

     

    • 이제 Spring에게 OrderLineItem의 클래스를 로드할 때 어떤 방법으로 ProductRepository 인스턴스를 의존 삽입해야 하는지를 알려줘야 한다.
    • Spring 빈 컨텍스트 설정 파일에 OrderLineItem ProductRepository의 연결 정보를 추가하자

     

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    @Configurable(value="orderLineItem",preConstruction=true)
    public class OrderLineItem {
        private ProductRepository productRepository;
     
        public OrderLineItem() {
        }
     
        public OrderLineItem(String productName, int quantity) {
            this.product = productRepository.find(productName);
            this.quantity = quantity;
        }
     
        public void setProductRepository(ProductRepository productRepository) {
            this.productRepository = productRepository;
        }
    }
    cs

     

    • @Configurable 어노테이션의 value에는 Spring 빈 컨텍스트에 정의한 OrderLineItem 빈의 id를 정의한다.
    • preConstruction의 값을 true로 한 이유는 이 값을 true로 설정하지 않으면 기본적으로 생성자 호출이 끝난 후 의존성이 주입되기 때문이다.
    •  따라서 위와 같이 생성자 내부에서 주입될 대상 객체를 호출하는 경우 NullPointerException이 발생하게 된다. 
    • 이를 방지하기 위해서는 생성자가 호출되기 전에 의존성이 주입되도록 preConstruction의 값을 true로 설정해 주어야 한다.

     

    • Spring 컨테이너를 사용하여 주문 시스템의 전체적인 결합도를 낮추는데 성공했다. 
    • 도메인 클래스들이 REPOSITORY의 인터페이스에만 의존할 뿐 실제적인 구현 클래스에 의존하지 않게 되었다. 
    • 이제는 메모리 컬렉션을 처리하는 REPOSITORY의 내부 구현을 데이터베이스에 접근하는 REPOSITORY로 대체하더라도 다른 클래스에 영향을 미치지 않을 것이다. 
    • 도메인 클래스가 REPOSITORY의 인터페이스에만 의존하기 때문에 Mock 객체를 사용하여 데이터베이스 없이도 테스트하는 것이 가능해졌다.

     

     

     

Designed by Tistory.