Wiki | Fórum | Home | Hľadať v Home | Perly |
Spring 3.0, JEE 6 a anotácie pre automatické prepájanie komponentov (Java)
  • Zobraziť
  • Upraviť
  • História úprav
  • Tlačiť
Hľadať:
Prejsť:

Obsah (skryť)

  1. 1. JSR-330
  2. 2. Springovské anotácie
  3. 3. Vzťah k JSR-250
  4. 4. Vzťah k Springu
  5. 5. Referencie
  6. 6. Komentáre
    1. 6.1 ~Cassara — 23 January 2012, 18:50
    2. 6.2 ~Quiana — 28 August 2011, 22:21
    3. 6.3 ~jonn3 — 15 June 2011, 13:59
    4. 6.4 ~jonn3 — 15 June 2011, 12:12
    5. 6.5 ~jonn2 — 15 June 2011, 10:24
    6. 6.6 ~jonn1 — 15 June 2011, 08:35
    7. 6.7 ~jonn1 — 02 June 2011, 09:44
    8. 6.8 ~jonn2 — 02 June 2011, 05:17
    9. 6.9 ~jonn3 — 02 June 2011, 00:46
    10. 6.10 ~dfhsfjsj — 26 May 2011, 15:49
    11. 6.11 ~jonn2 — 26 April 2011, 04:44
    12. 6.12 ~jonn2 — 19 March 2011, 16:54
    13. 6.13 ~jonn3 — 17 March 2011, 08:56
    14. 6.14 ~dfgrhbi3g8 — 14 March 2011, 00:53
    15. 6.15 ~jonn2 — 13 March 2011, 02:20
    16. 6.16 ~jonn1 — 28 February 2011, 08:06
    17. 6.17 ~jonn1 — 17 February 2011, 19:02

Od čias Springu 2.5 je k dispozícii sada anotácií, ktoré riešia dependency injection. (Viď existujúci článok.) V nej boli dané k dispozícii jednak springovské anotácie (@Component a pod.) a jednak anotácie z JSR-250 (najmä @Resource).

Od tých čias sa situácia ešte ,,skomplikovala". Medzičasom totiž vyšla finálna špecifikácia JEE6, ktorá rieši dependency injection v rámci dvoch JSR.

  • JSR-330: Dependency Injection for Java vznikla z potrieb DI frameworkov Spring a Google Guice, kde dali hlavy dohromady Rod Johnson a Crazy Bob Lee.
  • JSR-299: Contexts and Dependency Injection for the Java EE platform (alias Web Beans, pod vedením Gavina Kinga z JBossu), ktoré stavajú na JSR-330, a obohacujú DI o ďalšie vlastnosti. Táto JSR je v podstate abstrakciou funkcionality, ktorú poskytuje JBoss Seam.

Spočiatku to vyzeralo tak, že špecifikácie vznikli vzájomne ,,na truc". Vo úvodnej fáze review Red Had (teda JBoss) vyjadril hlboké pochybnosti o zmysle JSR-330 (niet divu, veď sa to isté snažil riešiť po svojom). Po troche politických bojov sa však obe špecifikácie zladili, a Red Hat ju odsúhlasil s dodatkom, že očakáva ďalšiu spoluprácu medzi oboma štandardmi. Ako tvrdí viacero článkov, oba treba chápať ako vzťah známy JDBC a JPA. Existuje v nich prienik, ale jedna (299) je nadstavbou druhej (330). (Je len zaujímavé, že IBM neskôr zmenila svoj názor, pretože vidí v JSR-330 značné technické nedostatky a nesplnenie zámeru.)

1.  JSR-330

Táto špecifikácia definuje päť anotácií a jeden interfejs, ktorými možno dosiahnuť DI. Samotnú implementáciu a spôsob prepájania však ponecháva na konkrétnu implementáciu prislušného DI frameworku.

