注射后初始化(JSF 1.2 + Guice)

时间:2009-05-20 04:22:31

标签: java jsf dependency-injection annotations guice

我正在尝试将Guice集成到JSF 1.2(Sun RI)应用程序中,我希望能够对我的托管bean执行以下操作:

  1. 使用Guice @Inject注释然后
  2. 注入依赖项
  3. 使用@PostConstruct注释
  4. 执行初始化

    我的问题是在处理@PostConstruct注释之前始终会调用@Inject方法。有谁知道这个问题的解决方案?

    托管bean:

    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;
        }
    }
    

    托管bean声明:

    <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但问题仍然存在。我找到了some discussion that seems to relate to my issue ...但我不明白如何使用这些信息:(

3 个答案:

答案 0 :(得分:1)

不幸的是,我没有给你答案,但我会说这个......

  

让对象注入自己看起来可能有效 - 你不一定需要使用超类:

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和序列化会发生什么事吗?这是我没有想过的东西,但它可能会影响会话bean。


  

这看起来不像是一种声音技术。如果我正确读取代码,每次解析对象时都会注入依赖项。


  

我怀疑这个补丁遇到了我提到的问题(不同的解析器,同一作者,无论如何)。除了错误之外,尝试同时使用两种不同的JSF(Sun和Apache)实现是行不通的。


我在野外看到了几个Guice / JSF项目(guicesf; jsf-sugar;也许还有更多?)但是还没有尝试过,所以我不知道他们是否会有所帮助你甚至是多么稳定。

无论你做什么,关注Web Beans(概述here)可能是一个想法,因为这可能会影响JSF中未来的bean处理功能(如果我理解Guice在正确堆叠,您可以使用它来实现 Web Bean - 而不是我建议您这样做。

答案 1 :(得分:1)

在做了一堆阅读之后,我得出的结论是,如果你使用JSF和Guice,最好避免使用@PostConstruct

在您提供的示例中,您可以注入Baz

public final class Foo {

    @Inject private Baz baz;
}

如果Guiz无法创建Baz,但必须由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();
    }
}

答案 2 :(得分:0)

This answer似乎有一个很好的解决方案来解决这个问题。具体来说,它建议在init()方法上使用@Inject注释,保证在调用构造函数后调用它。请注意,如果您正在使用属性注入,它可能无效。