java-forum.org
JBoss Seam
Alter Preis: 39,95 €
Jetzt: 0,00 €

zzgl. Versandkosten

Zurück   java-forum.org > Blogs > thE_29

Bewerten

Dependency/Code Injection mit Google Guice!

Veröffentlicht: 24.03.2009 um 17:07 von thE_29
Aktualisiert: 27.03.2009 um 08:55 von thE_29
Wegen diesem Bsp hier: http://www.java-forum.org/blogs/tfa/...it-spring.html und einer langen Diskussion um Singleton Patterns habe ich mir mal Google Guice und den sein Code Injection angeschaut.

Einleitung, etc.. nehmt bitte von tfa´s Blog!

Den Anfang macht das Bean. Angefangen mit dem Interface (wird nicht benötigt! Siehe Kommentar 2).
Java Code: Quelltext in neuem Fenster öffnen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package guicedemo;
 
/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2009</p>
 *
 * <p>Company: </p>
 *
 * @author Taschek Joerg
 * @version 1.0
 */
public interface Config
{
  public String getValue(String key);
 
  public void setValue(String key, String value);
}

Hier die ConfigImpl:

Java Code: Quelltext in neuem Fenster öffnen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package guicedemo;
 
import java.util.Map;
import java.util.HashMap;
 
/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2009</p>
 *
 * <p>Company: </p>
 *
 * @author Taschek Joerg
 * @version 1.0
 */
public class ConfingImpl implements Config
{
  private Map<String, String> prefs = new HashMap<String, String>();
 
  public ConfingImpl()
  {
    super();
  }
 
  public String getValue(String key) {
    return this.prefs.get(key);
  }
  
  public void setValue(String key, String value) {
    this.prefs.put(key, value);
  }
}

Bis jetzt noch kaum Unterschied als bei tfa! Jetzt kommen die 2 Klassen die mit Bean arbeiten wollen.

ReadController:
Java Code: Quelltext in neuem Fenster öffnen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package guicedemo;
 
import com.google.inject.Inject;
 
/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2009</p>
 *
 * <p>Company: </p>
 *
 * @author Taschek Joerg
 * @version 1.0
 */
public class ReadController
{
 
  private Config conf;
 
  @Inject  
  public ReadController(Config conf)
  {
    super();
    this.conf = conf;
  }
  
  public void printConfig() 
  {
    System.out.println("Konfiguration: Test=" + this.conf.getValue("Test"));
  }
}

Wie man hier sieht, hat man hier mehr keinen leeren (oder Standard) Konstruktor sondern einen mit dem Bean als Namen. Desweiteren ist das @Inject sehr wichtig (ohne dem funktioniert der ganze Zauber auch nicht).

WriteController:
Java Code: Quelltext in neuem Fenster öffnen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package guicedemo;
 
import com.google.inject.Inject;
 
/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2009</p>
 *
 * <p>Company: </p>
 *
 * @author Taschek Joerg
 * @version 1.0
 */
public class WriteController
{
 
  private Config conf;
 
  @Inject  
  public WriteController(Config conf)
  {
    super();
    this.conf = conf;
  }
  
  
  public void doConfig() {
    this.conf.setValue("Test", "42");
  }
  
}

Auch hier hat man wieder einen Konstruktor mit dem Interface, sowie das @Inject nicht vergessen.

Bei Google Guice hat man keine XML Datei, was angibt welches Interface wohingebunden wird. Stattdessen macht man das in einem Interface (Module) oder einer abstrakten Klasse (AbstractModule).

Ich habe diese Konfiguration in meiner main Klasse gemacht. Indem sie von AbstractModule abgeleitet ist und die Methode configure überschreibt. Man könnte es auch über eine anonyme Klasse übergeben (so mache ich es im 2ten Bsp!).

Java Code: Quelltext in neuem Fenster öffnen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package guicedemo;
 
