경량 구글 Guice 의존성 주입 프레임 워크

Github에서主页: https://github.com/google/guice
API : http://google.github.io/guice/api-docs/4.0/javadoc/

Guice는 (발음 '주스') 구글. 경량 의존성 주입 프레임 워크에 의해 당신에게 가져 위의 자바 6에 대한 가벼운 의존성 주입 프레임 워크입니다.

Spring의 의존성 주입 정보는 참조  봄 의존성 주입 DI 방법을

(A)의 구글 Guice의 예를 참조하십시오  구글 Guice에 가이드
예를 들어, 우리는이  Communication실제로 사용하는 클래스  Communicator실제로 메시지를 보낼 수 있습니다.

메이븐 종속성을 추가 :

<dependency>
    <groupId>com.google.inject</groupId>
    <artifactId>guice</artifactId>
    <version>4.0</version>
</dependency>

우리는 먼저 정의  Communicator인터페이스와 클래스의 실현을  DefaultCommunicatorImpl:

public interface Communicator {
    boolean sendMessage(String message);
}
public class DefaultCommunicatorImpl implements Communicator {
    public boolean sendMessage(String message) {
        System.out.println("Sending Message + " + message);
        return true;
    }
}

그럼 우리가 건네  @Inject받는 노트  Communication주입 클래스  Communicator에 의존 클래스를 :

import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;

import java.util.logging.Logger;

public class Communication {
    @Inject
    private Communicator communicator;

    public Communication(Boolean keepRecords) {
        if (keepRecords) {
            System.out.println("Message logging enabled");
        }
    }

    public boolean sendMessage(String message) {
        communicator.sendMessage(message);
        return true;
    }

    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new BasicModule());

        Communication comms = injector.getInstance(Communication.class);

        comms.sendMessage("hello world");
    }
}

에서  main(), 당신은 우리를 통해 볼 수 있습니다  Injector얻을  Communication후, 인스턴스를 부르는  sendMessage()방법.

그런 다음  BasicModule클래스는 종류 어떻게의입니까?

이 모듈은 정의의 기본 단위  바인딩. 베이스 유닛 바인딩 따라 정의.

  • 그것은 상속 할 필요가  AbstractModule클래스
  • 그것은  Communication인스턴스 인스턴스에 바인딩, 인수 전달  true생성자
  • 그것은됩니다  Communicator특정 구현에 바인딩 DefaultCommunicatorImpl
import com.google.inject.AbstractModule;

public class BasicModule extends AbstractModule {

    @Override
    protected void configure() {
        // 表明:当需要 Communicator 这个变量时,我们注入 DefaultCommunicatorImpl 的实例作为依赖
        bind(Communicator.class).to(DefaultCommunicatorImpl.class);

        bind(Communication.class)
                .toInstance(new Communication(true));
    }
}

다음과 같은 출력을 실행합니다 :

메시지 로깅은 활성화
메시지 +의 안녕 세계 보내기

우리는 분사 코드 형태로 관리가 오히려 XML 설정 파일을 통해보다 의존을 통해, Guice을 볼 수 있습니다,이 봄은 동일하지 않습니다.

우리 수도  @Provides에서 주석  BasicModule정의에 의존 :

public class BasicModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(Communication.class)
                .toInstance(new Communication(true));
    }

    @Provides
    @Singleton
    public Communicator getCommunicator() {
        return new DefaultCommunicatorImpl();
    }
}

상기  @Singleton주석이 단일 종속 범위 형태 인 것을 나타내고, 이는 느리게 시작로드 지연이다.

우리는 다음과 같은 여러 바인딩에 의존해야한다면 :

@Provides
@Singleton
public Communicator getCommunicator() {
    return new DefaultCommunicatorImpl();
}

@Provides
@Singleton
public Communicator getCommunicatorOneMoreTime() {
    return new DefaultCommunicatorImpl();
}

그것은 다음과 같은 예외 런타임을 던질 것이다 :

1) A binding to demo.guice.Communicator was already configured at demo.guice.BasicModule.getCommunicator().
  at demo.guice.BasicModule.getCommunicator(BasicModule.java:17)

1 error
    at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:466)
    at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:155)
    at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:107)
    at com.google.inject.Guice.createInjector(Guice.java:96)
    at com.google.inject.Guice.createInjector(Guice.java:73)
    at com.google.inject.Guice.createInjector(Guice.java:62)

