이해 의존 주입

6180 단어
기능을 발휘할 수 있는 응용은 각 구성 요소 간의 상호 협업을 피할 수 없고 프로젝트의 복잡도가 높아지면서 복잡해진다. 이런 협업이 바로 의존이다.전통적인 방법은 모든 대상이 자신과 관련된 대상(즉 그것이 의존하는 대상)의 인용을 관리하는 것이다. 이것은 고도의 결합과 테스트하기 어려운 코드를 초래할 것이다.예를 들면 다음과 같습니다.
public class DamselRescuingKnight implements Knight {
    private RescueDamselQuest quest;
    public DamselRescuingKnight() {
        this.quest = new RescueDamselQuest();
    }
 
    public void embarkOnQuest() {
        quest.embark();
    }
}

이 예에서는 다음을 수행합니다.
  • DamselRescuingKnight의 구조 함수에서RescueDamselQuest 대상을 구성하여 두 대상을 긴밀하게 결합시켰다.
  • 단원 테스트 어려움: embark OnQuest () 호출될 때 대상quest 방법도 성공적으로 호출될 수 있도록 보장해야 합니다
  • 긴밀한 결합이 가져오는 부작용이 비교적 많다. 예를 들어RescueDamselQuest 클래스의 코드를 변경할 때 이를 속성으로 하는 클래스와 관련이 있을 수 있다.Rescue Damsel Quest의 기능을 필요로 할 때 이런 방식을 사용하는 것은 물론 빠르지만 다른 유사한 기능을 사용할 때 다른 대상의 인용을 관리해야 한다. 하나의 기능을 추가할 때마다 여러 구성 요소의 코드와 관련이 있다.
    주입에 의존하면 어느 정도에 이런 긴밀한 결합이 가져오는 문제를 해결할 수 있다
    POJO
    일반적으로 Plain Ordinary Java Object, 즉 일반적인 Java 객체라고 합니다.그 내포된 의미는 어떤 클래스에서도 계승되지 않았고, 인터페이스도 이루어지지 않았으며, 다른 프레임워크에 침입되지 않은 자바 대상을 가리킨다.이러한 자바 대상은 간단하고 유연하여 임의로 확장할 수 있다.Spring의 의존 주입은 POJO의 잠재력을 발휘하여 침입되지 않은 상황에서 구성 요소의 역할을 발휘하게 함으로써 기능을 실현할 수 있을 뿐만 아니라 구성 요소 간의 느슨한 결합성을 유지할 수 있다.일반적으로 POJO에는 객체의 속성으로 private 매개 변수가 있습니다.그리고 매개 변수에 대한 get과 set 방법을 접근 인터페이스로 정의했습니다.예를 들면 다음과 같습니다.
    public class User {
        private long id;
        private String name;
        public void setId(long id) {
            this. id = id;
        }
        public void setName(String name) {
            this. name=name;
        }
        public long getId() {
            return id;
        }
        public String getName() {
            return name;
        }
    }

    의존 주입
    의존 주입이란 제3자 구성 요소 관리를 통해 조율 대상 간의 의존 관계를 형성하거나 관리할 필요가 없다.의존 관계는 자동으로 그것들을 필요로 하는 대상에 주입될 것이다.다음은 하나의 예를 통해 설명한다.
    public class BraveKnight() {
        private Quest quest;
        public BraveKnight(Quest quest) {
            this.quest = quest;
        }
        public embarkOnQuest() {
            quest.embark();
        }
    }

    이 예와 첫 번째 예가 비교되는 차이점은 구조 함수에서 자체적으로 하나의 대상을 만들고 관리하는 것이 아니라 구조기에서 매개 변수로 하나의 대상을 전달하는 것이다.이것은 주입에 의존하는 방식, 즉 구조기 주입(constructor injection)이다.
    더 중요한 것은 들어오는 Quest 클래스는 하나의 인터페이스일 뿐이다. 이것은 이 인터페이스를 계승한 모든 클래스가 들어오고 BraveKnight에서 역할을 발휘할 수 있음을 의미한다. 구체적인 기능을 추가할 때마다 클래스에서 새로운 대상을 다시 관리해야 한다.물론 여러 개의 매개 변수를 구조 함수에 전달할 수도 있다.
    그리고 우리는 이 종류에 대해 매우 편리하게 테스트를 진행할 수 있다. 여기서 모크 하나로 실현하면 이를 테스트할 수 있다.
    mock은 아날로그 대상의 실례를 만들 수 있습니다. 이것은 업무 논리의 연결성을 강조하며, 일반적으로 단일 테스트와 통합 테스트에 사용됩니다.
    import static org.mockito.Mockito.*; //              
    import org.junit.Test;
    public class BraveKnithtTest() {
        public void knightShouldEmbarkOnQuest() {
            Quest mockQuest = mock(Quest.class); // mock        
            BraveKnight  knight = new BraveKnight(mockQuest); // mockQuest      
            knight.embarkOnQuest();
        }
    }

    mock 테스트는 이 종류가 사용할 수 있는지 검사할 수 있습니다.그러나 우리가 Quest의 구체적인 클래스를 계승한 후에 이 클래스와 BraveKnight 사이에는 구체적으로 어떻게 협업하는가?
    응용 프로그램 구성 요소 간의 협업을 만드는 행위를 일반적으로 조립(wiring)이라고 하는데, 스프링 두 가지 자주 사용하는 조립 방식은 xml 파일 조립과 자바 언어 조립이다.예를 들어 SlayDragonQuest 클래스가 Quest 클래스를 계승하는 경우 xml 어셈블리를 사용하여 BraveKnight에 주입하는 방법은 다음과 같습니다.
    
    
    
    
    
        
    
    
    
    
    

    xml 파일에서 이 두 클래스는spring의 bean으로 성명되며, BraveKnight에 대해서는 constructor-arg라는 매개 변수를 사용하여quest라는 bean을 자신의 구조기 매개 변수로 삼아 SlayDragonQuest에 대한 의존을 실현합니다.
    이 예에서 BraveKnight는Quest에 의존하지만 어떤 종류의Quest에 전달되는지 모른다. 그러면 우리는 수시로 그에 전달된Quest를 바꾸어 서로 다른 기능을 실현할 수 있고 내부 코드를 바꾸지 않아도 된다. 이것이 바로 느슨한 결합이다.
    응용 프로그램을 시작해야 할 때spring의 응용 프로그램 상하문 (Application Context) 을 사용하여 bean의 정의를 불러오고 조립하십시오.위에서 설명한 xml 파일 구성을 사용하는 bean의 경우 다음과 같이 ClassPathXmlApplicationContext를 응용 프로그램 컨텍스트로 사용할 수 있습니다.
    import  org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public  class  KnightMain {
        public  static  void  main(String[] args) throws  Exception {
            ClassPathXmlApplicationContext  context  =
                    new  ClassPathXmlApplicationContext("META-INF/spring/knight.xml");
            Knight  knight  =  context.getBean(Knight.class); //  knight bean
            knight.embarkOnQuest(); //  knight
            context.close();
        }
    }

    반전 제어(IoC)
    의존 주입을 언급하면 같은 유명한 용어인'반전 제어'를 꺼내지 않을 수 없다.제어 반전은 제어와 반전 두 방면의 내용을 포함한다.즉, 특정한 인터페이스에서 클래스의 선택 제어권을 호출 클래스에서 제거하고 제3자에게 전달한다.구체적으로 예를 들어 이곳의'어떤 인터페이스'는 위의 Quest 인터페이스를 가리킨다. 호출 클래스BraveKnight에서 어떤 실현 클래스를 사용할 것인지의 선택권은 BraveKnight 자체가 결정하는 것이 아니라spring 용기가 Bean 설정(xml일 수도 있고javaconfig)으로 제어할 수 있다.반전을 제어한다는 용어가 직관적이지 않기 때문에 Martin Fowler는 이러한 패턴을 설명하기 위해 의존 주입(Dependency Injection)을 사용했다.
    BeanFactory 및 ApplicationContext
    IoC 용기 밑바닥은 자바 언어의 반사 메커니즘을 통해 bean을 실례화하고 Bean 이전의 의존 관계를 구축합니다.스프링의 IOC 용기는 이러한 기본 기능을 구현하는 데 더해 빈 인스턴스 캐시, 라이프 사이클 관리, 빈 인스턴스 에이전트, 이벤트 게시, 리소스 로드 등 고급 서비스도 제공한다.
    Bean공장(com.springframework.beans.factory.BeanFactory)은 스프링 프레임워크의 가장 핵심적인 인터페이스로 고급 IoC의 설정 메커니즘을 제공한다.BeanFactory는 서로 다른 유형의 자바 대상을 관리하는 것을 가능하게 하고 상하문(com.springframework.beans.factory.ApplicationContext)을 응용하여 구축한 BeanFactory의 기초 위에서 응용을 위한 더 많은 기능을 제공한다. 이는 국제화 지원과 프레임워크 이벤트 체계를 제공하여 실제 응용을 만들기 쉽다.일반적으로 BeanFactory는 Ioc 컨테이너이고 ApplicationContext는 응용 컨텍스트입니다.일부 장면에서는 ApplicationContext도 Spring 컨테이너가 됩니다.쉽게 말하면 BeanFactory는 Spring 프레임워크의 인프라 시설로 Spring 자체를 대상으로 한다.ApplicationContext는 Spring 프레임워크의 개발자를 대상으로 하고 거의 모든 응용 프로그램에서 BeanFactory 대신 ApplicationContext를 직접 사용할 수 있다.
    ApplicationContext의 초기화와 BeanFactory는 중대한 차이가 있다. BeanFactory는 초기화할 때 Bean을 실례화하지 않고 어떤 Bean을 처음 방문했을 때 비로소 목표를 실례화한다.전자는 상하문을 초기화할 때 모든 단일 실례를 실례화하는 Bean이다.따라서 ApplicationContext의 초기화 시간은 BeanFactory보다 조금 길다.

    좋은 웹페이지 즐겨찾기