2013-08-07 2 views
13

EDIT 2018-02-08: Пример проекта, демонстрирующего, как это сделать на https://github.com/ravn/dagger2-named-string-inject-example - Примечание: the whole source is in a single file!Кинжал: Inject @Named строки?

Я смотрю, может ли кинжал заменить наш взгляд на нас (поскольку платформа развертывания Java работает медленно).

Я строю карту строк конфигурации во время выполнения, и я хотел бы, чтобы при необходимости вводил кинжал.

E.g. Если у меня есть

java.util.Map<String, String> map = new java.util.TreeMap<String, String>(); 
map.put("key", "value"); 

и

@Inject 
Thermosiphon(Heater heater, @Named("key") String value) { 
    this.heater = heater; 
    System.out.println("value =" + value); 
} 

Я хотел бы иметь "значение" впрыскивается в стоимостном выражении.

Примеры в исходном коде не имеют никаких @Named-обычаев. Просто попытка дает следующее исключение:

Exception in thread "main" java.lang.IllegalStateException: Errors creating object graph: 
    No binding for @javax.inject.Named(value=key)/java.lang.String required by class bar.Thermosiphon 
    at dagger.internal.ThrowingErrorHandler.handleErrors(ThrowingErrorHandler.java:34) 
    at dagger.internal.Linker.linkRequested(Linker.java:146) 
    at dagger.ObjectGraph$DaggerObjectGraph.getInjectableTypeBinding(ObjectGraph.java:288) 
    at dagger.ObjectGraph$DaggerObjectGraph.get(ObjectGraph.java:249) 
    at app.CoffeeApp.main(CoffeeApp.java:20) 

Как я должен подходить к этому?

ответ

13

Похоже, что у вас есть карта, и вы хотите использовать что-то, что автоматически связывает их с именованными строками. Вы не можете сделать это автоматически в кинжале, как можете в Guice, так как в Guice вы можете создать связующее свойство.

Dagger требует знаний всех ваших привязок во время компиляции, для того, чтобы сделать анализ, чтобы убедиться, что все привязки и зависимость удовлетворены

Это сказали, вы могли бы сделать что-то подобное - это больше котла но это законно.

@Module(library = true) 
public class PropertiesModule { 
    public final Properties props; 

    PropertiesModule(Properties props) { 
    this.props = props; 
    } 

    @Provides @Named("property.one") String providePropertyOne() { 
    props.getProperty("property.one", "some default"); 
    } 

    @Provides @Named("property.two") String providePropertyTwo() { 
    props.getProperty("property.two", "some other default"); 
    } 
    ... 
} 

Это позволит всем Hte привязок вы должны быть созданы, но удовлетворяются из значений времени выполнения. Ключи, однако, известны во время компиляции (и должны быть, поскольку вы все равно используете @Named («строковый литерал»). Если вы определили свои имена свойств и значения по умолчанию как постоянные строки, вы можете даже делать:

@Provides @Named(PROPERTY_NAME_CONSTANT) String a() { 
    props.getProperty(PROPERTY_NAME_CONSTANT, PROPERTY_NAME_CONSTANT_DEFAULT); 
    } 

это больше плиты котла, но Dagger имеет, при попытке устранить большую котельную пластину, предпочли анализ времени компиляции над абсолютным снижением котельных пластин То есть, я буду предлагать функцию, которая позволит улучшить. эта ситуация, автогенерация модуля для системных свойств из известного списка или некоторые такие. Я думаю, что даже эта плита котла может быть уменьшена.

+0

Несмотря на то, что вначале это выглядело как больше работы, я думаю, что он может дать централизованную документацию о том, какие свойства поддерживаются часто с модульными приложениями, особенно в наших случаях использования. Я дам ему попробовать. –

+0

Было бы очень удобно указать список таких свойств в источнике и получить геттеры, созданные обработчиком аннотаций. Мне не нужны значения по умолчанию - мне нужно исключение во время выполнения, если не указано ключ в сообщении об ошибке. –

+0

Да, я думаю, нам нужно решение кода-gen для этого - то, что генерирует модуль из списка свойств. –

8

Вы должны определить поставщика в модуле кинжала для вашего экземпляра @Named.

@Provides @Named("foo") String provideFoo() 
{ 
    return "foo string"; 
} 

Затем вы можете ввести именованный экземпляр в свой конструктор или использовать инъекцию поля в вашем зависимом классе.

public class Thermosiphon 
{ 
    @Inject @Named("foo") String fooString; 

    @Inject public Thermosiphon(Heater heater) 
    { 
     System.out.println("value of fooString is " + fooString); 
    } 
} 
+0

Мои строки заданы в файлах свойств, которые читаются во время выполнения и могут содержать произвольные значения. Мне нужен провайдер для каждого гибкий ключ? –

+1

На данный момент не существует способа запуска новых и произвольных привязок, как есть в Guice - это приведет к нарушению строгих требований к анализу времени компиляции Dagger.Вы должны заранее знать структуру своего объекта, так что вы должны иметь все эти именованные привязки заранее. –

Смежные вопросы