우리는 지금이 있다면  Communicator또 다른 실현의 인터페이스를  AnotherCommunicatorImpl:

public class AnotherCommunicatorImpl implements Communicator {
    public boolean sendMessage(String message) {
        System.out.println("Another Sending Message + " + message);
        return true;
    }
}

에서 우리는  Communication이전에 의존하는 클래스가 필요  DefaultCommunicatorImpl하고 새로운 정의  AnotherCommunicatorImpl와 같은 :

public class Communication {

    @Inject
    private Communicator communicator;

    @Inject
    private Communicator anotherCommunicator;

    public Communication(Boolean keepRecords) {
        if (keepRecords) {
            System.out.println("Message logging enabled");
        }
    }

    public boolean sendMessage(String message) {
        communicator.sendMessage(message);

        anotherCommunicator.sendMessage(message);

        return true;
    }

    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new BasicModule());

        Communication comms = injector.getInstance(Communication.class);

        comms.sendMessage("hello world");
    }
}

그래서 우리는  BasicModule이를 결합하는 방법을 정의해야 하는가?
우리가 또 다른 추가하려고하면  @Provides방법을 그 반환  AnotherCommunicatorImpl예를 들어, :

@Provides
@Singleton
public Communicator getCommunicator() {
    return new DefaultCommunicatorImpl();
}

@Provides
@Singleton
public Communicator getAnotherCommunicator() {
    return new AnotherCommunicatorImpl();
}

그것은 다음과 같은 예외가있을 것이다 :

Exception in thread "main" com.google.inject.CreationException: Unable to create injector, see the following errors:

1) A binding to demo.guice.Communicator was already configured at demo.guice.BasicModule.getCommunicator().
  at demo.guice.BasicModule.getAnotherCommunicator(BasicModule.java:23)

여기에 우리가해야 할  @Named기능 주석의 속성 지정을 위해 제공합니다.
바인딩 주입 첫째 사용  @Named주석 :

@Inject
@Named("communicator")
private Communicator communicator;

@Inject
@Named("anotherCommunicator")
private Communicator anotherCommunicator;

바인딩 정의 할 때 다음 사용  @Named노트 :

@Provides
@Singleton
@Named("communicator")
public Communicator getCommunicator() {
    return new DefaultCommunicatorImpl();
}

@Provides
@Singleton
@Named("anotherCommunicator")
public Communicator getAnotherCommunicator() {
    return new AnotherCommunicatorImpl();
}

결과는 다음과 같습니다 :

메시지 로깅은 활성화
메시지 +의 안녕 세계 보내는
또 다른 메시지를 보내는 +의 안녕 세계를

Guice 작품

전체 :

  • Guice: 프레임 워크의 외관
  • Injector, • 상황에 따라 관리
  • Binder: 인터페이스와 바인딩의 구현
  • Module:의 그룹 Binder
  • Provider: 콩 제공
  • Key: BinderA와 대응 Provider
  • Scope: Provider범위

각 바인딩은  Binding<T>다음과 같은 구조를 가지고 :

public interface Binding<T> extends Element {
    Key<T> getKey();

    Provider<T> getProvider();

이 상속 동시에  Element소스를 포함 :

public interface Element {
    Object getSource();

각각의 볼 수있는 바인딩  Binding<T>키 포함  Key<T>하고 공급자  Provider:

  • 키는  Key<T>고유 각 바인딩을 결정합니다. 주요  Key<T>고객 코드는 유형 및 옵션 라벨에 따라 포함되어 있습니다. 동일한 유형의 여러 바인딩 지점 사이를 구분하기 위해 주석을 사용할 수 있습니다.

    • 예를 들어, 위의 코드는, Communicator종류는 두 개의 키가 있습니다 :
    • Key[type=demo.guice.Communicator, [email protected](value=communicator)]
    • Key[type=demo.guice.Communicator, [email protected](value=anotherCommunicator)]
  • 각 공급자에 대한  Provider유형의 원하는 인스턴스를 제공합니다 :

