jAbLoK

Google Guice

Zasláno do Java by Pavel Kolesnikov na Březen 14th, 2007

Pozorováním programátorů v divočině člověk snadno zjistí, že je zjevně zábavnější vytvářet obecné frameworky nežli aplikace, které něco opravdu dělají. Takže není divu, že máme další z mnoha frameworků poskytující podporu pro organizaci aplikace podle vzoru  inversion of control .

Název naznačuje, proč zrovna tenhle kousek stojí za popzornost: než byl vypuštěn do světa jako open-source projekt, tak byl po několik měsíčů prakticky ověřován na Gůglích  "mission critical applications"  (zdroj) — nevím, které přesně, někde jsem sice v této souvislost četl o AdWords, ale už si nevybavuju, kde.

Stručná charakteristika:

  • řeší jen a pouze dependency injection + integraci s servletovým kontejnerem
  • vyžaduje Javu 5, a je silně postaven na generických typech a anotacích
  • má být svižný (čemuž bych věřil, protože letmý pohled do zdrojáků naznačuje naprostou absenci reflection)

Jak se s Guice programuje?

Máme-li třídu závislou na implementaci nějakého rozhraní, označíme příslušný setter (nebo konstruktor) anotací @Inject:

import com.google.inject.Inject;

public class Client {
     private Counter counter;

    @Inject
    public void setCounter(Counter counter) {
        this.counter = counter;
    }

    public void test() {
        counter.ping();
        counter.ping();
        System.out.println(counter.getValue());
    }
}

Co nám vlastně do proměnné counter přilítne, určí programátor tak, že vyrobí, tzv. modul, tedy implementaci rozhraní com.google.inject.Module, ve většině newebových případů pak potomka com.google.inject.AbstractModule a pro webové aplikace má k dispozici rovnou com.google.inject.servlet.ServletModule.

V modulu si pak namapuje rozhraní na konkrétní implementaci a vymezí rozsah platnosti instancí, třeba takhle:

import com.google.inject.Scopes;
import com.google.inject.servlet.ServletModule;

public class MyModule extends AbstractModule {
    protected void configure() {
        super.configure();
        bind(Counter.class).to(CounterImpl.class).in(Scopes.SINGLETON);
    }
}

Výše uvedený kód říká, že do metod označených anotací com.google.inject.Inject, které přijímají parametr typu Counter se předá vždy jedna a tatáž instance (ano, to je to in(Scopes.SINGLETON)) třídy CounterImpl.

A pokud má náš kód běžet v prostředí webového kontejneru a modul vyrobíme rozšířením třídy ServletModule, pak máme — nejspíš v souladu s očekáváním — další dvě možnosti nastavení rozsahu platnosti injektovaných tříd, a to com.google.inject.servlet.ServletScopes.REQUEST a SESSION.

Pokračování možná jindy.