복붙노트

[SPRING] DI 프레임 워크의 필요성 이해하기

SPRING

DI 프레임 워크의 필요성 이해하기

이것은 순진한 질문 일 수 있습니다. 나는 현재 스프링 프레임 워크와 의존성 주입을 배우고있다. DI의 기본 원칙은 파악하기가 쉽지만, 구현을 위해 정교한 프레임 워크가 필요한 이유는 즉시 명백하지 않습니다.

다음을 고려하세요:

public abstract class Saw
{
    public abstract void cut(String wood);
}

public class HandSaw extends Saw
{
    public void cut(String wood)
    {
        // chop it up
    }
}

public class ChainSaw extends Saw
{
    public void cut(String wood)
    {
        // chop it a lot faster
    }
}

public class SawMill
{
    private Saw saw;

    public void setSaw(Saw saw)
    {
        this.saw = saw;
    }

    public void run(String wood)
    {
        saw.cut("some wood");
    }
}

그럼 간단하게 할 수 있습니다 :

Saw saw = new HandSaw();
SawMill sawMill = new SawMill();
sawMill.setSaw(saw);
sawMill.run();

어느 것과 동등한가?

<bean id="saw" class="HandSaw"/>

<bean id="sawMill" class="SawMill">
   <property name="saw" ref="saw"/>
</bean>

더 :

ApplicationContext context = new ClassPathXmlApplicationContext("sawmill.xml");
SawMill springSawMill = (SawMill)context.getBean("sawMill");
springSawMill.run();

물론, 이것은 모범적 인 예이며보다 복잡한 객체 관계를 사용하면 프로그래밍 방식으로 작성하는 것보다 XML 파일을 숨겨 놓는 것이 더 효율적 일 수 있지만 그보다 더 많은 것이 있어야합니다.

(나는 스프링 프레임 워크가 그 이상이라는 것을 알고 있지만 DI 컨테이너의 필요성을 생각하고있다.)

첫 번째 예제에서 의존성을 중류로 변경하는 것도 간단합니다.

// gotta chop it faster
saw = new ChainSaw();
sawMill.setSaw(saw);
sawMill.run();

