2017-01-14 6 views
2

Ich versuche, eine Klasse Generic (sagen ClassA) in einer anderen Klasse (sagen ClassB) mit Guice mit @Inject Annotation zu injizieren. Der Code der Klasse, die eingespritzt wird, ist unten gezeigt:Fehler beim Eingeben einer Klasse mit generischem Typ @Inject Guice

public interface InterfaceA<T> { 

} 

public class ClassA<T> implements InterfaceA<T> { 
    private final Class<T> data; 
    private Dependency1 dependency1; 

    @Inject 
    public ClassA(Class<T> data, Dependency1 dependency1) { 
     this.data = data; 
     this.dependency1 = dependency1; 
    } 

} 

Code of ClassB ist wie folgt:

public class ClassB { 
    private InterfaceA<Entity1> interfaceA; 

    @Inject 
    public ClassB(InterfaceA<Entity1> interfaceA) { 
     this.interfaceA = interfaceA; 
    } 
} 

Die Modulklasse ist wie folgt:

public class MyModule extends AbstractModule { 
    @Override 
    protected void configure() { 
     bind(new TypeLiteral<InterfaceA<Entity1>>(){}).to(new TypeLiteral<InterfaceA<Entity1>>(){}); 
    } 
} 

Jedoch Wenn die Anwendung gestartet wird, wird der folgende Fehler angezeigt:

ERROR [2017-01-14 19:54:00,646] com.hubspot.dropwizard.guice.GuiceBundle: Exception occurred when creating Guice Injector - exiting 
! com.google.inject.CreationException: Unable to create injector, see the following errors: 
! 
! 1) Could not find a suitable constructor in java.lang.Class. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private. 
! at java.lang.Class.class(Class.java:119) 

Irgendwelche Eingaben, wie man das löst, wären wirklich hilfreich. Danke im Voraus.

+0

Warum versuchen Sie, 'Class ' in etwas zu injizieren? Ist das nicht der springende Punkt, dass Sie den Typ im Modul kennen? – durron597

+0

Ich möchte es injizieren, weil ich wissen möchte, um die Klasse zu injizieren, die zur Laufzeit injiziert wird. – user3375226

+0

Das scheint gegen den Punkt der OO-Programmierung zu gehen. Auch haben alle Klassen eine '.getClass' Methode, die nicht ausreicht? – durron597

Antwort

2

Sie können dies nicht deklarativ tun. Sie müssen Anbieter Methoden verwenden:

public class MyModule extends AbstractModule { 
    @Override protected void configure() {} 

    @Provides InterfaceA<Entity1> provideInterfaceAEntity1(Dependency1 dep) { 
    return new ClassA<Entity1>(Entity1.class, dep); 
    } 
} 

Dies ist der einzige Weg, weil Sie nicht automatisch Class<T> in ClassA injizieren kann.

Sie benötigen eine solche Methode in Ihrer Module für jede Entity, die Sie mit InterfaceA koppeln möchten.

+0

Danke für deine Lösung! In diesem Fall verschieben wir jedoch alle Abhängigkeiten von ClassA außerhalb dieser Klasse. Dies scheint jedoch kein sauberer Weg zu sein. Außerdem verwenden wir hier nicht Guices @Inject-Funktionalität, sondern erstellen ein neues Objekt mit new(). Ich habe einen anderen Weg gefunden, dies zu tun. Schau dir meine Lösung an. – user3375226

+0

@ user3375226 Die Verwendung von 'new' ist nicht mit Guice verboten. Die Verwendung von '@ Inject 'ist nicht einmal obligatorisch. Darüber hinaus empfiehlt Guice, dass ein Konstruktor das endgültige Objekt anfordert. Mit 'literal.getRawType()' brechen Sie diese Empfehlung. Ich glaube diese Lösung ist die beste Guice-y. –

1

Ich habe endlich die Lösung gefunden. Anstatt Class<T> data in den Konstruktor von ClassA zu injizieren, injiziere ich hier TypeLiteral<T> literal und lese den Klassentyp von TypeLiteral mit der Methode getRawType().

-Code für KlasseA ist wie folgt:

public class ClassA<T> implements InterfaceA<T> { 
    private final Class<? super T> data; 
    private Dependency1 dependency1; 

    @Inject 
    public ClassA(TypeLiteral<T> literal, Dependency1 dependency1) { 
     this.data = literal.getRawType(); 
     this.dependency1 = dependency1; 
    } 
} 

Der Rest des Codes für andere Klassen nach wie vor gleich bleibt.

Verwandte Themen