import com.google.inject.AbstractModule;
import com.google.inject.Scopes;
import com.google.inject.Injector;
import com.google.inject.Guice;
 
/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2009</p>
 *
 * <p>Company: </p>
 *
 * @author Taschek Joerg
 * @version 1.0
 */
public class Main extends AbstractModule
{
  public Main()
  {
    super();
  }
  
  @Override
  protected void configure()
  {
    //hier wird es zugewiesen
    bind(Config.class)
        .to(ConfingImpl.class)
        .in(Scopes.SINGLETON);
  }
 
 
  public static void main(String args[])
  {
    Injector injector = Guice.createInjector(new Main()); //holt den Injector
    ReadController reader = injector.getInstance(ReadController.class); //instanziert die Klasse
    reader.printConfig();
    WriteController writer = injector.getInstance(WriteController.class); //nochmals die Klasse
    writer.doConfig();
    reader.printConfig();    
  }
 
}

Wie man sieht, MUSS man sich den Injector über eine statische Methode holen. Diesen gibt man ein Module oder ein AbstractModule an, welches ungefähr die gleiche Arbeit verrichtet, wie unter spring die XML Datei.
Es gibt an, worauf unsere Bean/Interface gebunden werden soll.

Ausgabe:
Zitat:
Konfiguration: Test=null
Konfiguration: Test=42
Hier noch ein Bsp wie man 2 Beans konfigurieren kann.
Es ist nicht zwingend notwendig, dass alle Klassen diese Beans im Konstruktor haben.

Hier das neue Interface:
Java Code: Quelltext in neuem Fenster öffnen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package guicedemo;
 
/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2009</p>
 *
 * <p>Company: </p>
 *
 * @author Taschek Joerg
 * @version 1.0
 */
public interface Demo
{
  public int getDemoWert();
}

Die Impl dazu:
Java Code: Quelltext in neuem Fenster öffnen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package guicedemo;
 
/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2009</p>
 *
 * <p>Company: </p>
 *
 * @author Taschek Joerg
 * @version 1.0
 */
public class DemoImpl implements Demo
{
  private static int var = 0; //um zu sehen wie oft es instanziert wird
  
  public DemoImpl()
  {
    super();
    var++;
  }
 
  public int getDemoWert()
  {
    return var;
  }
}

Der WriteController ist UNVERÄNDERT (also der Konstruktor hat weiterhin nur 1 Parameter).

Neuer ReadController:
Java Code: Quelltext in neuem Fenster öffnen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package guicedemo;
 
import com.google.inject.Inject;
 
/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2009</p>
 *
 * <p>Company: </p>
 *
 * @author Taschek Joerg
 * @version 1.0
 */
public class ReadController
{
 
  private Config conf;
  private Demo demo;
 
  @Inject  
  public ReadController(Config conf, Demo demo) //zusätzlicher parameter
  {
    super();
    this.conf = conf;
    this.demo = demo;
  }
  
  public void printConfig() 
  {
    System.out.println("Konfiguration: Test=" + this.conf.getValue("Test") + "  DEMO WERT: " + demo.getDemoWert());
  }
}

Wie man sieht, hat man hier einen zusätzlichen Parameter, aber das stellt kein Problem dar.

Neue Main:
Java Code: Quelltext in neuem Fenster öffnen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package guicedemo;
 
import com.google.inject.AbstractModule;
import com.google.inject.Scopes;
import com.google.inject.Injector;
import com.google.inject.Guice;
 
/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2009</p>
 *
 * <p>Company: </p>
 *
 * @author Taschek Joerg
 * @version 1.0
 */
