Guice 注入空指针

Posted

技术标签:

【中文标题】Guice 注入空指针【英文标题】:Guice injection null pointer 【发布时间】:2012-10-29 04:27:41 【问题描述】:

我们尝试使用 Guice 重构项目。这个想法是将所有 Language 接口绑定到一个 concreate 对象,例如 FrenchPolish

我们有一个绑定模块:

public class StandardModule extends AbstractModule 

    @Override
    protected void configure() 

       bind(Language.class).to(Polish.class);

    
 

还有一个使用这个注入对象的类(AboutDialog.java):

@Inject Language language;

public AboutDialog(JFrame parent) 
    super(parent, "", true);
    this.language=language;
    this.setTitle(language.getLanguageInUse().getString("AboutDialog.title"));
    this.parent = parent;
    try 
        jbInit();
     catch (Exception e) 
        e.printStackTrace();
    
    pack();

我们得到了结果:

java.lang.NullPointerException at net.sf.jmoney.gui.AboutDialog.<init>(AboutDialog.java:67)

第 67 行是:

this.setTitle(language.getLanguageInUse().getString("AboutDialog.title"));

我们的界面是:

public interface Language 

    public ResourceBundle getLanguageInUse();

波兰语课是:

public class Polish implements Language 

    private ResourceBundle languageInUse;

    public Polish() 
        languageInUse = ResourceBundle.getBundle(Constants.LANGUAGE_PL);
    

    public ResourceBundle getLanguageInUse() 
        return languageInUse;
    



我们迷路了……

【问题讨论】:

你应该稍微改变你的代码,看看 NPE 是在哪里抛出的。 code ResourceBundle bundle = language.getLanguageInUse(); String label = bundle.getString("AboutDialog.title"); 空对象是语言。我们认为注入不起作用。 如何创建 AboutDialog?我不认为您正在使用 Guice 创建对话框,因为 Guice 需要一个空的构造函数,或者您是否将 jframe 绑定到某个地方? 尝试在波兰类的构造函数中使用 log/System.out 指令打印当前线程堆栈跟踪。这样就可以看出是不是Guice框架构建的了。是 this.language=language;真的需要指导吗? ResourceBundle 可以加载本地特定的属性,无需将其包装在语言类中:docs.oracle.com/javase/tutorial/i18n/resbundle/concept.html 【参考方案1】:

我假设您没有在 Guice 的帮助下创建 AboutDialog

您可以使用injector.injectMembers(this),其中thisAboutDialog

最好的方法是 AboutDialog 将由 Guice 创建,因此所有成员都将被注入。

【讨论】:

【参考方案2】:

您正在使用“字段注入”。这将使您难以在构造函数中使用注入的值;即使 Guice 要创建对象(现在没有发生)或者您要使用 injector.injectMembers(aboutDialog),构造函数也会在注入器有机会注入您想要的字段之前运行。

创建一个接受可变参数和注入参数的类有点棘手。这给您留下了几个选择:

注入 JFrame。如果您知道在创建构造函数时将使用什么 JFrame,那么只需在模块中使用 bind(JFrame.class).toInstance(myJFrame);。然后 Guice 可以完全创建 AboutDialog。

手动创建工厂。这样你就可以注入AboutDialog.Factory 并调用create 来获取你的AboutDialog。它看起来像这样:

public class AboutDialog extends JDialog 

  /** Injectable factory. */
  public static class Factory 
    @Inject private Language language;

    public AboutDialog create(JFrame parent) 
      return new AboutDialog(parent, language);
    
  

  // no @Inject parameter; you're calling "new" yourself above!
  public AboutDialog(JFrame parent, Language language) 
    super(parent, "", true);
    this.language = language;
    // ... other initialization
  

创建一个工厂并让 Guice 通过assisted injection 为您连接。

public class AboutDialog extends JDialog 

  public interface Factory 
    public AboutDialog create(JFrame parent);
  

  // you need the @Inject, and also the @Assisted to tell Guice to
  // use the parameter instead of Guice bindings
  @Inject
  public AboutDialog(@Assisted JFrame parent, Language language) 
    super(parent, "", true);
    this.language = language;
    // ... other initialization
  


public class StandardModule extends AbstractModule 
  @Override protected void configure() 
    bind(Language.class).to(Polish.class);

    // here every method in AboutDialog.Factory will be implemented
    // to create the method's return type [AboutDialog] based on
    // the parameters (like JFrame) and the bindings (like Language)
    install(new FactoryModuleBuilder().build(AboutDialog.Factory.class));
  

如问题 cmets 中所述,请确保您通过 @Injected 构造函数/字段或从 Injector 本身获取您的 AboutDialog(或 AboutDialog.Factory,否则 Guice 将不知道注入参数。

【讨论】:

我们已经成功注入对象,项目完美运行。谢谢你的帮助^^。 不客气!如果您的问题得到解决,请记得accept an answer。祝你的项目好运! 这句话“构造函数将在注入器有机会注入你想要的字段之前运行”拯救了我的一天,因为我不明白为什么在我的默认构造函数中使用我的注入字段总是空的.谢谢!!!

以上是关于Guice 注入空指针的主要内容,如果未能解决你的问题,请参考以下文章

@Inject 注入 还是报空指针

用于字段注入的空指针

spring set注入 空指针问题

SpringBoot@Autowired注入静态成员变量报空指针异常

spring bean注入报空指针null,但set设值时对象是存在的,而且只是部分方法报空指针

spring注入问题空指针