Guice: Нужно ли аннотировать каждый класс графа объектов с помощью @Inject? - PullRequest
9 голосов
/ 10 августа 2011

Я бы хотел представить Guice для использования существующего проекта среднего размера.Для моих требований мне нужна настраиваемая область (сессия слишком большая, а запрос - маленький для моего проекта).

Представьте, что я запрашиваю подсказку, чтобы предоставить мне экземпляр класса, который имеет прямые и косвенные зависимости от многих других классов (состав).

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

Вопрос:

  • Действительно ли мне нужно поместить аннотацию @Inject (и мою собственную область видимости) на конструкторы всех участвующих классов или есть ли способ , что guice требует только этих аннотаций для класса верхнего уровня , который я запрашиваю, и что все дальнейшие зависимости разрешаются путем "запроса" моего пользовательскогообласть для поставщика зависимых типов?

Если это так, это увеличит усилия по внедрению Guice, потому что мне нужно настроить более 1000 классов.Любая помощь и опыт во время введения guice приветствуется.

Ответы [ 3 ]

13 голосов
/ 10 августа 2011

Прежде всего, можно использовать Guice, не помещая аннотацию @Inject в любом месте. Guice поддерживает привязки провайдера , @ Предоставляет методы и привязки конструктора , которые позволяют вам связывать типы по вашему выбору. Тем не менее, для нормальной работы он требует, чтобы @Inject аннотации служили метаданными, сообщающими ему, какие зависимости требуются классу и где он может их внедрить.

Есть причина этого в том, что в противном случае он не может определенно сказать, что он должен вводить и где. Например, классы могут иметь несколько конструкторов, и Guice нужен какой-то способ выбрать один для внедрения, который не основывается на догадках. Вы можете сказать: «Ну, у моих классов только один конструктор, поэтому ему не нужно @Inject», но что происходит, когда кто-то добавляет новый конструктор в класс? Тогда у Guice больше нет оснований для принятия решения, и приложение перестает работать. Кроме того, все это предполагает, что вы только делаете инъекцию конструктора. Хотя внедрение конструктора, безусловно, является лучшим выбором в целом, Guice также допускает внедрение методов (и полей), и проблема необходимости явно указывать точки внедрения класса здесь более серьезна, так как большинство классов будет иметь много методов, которые не являются используется для инъекций и не более нескольких из них.

В дополнение к важности @Inject в сообщении Guice, он также служит документацией о том, как класс предназначен для использования - что этот класс является частью проводной инфраструктуры внедрения зависимостей приложения. Это также помогает быть последовательным в применении @Inject аннотаций к вашим классам, даже если в настоящее время это не будет абсолютно необходимо для тех, кто просто использует один конструктор. Я также хотел бы отметить, что вы можете использовать аннотацию @javax.inject.Inject JSR-330 в Guice 3.0, если стандартная аннотация Java предпочтительнее, чем специфичная для Guice.

Мне не совсем понятно, что вы имеете в виду, когда спрашиваете о поле действия у провайдера. Области обычно не создают объекты сами по себе; они контролируют, когда запрашивать у поставщика с незаданной областью зависимости для нового экземпляра, и как контролировать область действия этого экземпляра. Конечно, провайдеры являются частью того, как они работают, но я не уверен, что вы это имеете в виду. Если у вас есть какой-то особый способ предоставления экземпляров объектов, то для этого нужно использовать Provider привязки и @Provides методы, которые не требуют аннотаций @Inject для самих классов.

1 голос
/ 12 августа 2011

НЕТ ВЫ НЕ

GUICE не просит вас вводить каждый отдельный объект. GUICE попытается создать только внедренные объекты. Таким образом, вы можете @Inject объекты, которые вы хотите ввести.

В области действия - Scope, по сути, контролирует, как ваши объекты создаются GUICE. Когда вы пишете свою собственную пользовательскую область, вы можете иметь структуру данных, которая контролирует способ создания объектов. Когда вы добавляете класс с вашей пользовательской аннотацией, GUICE вызовет ваш метод области перед созданием с провайдером для этого класса. Затем вы можете решить, хотите ли вы создать новый объект или использовать существующий объект из структуры данных (такой как hashmap или что-то еще). Если вы хотите использовать существующий, вы получаете это и возвращаете объект, в противном случае вы делаете provider.get () и возвращаете.

Обратите внимание на это

public <T> Provider<T> scope(final Key<T> key, final Provider<T> unscoped) {
    return new Provider<T>() {
      public T get() {
        Map<Key<?>, Object> scopedObjects = getScopedObjectMap(key);

        @SuppressWarnings("unchecked")
        T current = (T) scopedObjects.get(key);
        if (current == null && !scopedObjects.containsKey(key)) {
          current = unscoped.get();
          scopedObjects.put(key, current);
        }
        // what you return here is going to be injected ....
        // in this scope object you can have a datastructure that holds all references 
        // and choose to return that instead depending on your logic and external 
        // dependencies such as session variable etc...
        return current;
      }
    };
  }

Вот учебник ...

http://code.google.com/p/google-guice/wiki/CustomScopes

0 голосов
/ 10 августа 2011

На самом базовом уровне аннотация @Inject идентифицирует материал, который вам понадобится установить. Вы можете использовать guice непосредственно в поле, в метод или в конструктор. Вы должны использовать аннотацию @Inject каждый раз, когда хотите, чтобы подсказка вводила объект.

Здесь является обучающим руководством.

...