public class Main
{
  public static void main(String args[])
  {
    //mit anonamyer Klasse instanzieren
    Injector injector = Guice.createInjector(new AbstractModule(){
      @Override
      protected void configure()
      {
        //hier wird es zugewiesen
        bind(Config.class).to(ConfingImpl.class).in(Scopes.SINGLETON);
        bind(Demo.class).to(DemoImpl.class).in(Scopes.SINGLETON);
 
      }
    });
    ReadController reader = injector.getInstance(ReadController.class);
    reader.printConfig();
    WriteController writer = injector.getInstance(WriteController.class);
    writer.doConfig();
    reader.printConfig();
  }
 
}

Habe den Injector auf eine anonyme Klasse umgebaut und die Ausgabe ist wiefolgt:
Zitat:
Konfiguration: Test=null DEMO WERT: 1
Konfiguration: Test=42 DEMO WERT: 1
Wie man sieht, geht Code Injection mit Google Guice recht leicht.
"Dependency/Code Injection mit Google Guice!" bei Mister Wong speichern "Dependency/Code Injection mit Google Guice!" bei YiGG.de speichern "Dependency/Code Injection mit Google Guice!" bei Google speichern "Dependency/Code Injection mit Google Guice!" bei del.icio.us speichern
Kategorie: Kategorielos
Hits 844 Kommentare 5 Hinweis auf diesen Blog-Eintrag per E-Mail verschicken
« Zurück     Startseite des Blogs     Nächste »
Kommentare 5

Kommentare

  1. Alt
    Es wird nicht gezwungenremaßen ein Interface benötigt. Man kann von Guice auch konkrete Klassen injecten lassen
    permalink
    Veröffentlicht: 25.03.2009 um 02:10 von KSG9|sebastian KSG9|sebastian ist offline
  2. Alt
    Benutzerbild von thE_29
    Jo, du hast recht es geht auch ohne Interface!

    Dann muss der Konstruktor aber auch die Impl Klasse erwarten und nicht das Interface!

    So wird es gebunden:
    Java Code: Quelltext in neuem Fenster öffnen
    1
    
    bind(DemoImpl.class).in(Scopes.SINGLETON);

    So sieht dann der Konstruktor aus:
    Java Code: Quelltext in neuem Fenster öffnen
    1
    2
    3
    4
    5
    6
    7
    
      @Inject
      public ReadController(Config conf, DemoImpl demo) 
      {
        super();
        this.conf = conf;
        this.demo = demo;
      }
    permalink
    Veröffentlicht: 25.03.2009 um 08:56 von thE_29 thE_29 ist offline
  3. Alt
    find das beispiel irgendwie unnötig kompliziert und verwirrend...
    wieso die config und wieso readcontroller und writecontroller? wieso nicht einfach n interface + implementierung?
    Ist zwar im prinzip das gleiche aber durch die namen sehr verwirrend imo...
    permalink
    Veröffentlicht: 26.03.2009 um 18:36 von raiL raiL ist offline
  4. Alt
    Benutzerbild von masta // thomas
    ich bin btw. großer fan von guice meine letzten beiden projekte haben davon profitieren können. einen guten einblick verschafft die präsentation von bob lee (crazybob.org: Introduction to Guice Video (Redux)) (ein übrigens durchaus cooler typ wie ich finde )
    permalink
    Veröffentlicht: 27.03.2009 um 08:45 von masta // thomas masta // thomas ist offline
  5. Alt
    Benutzerbild von thE_29
    @raiL: Habe das Bsp so gewählt, weil tfa das auch so hatte und weil ich zeigen wollte, dass der Konstruktor nicht immer alle Beans haben muss, aber trotzdem instanziert wird.
    Aber ich kann auch noch ein simples Bsp machen!

    @masta: Jo, das Code/Dependency Injection ist mit Guice um einiges leichter als mit spring.
    permalink
    Veröffentlicht: 27.03.2009 um 08:55 von thE_29 thE_29 ist offline
 

Alle Zeitangaben in WEZ +1. Es ist jetzt 02:09 Uhr.


Powered by vBulletin® Version 3.8.3 (Deutsch)
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.2
Thanks for Smilies by smilies.4-user.de