Všetky anotácie sú z balíčka javax.inject.

  • @Inject - anotuje konštruktory, metódy či inštančné premenné, do ktorých majú byť injektnuté inštancie beanov.
  • @Qualifier - anotácia anotácií, ktorými možno bližšie obmedziť / špecifikovať injektovanie.
  • @Scope - metaanotácia, ktorá definuje anotácie zodpovedajúce scopeom, teda rozsahom platnosti. V prípade injektovania sa implicitne (ak chýba anotácia) predpokladá prototype scope (teda non-singleton), čiže s každým injektovaním sa vytvára nová inštancia injektovaného beanu
  • @Singleton — anotácia typu @Scope, ktorá indikuje, že anotovaný typ bude pri injektovaní používaný ako singleton.
  • @Named - umožní bližšie špecifikovať injektovaný bean. Odporúča sa používať len v prípade kontajnerov, ktoré označujú beany identifikátorom (čo je prípad Springu). V špecifikácii JEE6 má ešte jeden význam: ak je ňou anotovaná trieda, možno k nej pristupovať v rámci expression language (napr. v JSF šablónach).

Ukážme si jednoduchý príklad v ktorom sa používajú anotácie.

2.  Springovské anotácie

Majme interfejs na generovanie citátov:

package sk.novotnyr.quotes;

public interface QuoteGenerator {
  public String getQuote();
}
[$[Get Code]]

a jeho jednoduchú implementáciu:

package sk.novotnyr.quotes;

public class HardwiredQuoteGenerator implements QuoteGenerator {

  public String getQuote() {
    return "Spring is gr8";
  }

}
[$[Get Code]]

A okrem toho majme triedu, ktorá bude vypisovať citáty na štandardný výstup:

public class QuotePrinter {
  private QuoteGenerator quoteGenerator;

  public void print() {
    String quote = quoteGenerator.getQuote();
    System.out.println(quote);
  }

  // gettre a settre
}
[$[Get Code]]

V JSR-330 je k dispozícii anotácia @Inject, ktorá indikuje nutnosť injektovania inštancie. Keďže QuotePrinter vyžaduje inštanciu QuoteGeneratora, injektovanie označíme anotáciou.

public class QuotePrinter {
  @Inject
  private QuoteGenerator quoteGenerator;

  public void print() {
    String quote = quoteGenerator.getQuote();
    System.out.println(quote);
  }
}
[$[Get Code]]

Do quoteGeneratora sa automaticky nawireuje implementácia príslušného rozhrania (prebieha detekcia podľa typu, v kontexte sa musí nájsť práve jedna implementácia, inak nastane výnimka). Ak použijeme @Inject na inštančnej premennej, nemusíme dokonca poskytnúť gettre a settre.

Ostáva ešte jedna ,,drobnosť: ako zaregistrovať beany v aplikačnom kontexte? Klasických možností je viac:

  • buď ich uvedieme do XML deskriptora aplikačného kontextu
  • alebo ich anotujeme pomocou springovskej anotácie @Component

Treťou možnosťou je využitie JSR-330 anotácie Named. Ak je ňou anotovaný typ, Spring ho automaticky odhalí a zaradí do aplikačného kontextu.