해결법

  1. ==============================

    1.나는 똑같은 질문을했고, 이것으로 답을 얻었습니다 : 허락하신다면, "그럼 간단히 할 수 있습니다 : ..."( "클래스 A"라고 부르 자)에서 설명했던 것을 할 수 있습니다. 그러나 그것은 클래스 A를 HandSaw 또는 클래스 SawMill에서 필요한 모든 종속성에 결합시킵니다. 왜 A가 HandSaw에 결합되어야합니까? 아니면보다 현실적인 시나리오를 취할 경우 DAO 레이어에 필요한 JDBC 연결 구현에 비즈니스 로직을 결합해야하는 이유는 무엇입니까? 내가 제안한 해결책은 "의존성을 한 단계 더 나아가게했다"는 것이 었습니다. 이제는 JDBC 연결에 대한 내 견해를 가지고 있습니다. HTML (또는 스윙, 취향 선택) 만 다루어야합니다.

    나는 똑같은 질문을했고, 이것으로 답을 얻었습니다 : 허락하신다면, "그럼 간단히 할 수 있습니다 : ..."( "클래스 A"라고 부르 자)에서 설명했던 것을 할 수 있습니다. 그러나 그것은 클래스 A를 HandSaw 또는 클래스 SawMill에서 필요한 모든 종속성에 결합시킵니다. 왜 A가 HandSaw에 결합되어야합니까? 아니면보다 현실적인 시나리오를 취할 경우 DAO 레이어에 필요한 JDBC 연결 구현에 비즈니스 로직을 결합해야하는 이유는 무엇입니까? 내가 제안한 해결책은 "의존성을 한 단계 더 나아가게했다"는 것이 었습니다. 이제는 JDBC 연결에 대한 내 견해를 가지고 있습니다. HTML (또는 스윙, 취향 선택) 만 다루어야합니다.

    DI 프레임 워크는 XML (또는 JavaConfig)에 의해 구성되어 "필요한 서비스를 얻으십시오". 초기화 된 방법, 작동해야하는 부분은 신경 쓰지 않아도됩니다. 서비스 객체를 가져 와서 활성화하면됩니다.

    또한, 당신은 "plus :"(당신이 SawMill springSawMill = (SawMill) context.getBean ( "sawMill"); springSawMill.run ();) 위치에 대해 오해하고있다. sawMill 빈을 얻을 필요가 없다. 컨텍스트에서 - sawMill 빈은 DI 프레임 워크에 의해 객체 (클래스 A)에 주입되어야합니다. 그래서 ... getBean (...) 대신에, "sawMill.run ()"으로 가면 어디서 왔는지, 누가 초기화했는지, 어떻게 초기화했는지 신경 쓰지 않아도됩니다. 당신이 신경을 써도 / dev / null, 테스트 출력, 또는 진짜 CnC 엔진으로 바로 갈 수 있습니다 ... 요점은 - 당신은 상관하지 않습니다. 당신이 신경 쓰는 모든 것은 그것이하기로 계약 된 것을해야하는 당신의 작은 작은 클래스 A입니다 - 톱 밀을 활성화하십시오.

  2. ==============================

    2.의존성 주입은 암시 적 매개 변수 전달의 퇴보 한 형태이며 그 목적은 본질적으로 동일하여 구성이라는 문제를 해결합니다. 문제 :

    의존성 주입은 암시 적 매개 변수 전달의 퇴보 한 형태이며 그 목적은 본질적으로 동일하여 구성이라는 문제를 해결합니다. 문제 :

    Dependency Injection 프레임 워크는 함축적 인 매개 변수, Curried 함수 및 언어의 모나드를위한 편리한 기능의 부족을 보완합니다.

  3. ==============================

    3.Spring은 똑같이 중요한 세 가지 기능을 가지고있다.

    Spring은 똑같이 중요한 세 가지 기능을 가지고있다.

    의존성 주입을 새로운 호출에 대한 단일 호출과 비교할 때 이점을 보는 것이 어렵다는 것에 동의 할 것입니다. 이 경우 코드는 한 줄이기 때문에 후자는 분명 더 단순 해 보일 것입니다. Spring의 설정은 항상 코드 라인을 증가시킬 것이므로, 그것은 논쟁의 여지가 없다.

    클래스에서 트랜잭션과 같은 교차 관심사를 취할 수 있고 선언적 방식으로 애스펙트를 사용하여 측면을 설정할 수있을 때 훨씬 더 자세하게 보입니다. 단일 "새로운"호출과의 비교는 Spring이 생성 된 호출이 아닙니다.

    아마도 Spring을 사용하여 얻은 최상의 결과는 권장되는 관용구가 인터페이스, 레이어 및 DRY 같은 좋은 원칙을 사용하는 방식입니다. 이것은로드 존슨이 컨설팅 조직에서 사용한 객체 지향 베스트 프랙티스의 증류입니다. 그는 시간이 지남에 따라 구축 한 코드가 고객에게 더 나은 소프트웨어를 제공하는 데 도움이되는 것을 발견했습니다. 그는 "Expert 1 : 1 J2EE"에서 자신의 경험을 요약하고 Spring으로 코드를 오픈 소스 화했습니다.

    나는 그의 경험이 당신이 더 나은 코드를 작성하는 데 도움이 될 것이라고 생각하는 정도로 프레임 워크를 구입한다고 말하고 싶다.

    세 가지 기능을 모두 결합 할 때까지 Spring의 모든 가치를 얻을 수 있다고 생각하지 않습니다.

  4. ==============================

    4.필자는 여러 가지 이유로 수동으로 코드를 사용하지 않고 구성 파일에 "배선"을 넣는 것이 더 합리적이라고 생각합니다.

    필자는 여러 가지 이유로 수동으로 코드를 사용하지 않고 구성 파일에 "배선"을 넣는 것이 더 합리적이라고 생각합니다.

  5. ==============================

    5.필자는 일반적으로 XML이나 Reflection 기반 DI에 신경 쓰지 않는다. 왜냐하면 나의 사용 사례에서는 불필요한 복잡성이 추가되기 때문이다. 대신, 저는 보통 수동식 DI를 사용합니다. 좀 더 자연스럽고 대부분의 이점이 있습니다.

    필자는 일반적으로 XML이나 Reflection 기반 DI에 신경 쓰지 않는다. 왜냐하면 나의 사용 사례에서는 불필요한 복잡성이 추가되기 때문이다. 대신, 저는 보통 수동식 DI를 사용합니다. 좀 더 자연스럽고 대부분의 이점이 있습니다.

    public class SawDI{
        public Saw CreateSaw(){
            return new HandSaw();
        }
    
        public SawMill CreateSawMill(){
            SawMill mill = new SawMill();
            mill.SetSaw(CreateSaw());
            return mill;
        }
    }
    
    // later on
    
    SawDI di = new SawDI();
    SawMill mill = di.CreateSawMill();
    

    이는 여전히 복잡한 DI 프레임 워크 또는 XML 구성 파일에 의존하지 않고도 커플 링을 중앙 집중화하고 모든 장점을 보유한다는 것을 의미합니다.

  6. ==============================

    6.DI 컨테이너 / 라이브러리의 대부분이 (전부는 아닐지라도) 한 가지는 DI를 통해 생성 된 모든 인스턴스의 메소드를 인터셉트 할 수 있다는 것입니다.

    DI 컨테이너 / 라이브러리의 대부분이 (전부는 아닐지라도) 한 가지는 DI를 통해 생성 된 모든 인스턴스의 메소드를 인터셉트 할 수 있다는 것입니다.

  7. ==============================

    7.의존성 주입의 주요한 단점은 잊어 버리십시오 : 강력한 Java IDE의 찾기 용도를 사용하여 무언가가 초기화 된 곳을 쉽게 찾을 수있는 능력이 느슨합니다. 리팩터링을 많이하고 테스트 코드가 애플리케이션 코드의 10 배가되는 것을 피하려면 매우 심각한 문제 일 수 있습니다.

    의존성 주입의 주요한 단점은 잊어 버리십시오 : 강력한 Java IDE의 찾기 용도를 사용하여 무언가가 초기화 된 곳을 쉽게 찾을 수있는 능력이 느슨합니다. 리팩터링을 많이하고 테스트 코드가 애플리케이션 코드의 10 배가되는 것을 피하려면 매우 심각한 문제 일 수 있습니다.

  8. ==============================

    8.삽입 된 클래스를 하드 코딩하면 컴파일 타임에 해당 클래스를 사용할 수 있어야합니다. 설정 파일을 사용하면 재 컴파일하지 않고 런타임에 사용 된 톱을 변경할 수 있으며 클래스 패스에 방금 배치 한 새 항아리에서 가져온 톱을 사용할 수도 있습니다. 가치가 있다면 여분의 복잡성은 해결해야 할 과제에 달려 있습니다.

    삽입 된 클래스를 하드 코딩하면 컴파일 타임에 해당 클래스를 사용할 수 있어야합니다. 설정 파일을 사용하면 재 컴파일하지 않고 런타임에 사용 된 톱을 변경할 수 있으며 클래스 패스에 방금 배치 한 새 항아리에서 가져온 톱을 사용할 수도 있습니다. 가치가 있다면 여분의 복잡성은 해결해야 할 과제에 달려 있습니다.

  9. ==============================

    9.최근에는 DI 패턴을 잊어 버릴 정도로 DI 프레임 워크를 매우 강조하고 있습니다. J. B. Rainsberger가 요약 한 DI의 원칙 :

    최근에는 DI 패턴을 잊어 버릴 정도로 DI 프레임 워크를 매우 강조하고 있습니다. J. B. Rainsberger가 요약 한 DI의 원칙 :

    눈치 챘 겠지만 수동으로 프레임 워크를 사용하는 것과 프레임 워크를 사용하는 것 사이에는 큰 차이가 없습니다. 아래에 표시된 것처럼 생성자 삽입을 사용하면 코드 예제의 상용구가 훨씬 적어지며 컴파일러에서 필요한 모든 종속성을 제공해야합니다 (IDE에서 입력해야하는 경우도 있음).

    SawMill sawMill = new SawMill(new HandSaw());
    sawMill.run();
    

    DI 프레임 워크는 공장을 생성하고 오브젝트를 서로 연결하는 보일러 플레이트를 줄일 수 있지만 동시에 각 종속성이 어디서 발생하는지 파악하는 것을 더 어렵게 만들 수도 있습니다. DI 프레임 워크의 구성은 추상 그리고 당신의 IDE는 특정 생성자가 호출되는 곳을 알려주지 못할 수도 있습니다.

    DI 프레임 워크의 간접적 인 단점은 종속 관계를 너무 쉽게 연결할 수 있다는 것입니다. 더 이상 의존성을 가지고 고통을 느낄 수없는 경우 클래스 간의 결합을 줄이기 위해 응용 프로그램의 디자인을 다시 생각하는 대신 더 많은 종속성을 계속 추가 할 수 있습니다. 종속성을 수동으로 배선 (특히 테스트 코드에서)하면 테스트 설정이 길어지고 단위 테스트를 작성하는 것이 어려워지면 의존성이 너무 많을 때 더 쉽게 알 수 있습니다.

    DI 프레임 워크의 몇 가지 장점은 AOP (예 : Spring의 @Transactional), 범위 지정 (일반 코드로 여러 번 범위 지정이 충분 함) 및 Pluggability (플러그인 프레임 워크가 실제로 필요한 경우)와 같은 고급 기능을 지원하는 데 있습니다.

    최근 수동 DI 대 프레임 워크 기반 DI의 실험을했습니다. 진행 상황과 결과는 Let 's Code 딤드 워프 에피소드 42 번부터 47 번까지의 스크린 캐스트로 표시됩니다. 문제의 프로젝트는 배우 작성을위한 Guice 기반 플러그인 시스템을 가지고 있으며, Guice없이 수동 DI를 사용하여 다시 작성했습니다. 그 결과는 훨씬 간단하고 명확한 구현이었으며, 약간의 상용구가되었습니다.

    시놉시스 : 먼저 수동 DI (바람직하게는 생성자 삽입)를 사용해보십시오. 상용구가 많으면 의존성을 줄이기 위해 디자인을 다시 생각해보십시오. DI 프레임 워크의 일부 기능이 가치를 제공하는 경우 DI 프레임 워크를 사용하십시오.

  10. ==============================

    10.Spring은 근본적으로 두 가지가 다른 하나 위에 쌓여 있다는 것을 이해하는 것이 중요합니다.

    Spring은 근본적으로 두 가지가 다른 하나 위에 쌓여 있다는 것을 이해하는 것이 중요합니다.

    (2)는 Spring 코드의 대부분이다. 기본적으로 Java 기술을 선택하면 Spring에 도움이되는 클래스가 있다는 것을 알게 될 것입니다. 이것은 ActiveMQ, Sun One MQ 또는 Spring JmsTemplate이면서 추상화 된 것을 사용할 수 있기 때문에 데이터 액세스 기술, 웹 서비스 등에 대해서도 마찬가지입니다.

    이 헬퍼들은 모두 (1)을 사용하여 연결합니다.

  11. ==============================

    11.Dependency Injection을 사용할 때 가장 큰 장점 중 하나는 클래스에 대한 단위 테스트를 만들 때 클래스 종속성의 모의 (mock) 또는 스텁 (stub)을 제공하는 것이 훨씬 쉬워진다는 것입니다. 이를 통해 공동 작업자에 의존하지 않고 클래스를 독립적으로 테스트 할 수 있습니다.

    Dependency Injection을 사용할 때 가장 큰 장점 중 하나는 클래스에 대한 단위 테스트를 만들 때 클래스 종속성의 모의 (mock) 또는 스텁 (stub)을 제공하는 것이 훨씬 쉬워진다는 것입니다. 이를 통해 공동 작업자에 의존하지 않고 클래스를 독립적으로 테스트 할 수 있습니다.

    당신의 예제에서는 클래스의 Saw 나 SawMill을 모방하거나 스텁하는 방법이 없습니다. Saw와 SawMill이 setter 또는 생성자를 통해 설정된 경우 단위 테스트를 실행할 때 SawMill을 직접보고 조롱 할 수 있습니다.

  12. ==============================

    12.Spring은 DI 모델을 이해하고 심지어 권장하도록 도와줍니다. 그러나, 나는 당신이 봄을 가져야한다고 생각하지 않습니다.

    Spring은 DI 모델을 이해하고 심지어 권장하도록 도와줍니다. 그러나, 나는 당신이 봄을 가져야한다고 생각하지 않습니다.

    디버깅, 리팩터링 및 코드 분석을 수행 할 수있는 Java로 구성 파일을 가질 수 있습니다.

    이 자바 설정 파일을 다른 패키지에 넣는 것이 좋지만 그렇지 않으면 XML 설정 파일과 동일하다. 중요하다면이 파일을 동적으로로드 할 수도 있습니다.

  13. from https://stackoverflow.com/questions/500637/understanding-the-need-for-a-di-framework by cc-by-sa and MIT license