2012-11-08 11 views
12

Wir versuchen, ein Projekt mit Guice Refactoring. Die Idee ist, alle Sprache Schnittstelle zu einem Concreate-Objekt wie Französisch oder Polnisch zu binden.Guice Injektion Null Zeiger

Wir haben ein Modul für die Bindung:

public class StandardModule extends AbstractModule { 

    @Override 
    protected void configure() { 

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

    } 
} 

Und ein classe (AboutDialog.java), die dieses injizierten Objekt verwenden:

@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(); 
} 

Und wir haben als Ergebnis:

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

Zeile 67 ist:

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

Unsere Schnittstelle ist:

public interface Language { 

    public ResourceBundle getLanguageInUse(); 
} 

Und die polnische Klasse:

public class Polish implements Language { 

    private ResourceBundle languageInUse; 

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

    public ResourceBundle getLanguageInUse() { 
     return languageInUse; 
    } 


} 

Wir sind verloren ...

+0

Sie sollten Ihren Code ein wenig ändern, um zu sehen, wo geworfen wird der NPE 'Code Resource Bündel = language.getLanguageInUse();.. String label = bundle.getString ("AboutDialog.title"); ' –

+0

Das Nullobjekt ist Sprache. Wir denken, dass die Injektion nicht funktioniert. – user1810567

+0

Wie erstellen Sie den AboutDialog? Ich glaube nicht, dass Sie den Dialog mit Guice erstellen, weil Guice einen leeren Konstruktor benötigt oder binden Sie Jframe irgendwo ein? –

Antwort

8

Ich gehe davon aus, dass Ihr nicht Ihre AboutDialog mit Hilfe schaffen von Guice.

Sie könnten injector.injectMembers(this) verwenden, wobei this die AboutDialog ist.

Der beste Weg wäre, dass die AboutDialog von Guice erstellt wird, so dass alle Mitglieder injiziert werden.

7

Sie verwenden "Feldinjektion". Dies macht es schwierig, die injizierten Werte in einem Konstruktor zu verwenden. selbst wenn Guice das Objekt erstellen sollte (was jetzt nicht geschieht) oder Sie injector.injectMembers(aboutDialog) verwenden würden, würde der Konstruktor ausgeführt werden, bevor der Injektor die Chance hat, das gewünschte Feld zu injizieren.

Es ist etwas komplizierter, eine Klasse zu erstellen, die sowohl einen variierenden Parameter als auch einen injizierten Parameter verwendet. Dies lässt Sie mit ein paar Optionen:

  • Injizieren Sie den JFrame. Wenn Sie wissen, welche JFrame Sie verwenden werden, wenn der Konstruktor erstellt wird, verwenden Sie einfach bind(JFrame.class).toInstance(myJFrame); in Ihrem Modul. Dann kann Guice den AboutDialog vollständig erstellen.

  • Erstellen Sie eine Factory manuell. Auf diese Weise können Sie AboutDialog.Factory injizieren und einfach create anrufen, um Ihre AboutDialog zu erhalten. Es wird in etwa so aussehen:

    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 
        } 
    } 
    
  • eine Fabrik erstellen und lassen Sie es Guice Draht über assisted injection für Sie auf.

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

wie in der Frage Kommentare erwähnt, stellen Sie sicher, Sie bekommen Ihre AboutDialog (oder AboutDialog.Factory über einen @Inject ed Konstruktor/Feld oder aus dem Injector selbst oder sonst Guice nicht wissen, die zu injizieren Parameter

+0

Es ist uns gelungen, das Objekt und die Projekt funktioniert perfekt. Danke für deine Hilfe ^^. – user1810567

+0

Gern geschehen! Wenn das Problem gelöst ist, denken Sie daran, [Antwort akzeptieren] (http://stackoverflow.com/faq#howtoask) zu akzeptieren. Viel Glück mit Ihrem Projekt! –

+1

Dieser Satz "der Konstruktor würde laufen, bevor der Injektor die Chance hat, das von Ihnen gewünschte Feld zu injizieren" hat meinen Tag gerettet, da ich nicht verstand, warum meine injizierten Felder in meinem Standard-Konstruktor immer Null waren. Vielen Dank!!! – mljrg