@Named
public class QuotePrinter {
[$[Get Code]]

a

@Named
public class QuoteGenerator {
[$[Get Code]]

Teraz už môžeme vytvoriť aplikačný kontext. V tomto prípade môžeme s výhodou využiť triedu AnnotationConfigApplicationContext:

AnnotationConfigApplicationContext context
   = new AnnotationConfigApplicationContext("sk.novotnyr.quotes");
QuotePrinter printer = context.getBean(QuotePrinter.class);
for (int i = 0; i < 3; i++) {
  printer.print();
}
[$[Get Code]]

Trieda automaticky vyhľadá v balíčku sk.novotnyr.quote nielen triedy anotované ako Named, ale aj všetky triedy so springovským stereotypom @Component (teda všetky triedy anotované ako @Component, @Repository, @Service a @Controller).

Anotácia @Named môže byť použitá v prípade, že chceme pri injektovaní presnejšie vyšpecifikovať použitý bean (napr. v prípade, že sa v aplikačnom kontexte nachádza viacero implementácií daného interfejsu):

@Inject
@Named("HardwiredQuoteGenerator")
private QuoteGenerator quoteGenerator;
[$[Get Code]]

V tomto prípade sa injektne ten bean, ktorý má v triede anotáciu @Named("HardwiredQuoteGenerator").

Nezabúdajme na to, že v tomto prípade prebehne prototype injektovanie. Vytvorí sa teda toľko inštancií QuoteGeneratora, koľko je inštancií QuotePrintera. Ak chceme mať QuoteGenerator ako singleton, musíme ho tak označiť.

@Named("HardwiredQuoteGenerator")
@Singleton
public class HardwiredQuoteGenerator
[$[Get Code]]

3.  Vzťah k JSR-250

Z predošlého článku si pamätáme, že injektovanie možno dosiahnuť aj pomocou anotácií javax.annotation.Resource a javax.annotation.WebServiceRef, kde prvá z nich slúžila jednak v úlohe anotovania beanu, ktorý sa má zaviesť do kontextu, jednak v úlohe anotácie @Inject a zároveň v nej bolo možné pomenovávať beany a bližšie špecifikovať odkaz na ne (teda obe úlohy @Named).

Špecifikácia JSR-250 však uvádza, že ,,The @Resource annotation is used to declare a reference to a resource such as a data source, an enterprise bean, or an environment entry," teda anotácia @Resource deklaruje odkaz na zdroj/prostriedok, ako napr. dátový zdroj enterprise bean či premenná prostredia.

Podľa dokumentácie (The Java EE 6 Tutorial, Volume I) a špecifikácie JSR-250 je úloha tejto anotácie skôr spätá s JNDI. V prípade jej použitia na triede sa z atribútu name odvodí JNDI meno, pod ktorým sa inštancia zaregistruje do JNDI kontextu. Ak je použitá na mene, z názvu premennej sa odvodí kľúč do JNDI kontextu, z ktorého sa inštancia vytiahne.

4.  Vzťah k Springu

Spring anotáciaJSR-330 anotácia
@Component@Named na type
@Autowire@Inject
@Qualifier na inštančnej premennej/metódy@Named

5.  Referencie

  • Introduction to Contexts and Dependency Injection for the Java EE Platform
  • Announcing @javax.inject.Inject — pôvodné oznámenie Crazy Bob Leeho
  • What Is The Relation Between JSR-299 and JSR-330 In Java EE 6? Do We Need Two DI APIs?

6.  Komentáre

6.1  Cassara? — 23 January 2012, 18:50

If I communiceatd I could thank you enough for this, I'd be lying.

6.2  Quiana? — 28 August 2011, 22:21

Never seen a beettr post! ICOCBW

6.3  jonn3? — 15 June 2011, 13:59

comment4,

6.4  jonn3? — 15 June 2011, 12:12

comment2,

6.5  jonn2? — 15 June 2011, 10:24

comment1,

6.6  jonn1? — 15 June 2011, 08:35

comment6,

6.7  jonn1? — 02 June 2011, 09:44

comment4,

6.8  jonn2? — 02 June 2011, 05:17

comment6,

6.9  jonn3? — 02 June 2011, 00:46

comment1,

6.10  dfhsfjsj? — 26 May 2011, 15:49

18.txt;16;16

6.11  jonn2? — 26 April 2011, 04:44

comment1,

6.12  jonn2? — 19 March 2011, 16:54

comment4,

6.13  jonn3? — 17 March 2011, 08:56

comment6,

6.14  dfgrhbi3g8? — 14 March 2011, 00:53

base72.txt;50;50

6.15  jonn2? — 13 March 2011, 02:20

comment5,

6.16  jonn1? — 28 February 2011, 08:06

comment3,

6.17  jonn1? — 17 February 2011, 19:02

comment2,

Pridať komentár 
Autor 

Upraviť - História úprav - Tlačiť - Posledné úpravy - Posledná zmena 23. 01. 2012 18.50