    • 당신은 클래스를 제공 할 수 Guice는 당신이 그것의 인스턴스를 만드는 데 도움이됩니다.
    • 당신은 또한 당신이 클래스를 바인딩 할 Guice의 예를 제공 할 수 있습니다.
    • 당신은 또한 자신을 구현할 수  Provider<T>Guice 그것에 의존성을 주입 할 수 있습니다.
    • 예를 들어, 위의 코드는 공급자가 class demo.guice.DefaultCommunicatorImpl
  • 각 바인딩 및 선택 범위. 범위가없는 기본 바인딩 Guice는 새로운 객체를 생성 할 때마다 주입합니다. 사용자 지정 범위는 새로운 객체를 생성 할 것인지 여부를 Guice을 제어 할 수 있습니다. 예를 들어, 당신은 HttpSession이 각각의 인스턴스를 만드는 데 사용할 수 있습니다.

우리는 각각의 방법으로 결합을 통해 수 Binding<T>

Injector injector = Guice.createInjector(new BasicModule());

Map<Key<?>, Binding<?>> bindings = injector.getBindings();

for (Map.Entry<Key<?>, Binding<?>> bingingEntry : bindings.entrySet()) {

    Binding binging = bingingEntry.getValue();

    Key key =  binging.getKey();
    Provider provider = binging.getProvider();

    System.out.println("Key: " + key.toString());

    System.out.println("Provider: " + provider.get().getClass());

    System.out.println("************");
}

다음과 같이 출력은 다음과 같습니다

Key: Key[type=com.google.inject.Stage, annotation=[none]]
Provider: class com.google.inject.Stage
************
Key: Key[type=com.google.inject.Injector, annotation=[none]]
Provider: class com.google.inject.internal.InjectorImpl
************
Key: Key[type=java.util.logging.Logger, annotation=[none]]
Provider: class java.util.logging.Logger
************
Key: Key[type=demo.guice.Communication, annotation=[none]]
Provider: class demo.guice.Communication
************
Key: Key[type=demo.guice.Communicator, [email protected](value=communicator)]
Provider: class demo.guice.DefaultCommunicatorImpl
************
Key: Key[type=demo.guice.Communicator, [email protected](value=anotherCommunicator)]
Provider: class demo.guice.AnotherCommunicatorImpl
************

injector.getInstance(XXX.class);프로세스 :
먼저 지정된 클래스  new Key(), Key클래스 정보를 포함  XXX.class하고 주석 정보 XXX.class에 대한  hashcode주석  hashcode결정  Key의  hashcode, getProvider따라하면  Key할  hashcode결정하기 위해 동일 여부 Key, 다음에 촬영  Provider에 의해  Provider최종 샘플을 제공한다.
위의 예  Key[type=demo.guice.Communicator, [email protected](value=communicator)]와  각각에  그리고  .Key[type=demo.guice.Communicator, [email protected](value=anotherCommunicator)]hashcode-1491509781349671560

Guice DI과 스프링 DI를 비교

참조  봄과 Guice의 차이

  • 사용

    • 봄은 XML에 대한 클래스와 클래스 분리의 관계에있을 것입니다, 컨테이너는 호출 된 객체를 주입하기위한 책임이있다
    • Guice는 XML을 사용하지 않지만 주석 주석의 사용
  • 운영 효율성 :

    • 주석은 주석, CGLIB 고효율을 사용 Guice,이 스프링 가장 큰 차이점이며, 스프링 Guice는 않지만 주입에 사용될 때,은, 마무리에 주입에 대한 주입에 대한 구성 파일을로드하는 시간 높은 운영 효율성과 유연성을 제공합니다.
  • 입력 커플 링 :

    • 봄 커플 링 낮은 외부 의존성의 방식으로, 비 침습적 기반 강조 클래스 내부 구성 파일 소란에 매우 깨끗
    • 높은 커플 링, 표시 코드 레벨의 DI 플래그 Guice  @inject클래스 수준까지 결합 침입 코드를,



저자 : 풀 타임 워크에
링크 : HTTPS : //www.jianshu.com/p/7fba7b43146a의
출처 : 제인 책
저자가 보유 제인 책의 저작권은, 어떤 형태로도 복제되어, 승인을 얻기 위해 작성자에게 문의하고 소스를 표시하시기 바랍니다.

출시 여섯 개 원래 기사 · 원의 찬양 (43) · 전망 570 000 +

추천

출처blog.csdn.net/hany3000/article/details/100159754