Инициализация после инъекции (JSF 1.2 + Guice) - PullRequest
2 голосов
/ 20 мая 2009

Я пытаюсь интегрировать Guice в приложение JSF 1.2 (Sun RI), и я хочу иметь возможность сделать следующее для моих управляемых компонентов:

  1. Внедрить зависимости, используя аннотацию Guice @Inject, затем
  2. Выполнить инициализацию, используя аннотацию @PostConstruct

Моя проблема в том, что метод @PostConstruct всегда вызывается до обработки аннотаций @Inject. Кто-нибудь знает решение этой проблемы?

Управляемый компонент:

public final class Foo {

    @Inject private BazService bazService;
    private Baz baz;

    @PostConstruct
    public void init() {
        bar = bazService.loadBaz();
    }

    public void setBazService(BazService bazService) {
        this.bazService = bazService;
    }
}

Объявление управляемого компонента:

<managed-bean>
  <managed-bean-name>foo</managed-bean-name>
  <managed-bean-class>bean.Foo</managed-bean-class>
  <managed-bean-scope>request</managed-bean-scope>
  <managed-property>
    <property-name>id</property-name>
    <value>#{param.id}</value>
  </managed-property>
</managed-bean>

Привязки Guice:

public final class MyGuiceModule extends AbstractModule {

    @Override
    protected void configure() {
        bind(BazService.class).to(DummyBazService.class).in(Scopes.SINGLETON);
    }
}

Я пробовал следующее:

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


Редактировать

Я использовал Guice 1.0. Сейчас я обновился до Guice 2.0, но проблема остается. Я нашел некоторое обсуждение, которое, похоже, относится к моей проблеме ... но я не понимаю, как использовать эту информацию: (

Ответы [ 3 ]

1 голос
/ 22 мая 2009

После долгих чтений я пришел к выводу, что лучше всего избегать @PostConstruct, если вы используете JSF и Guice.

В приведенном вами примере вы можете ввести Baz:

public final class Foo {

    @Inject private Baz baz;
}

Если Baz не может быть создан Guice, но должен быть создан BazService, вы можете использовать метод провайдера:

public final class MyGuiceModule extends AbstractModule {

    @Override
    protected void configure() {
        bind(BazService.class).to(DummyBazService.class).in(Scopes.SINGLETON);
    }

    @Provides
    Baz provideBaz(BazService bazService) {
        return bazService.loadBaz();
    }
}
1 голос
/ 21 мая 2009

К сожалению, у меня нет ответа для вас, но я скажу это ...

Получение объектов для инъекции выглядит так, как будто это может работать - вам не обязательно использовать суперкласс:

public final class Foo {

  @Inject
  private BazService bazService;
  private Baz baz;

  @PostConstruct
  public void init() {
    InjectorFinder.getInjector().injectMembers(this);
    baz = bazService.loadBaz();
  }

  public void setBazService(BazService bazService) {
    this.bazService = bazService;
  }

}

Я также не вижу причин сохранять ссылку на инжектор, поэтому рассмотрим служебный класс:

public class InjectorFinder {
  public static Injector getInjector() {
    FacesContext facesContext = FacesContext
        .getCurrentInstance();
    ExternalContext extContext = facesContext
        .getExternalContext();
    Map<String, Object> applicationMap = extContext
        .getApplicationMap();
    return (Injector) applicationMap.get(Injector.class
        .getName());
  }
}

Что-нибудь происходит с @PostConstruct и сериализацией? Это то, о чем я не особо задумывался, но это может повлиять на сессионные компоненты.


Это не похоже на звуковую технику. Если я правильно прочитал код, зависимости будут вставляться каждый раз, когда объект разрешается.


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


Я видел несколько проектов Guice / JSF в дикой природе ( guicesf ; jsf-sugar ; может быть, есть и другие?), Но я не пробовал их, поэтому у меня есть не знаю, помогут ли они вам или даже насколько они стабильны.

Что бы вы ни делали, возможно, стоит присмотреться к Web Beans (обзор здесь ), поскольку это может повлиять на будущие функции обработки bean-компонентов в JSF (если я правильно понять место Guice в стеке, вы можете использовать его для реализации Web Beans - я не рекомендую вам это делать).

0 голосов
/ 01 ноября 2011

Этот ответ , кажется, имеет хорошее решение, как решить эту проблему. В частности, он предлагает использовать аннотацию @Inject для метода init (), который гарантированно получит вызов после вызова вашего конструктора. Обратите внимание, что это может не работать, если вы используете внедрение свойств.

...