2015-10-01 32 views
8

Używam lombok w moim projekcie, z wieloma klasami z @RequiredArgsConstructors. Chciałbym, aby te konstruktory były automatycznie używane w guice.Tworzenie niestandardowej adnotacji @Inject

Jedną z opcji, która działa, jest użycie @RequiredArgsConstructors([email protected]__(@Inject)), ale jest to zarówno brzydkie, jak i eksperymentalne (czytaj: może zniknąć z lombok w przyszłości).

Co mam zamiar zrobić, to zrobić niestandardową adnotację wtrysku, powiedzmy @InjectOnlyConstructor, aby umieścić definicję klasy i użyć guice's SPI s, aby powiązać te typy. Ale nie wiem, jak odkryć te typy w SPI.

Jak mogę przejrzeć elementy guice i powiązać je z tymi konstruktorami, które domyślnie odrzucają guice?

Przykład czego chcę klasa wyglądać:

@Singleton 
@InjectOnlyConstructor 
@RequiredArgsConstructor 
public class CatPictureService { 
    private final WebServiceClient client; 

    // Cool stuff that would make facebook cry 
} 

Jako planu tworzenia kopii zapasowych, mogę mieć moduł, który skanuje pakiety mojego projektu i automatycznie wiąże te typy.

+0

Sztuką będzie użycie [toConstructor()] (http://google.github.io/guice/api-docs/latest/javadoc/com/google/inject/binder/LinkedBindingBuilder.html#toConstructor-java .lang.reflect.Constructor-) wiązania. Napiszę bardziej kompletne rozwiązanie później! –

+0

@TavianBarnes Tak! Pomyślałem, że to jest sposób na wykonanie backendu, ale odkryłem, że jest to koniec odkrywania typów, które muszą być związane za pomocą SPI (tj. Niedostatecznie skanuje ścieżkę klasy). –

+0

Styczna: Adnotacje na konstruktorach, metodach i paramertach są wymagane nie tylko w przypadku wstrzyknięć zależnych, ale w różnych innych przypadkach użycia. Biorąc pod uwagę, że status onX firmy Lombok ma status "niepewny", szukam bardziej wszechstronnego przykładu, który działa nie tylko dla Guice, ale także dla innych. Czy masz jakieś rozwiązanie? –

Odpowiedz

2

Zaczynam myśleć, że nie da się podłączyć do Guice, aby rozwiązać typy niezwiązane.

Więc wymyśliłem cztery różne rozwiązania. Pierwszy jest moim ulubionym, obejmuje model z wyraźnym kodem z oficjalnym użyciem rozszerzenia Guice. Go użyć w następujący sposób:

public class Bar { 
    private Bar(XYZ xyz) { ... } 
} 

Injector inject = Guice.createInjector(new AbstractModule() { 
    protected void configure() { 
     install(new OnlyConstructorBuilder(Bar.class)); 
    } 
}); 

OnlyConstructorBuilder jest zdefiniowany jako takie:

@RequiredArgsConstructor 
private static class OnlyConstructorBuilder extends AbstractModule { 
    private final Class<?> type; 

    @Override 
    protected void configure() { 
     bindToOnlyConstructor(type); 
    } 

    @SuppressWarnings("unchecked") 
    private <T> void bindToOnlyConstructor(Class<T> type) { 
     Constructor<T>[] ctors = (Constructor<T>[])type.getDeclaredConstructors(); 

     if (ctors.length > 1) { 
      addError("%s has too many constructors %s", type.getName(), Arrays.toString(ctors)); 
      return; 
     } else if (ctors.length < 1) { 
      addError("%s needs at least one constructor", type.getName()); 
      return; 
     } else { 
      bind(type).toConstructor(ctors[0]); 
     } 
    } 
} 

Drugie podejście jest skanowanie ścieżkę-lub klasa porcje IT poszukuje konkretnej adnotacji. To był mój oryginalny pomysł i nie jest to zbyt trudne, jeśli używasz pomocników do refleksji Guawy. Zrobiłem już coś podobnego, ale ludzie uważają to za zbyt magiczne. Część wiążąca jest podobna do powyższej.

Trzecie podejście to bind(Bar.class) w module i użycie elementu SPI do wyszukiwania UntargetedBinding s z pewną adnotacją. Ale ponieważ już wiążę klasę, równie dobrze mogę związać się z jedynym konstruktorem.

Czwarte podejście jest najgorsze. Korzysta z interfejsu API Elements i określa zależności każdego powiązania; wyszukiwanie niezwiązanych zależności za pomocą określonej adnotacji. To droga, której nie chcę zejść.

+0

W 'configure' klasy' Module', skanowanie fragmentów ścieżki klas (używając biblioteki Reflections) i wiązanie ich jak 'bindToOnlyConstructor' wydaje mi się najczystszym rozwiązaniem dla mnie. –