Nano Hash - криптовалюты, майнинг, программирование

Guice: правильное внедрение сгенерированных на заводе экземпляров

Я использую Guice 3.0 в проекте Groovy и сталкиваюсь со странным/неожиданным поведением инъекций. Мой основной/начальный класс:

class WidgetServicePerfTester {
    @Inject
    WidgetGenerator widgetGenerator

    static main(args) {
        Injector injector = Guice.createInjector(new WidgetServicePerfTesterModule())
        WidgetServicePerfTester perfTester = injector.getInstance(WidgetServicePerfTester)

        perfTester.run()
    }

    void run() {
        List<Widget> widgets = widgetGenerator.generateWidgets()
        widgets.each {
            it.doStuff()
        }
    }
}

Мой ПОЖО:

class Widget extends Thingy {
    WidgetClient widgetClient

    int numFoos

    @Override
    void doStuff() {
        widgetClient.doSomethingOnServer()
    }
}

Мои генераторы POJO (API + внедрение):

interface WidgetGenerator {
    List<Widget> generateWidgets()
}

class SimpleWidgetGenerator implements WidgetGenerator {
    @Inject
    WidgetClient widgetClient

    int numWidgets

    SimpleWidgetGenerator() {
        super()
    }

    SimpleWidgetGenerator(int numWidgets) {
        super()

        this.numWidgets = numWidgets
    }

    @Override
    List<Widget> generateWidgets() {
        List<Widget> widgets = []

        Widget firstWidget = new Widget(widgetClient: widgetClient, numFoos: getRandomNumber())
        widgets.add(firstWidget)

        // Code that populates the rest of 'widgets' with 'numWidgets' number of Widgets.
    }
}

Мой модуль Guice:

class WidgetServicePerfTesterModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(WidgetClient).to(SimpleWidgetClient)
    }

    @Provides
    public WidgetGenerator provideSimpleWidgetGenerator() {
        new SimpleWidgetGenerator(50)
    }
}

Когда я запускаю этот код, я получаю исключения нулевого указателя, потому что WidgetClient, введенный в каждый Widget, равен NULL. Почему и как это исправить?


  • WidgetClient и SimpleWidgetClient не определены. А также Thingy. Не могли бы вы предоставить реализацию? 13.01.2015

Ответы:


1

Вся проблема начинается здесь, в классе WidgetServicePerfTesterModule, в следующем блоке кода:

@Provides
public WidgetGenerator provideSimpleWidgetGenerator() {
    new SimpleWidgetGenerator(50)
}

Экземпляр SimpleWidgetGenerator создается с помощью этого конструктора:

SimpleWidgetGenerator(int numWidgets) {
    super()
    this.numWidgets = numWidgets
}

и поскольку этот объект создается вручную, вставка WidgetClient в SimpleWidgetGenerator не сработает - он нулевой и это объяснимо.

Для решения проблемы следует использовать guice-assistedinject и создать фабрику для виджетов. Здесь вы можете найти рефакторинговый проект с использованием упомянутых расширений. Все работает нормально.

Теперь ясно?

13.01.2015
  • Спасибо @Opal (+1) - так что, думаю, я ищу хорошее руководство, когда дело доходит до использования guice-assistedinject. Это решение работает, но я никогда бы не догадался об этом за миллион лет. При чем здесь эмпирическое правило? Когда следует использовать FactoryModuleBuilder? Какие проблемы он решает? Спасибо еще раз! 13.01.2015
  • FactoryModuleBuilder следует использовать, когда вам нужно создать объект с полями, аннотированными с помощью @Inject, а также поля, которые не могут быть введены, например. имя студента из БД. Затем, используя вспомогательную инъекцию, вы можете передать аргумент конструктора и ввести поле. Кажется, это то, что вам нужно здесь. 13.01.2015
  • Если проблема решена, пожалуйста, примите ответ. 13.01.2015
  • Извините, @Opal, вы были так полезны здесь (+2 за последние 2 комментария), я не хочу отменять зеленую галочку, но есть только 1 последний пункт о вашем коде, которому я до сих пор не следую. Где находится ваш WidgetFactory импл и как он вводится? 13.01.2015
  • WidgetFactory реализуется самим guice, вам просто нужно определить фабричные методы и установить фабрику с помощью следующего оператора install(new FactoryModuleBuilder().build(WidgetFactory)). Это все. 14.01.2015
  • @smeeb я могу чем-то еще помочь или проблема решена? 14.01.2015
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..