Kratki vodič za opsege proljetnog graha

1. Pregled

U ovom brzom vodiču naučit ćete o različitim vrstama opsega graha u okviru Spring.

Opseg graha definira životni ciklus i vidljivost tog zrna u kontekstu u kojem se koristi.

Najnovija verzija Spring framework-a definira 6 vrsta opsega:

  • jednokrevetna
  • prototip
  • zahtjev
  • sjednica
  • primjena
  • web utičnica

Posljednja četiri spomenuta opsega zahtjev, sesija, prijava i web utičnica dostupni su samo u web-svjesnoj aplikaciji.

2. Singleton Scope

Definiranje graha sa jednokrevetna doseg znači da spremnik stvara jednu instancu tog graha i svi zahtjevi za tim imenom graha vratit će isti objekt koji je predmemoriran. Sve promjene na objektu odrazit će se na sve reference na grah. Ovaj je opseg zadana vrijednost ako nije naveden nijedan drugi opseg.

Stvorimo a Osoba entitet koji predstavlja pojam opsega:

javni razred Osoba {ime privatnog niza; // standardni konstruktor, getteri i postavljači}

Poslije definiramo grah sa jednokrevetna opseg pomoću @Skop napomena:

@Bean @Scope ("singleton") javna Osoba personSingleton () {return new Person (); }

Također možemo koristiti konstantu umjesto znaka Niz vrijednost na sljedeći način:

@Scope (value = ConfigurableBeanFactory.SCOPE_SINGLETON)

Sada nastavljamo s pisanjem testa koji pokazuje da će dva objekta koja se odnose na isti grah imati iste vrijednosti, čak i ako samo jedan od njih promijeni svoje stanje, budući da se oba pozivaju na istu instancu graha:

privatni statički završni niz NAME = "John Smith"; @Test javna praznina givenSingletonScope_whenSetName_thenEqualNames () {ApplicationContext applicationContext = new ClassPathXmlApplicationContext ("scopes.xml"); Person personSingletonA = (Person) applicationContext.getBean ("personSingleton"); Person personSingletonB = (Person) applicationContext.getBean ("personSingleton"); personSingletonA.setName (NAME); Assert.assertEquals (NAME, personSingletonB.getName ()); ((AbstractApplicationContext) applicationContext) .close (); }

The opsezi.xml datoteka u ovom primjeru treba sadržavati xml definicije korištenog graha:

3. Opseg prototipa

Grah sa prototip scope vratit će drugu instancu svaki put kad se zatraži iz spremnika. Definira se postavljanjem vrijednosti prototip prema @Skop napomena u definiciji graha:

@Bean @Scope ("prototype") public Person personPrototype () {return new Person (); }

Također bismo mogli upotrijebiti konstantu kao za singleton opseg:

@Scope (vrijednost = ConfigurableBeanFactory.SCOPE_PROTOTYPE)

Sada ćemo napisati sličan test kao i prije koji pokazuje da će dva objekta koja traže isto ime graha s prototipom opsega imati različita stanja, jer se više ne odnose na istu instancu graha:

privatni statički završni niz NAME = "John Smith"; privatni statički završni niz NAME_OTHER = "Anna Jones"; @Test javna praznina givenPrototypeScope_whenSetNames_thenDifferentNames () {ApplicationContext applicationContext = new ClassPathXmlApplicationContext ("scopes.xml"); Person personPrototypeA = (Person) applicationContext.getBean ("personPrototype"); Person personPrototypeB = (Person) applicationContext.getBean ("personPrototype"); personPrototypeA.setName (NAME); personPrototypeB.setName (NAME_OTHER); Assert.assertEquals (NAME, personPrototypeA.getName ()); Assert.assertEquals (NAME_OTHER, personPrototypeB.getName ()); ((AbstractApplicationContext) applicationContext) .close (); } 

The opsezi.xml datoteka slična je onoj koja je predstavljena u prethodnom odjeljku, dok dodajete xml definiciju za grah s prototip opseg:

4. Opseg svjesnog weba

Kao što je spomenuto, postoje četiri dodatna područja koja su dostupna samo u kontekstu web-svjesne aplikacije. Oni se rjeđe koriste u praksi.

The zahtjev doseg stvara instancu graha za jedan HTTP zahtjev dok sesija Opseg se stvara za HTTP sesiju.

The primjena scope stvara primjerak graha za životni ciklus a ServletContext i web utičnica opseg ga stvara za određenu WebSocket sjednica.

Stvorimo klasu koja će se koristiti za instanciranje graha:

javna klasa HelloMessageGenerator {privatna niz poruka; // standardni geter i postavljač}

4.1. Opseg zahtjeva

Grah možemo definirati sa zahtjev opseg pomoću @Skop napomena:

@Bean @Scope (value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS) public HelloMessageGenerator requestScopedBean () {return new HelloMessageGenerator (); }

The proxyMode atribut je neophodan jer u trenutku instanciranja konteksta web aplikacije nema aktivnog zahtjeva. Spring će stvoriti proxy koji će se ubrizgati kao ovisnost i instancirati ciljni grah kada je to potrebno u zahtjevu.

Također možemo koristiti i @RequestScope sastavljena napomena koja služi kao prečac za gornju definiciju:

@Bean @RequestScope public HelloMessageGenerator requestScopedBean () {return new HelloMessageGenerator (); }

Dalje, možemo definirati kontroler koji ima ubrizganu referencu na requestScopedBean. Moramo pristupiti istom zahtjevu dva puta kako bismo testirali web specifične domete.

Ako prikažemo poruka svaki put kad se zahtjev pokrene, možemo vidjeti da se vrijednost resetira na null, iako se kasnije mijenja u metodi. To je zato što se za svaki zahtjev vraća različita instanca graha.

@Controller javna klasa ScopesController {@Resource (name = "requestScopedBean") HelloMessageGenerator requestScopedBean; @RequestMapping ("/ scopes / request") javni niz getRequestScopeMessage (konačni model modela) {model.addAttribute ("previousMessage", requestScopedBean.getMessage ()); requestScopedBean.setMessage ("Dobro jutro!"); model.addAttribute ("currentMessage", requestScopedBean.getMessage ()); povratak "scopesExample"; }}

4.2. Opseg sjednice

Grah možemo definirati sa sjednica opseg na sličan način:

@Bean @Scope (value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS) javni HelloMessageGenerator sessionScopedBean () {return new HelloMessageGenerator (); }

Tu je i namjenska sastavljena bilješka koju možemo koristiti za pojednostavljivanje definicije graha:

@Bean @SessionScope javni HelloMessageGenerator sessionScopedBean () {vratiti novi HelloMessageGenerator (); }

Zatim definiramo kontroler s referencom na sessionScopedBean. Opet, moramo pokrenuti dva zahtjeva kako bismo pokazali da vrijednost poruka polje je isto za sesiju.

U ovom slučaju, kada se zahtjev podnosi prvi put, vrijednost poruka je null. Ali kad se jednom promijeni, ta se vrijednost zadržava za naknadne zahtjeve jer se ista instanca graha vraća tijekom cijele sesije.

@Controller javna klasa ScopesController {@Resource (name = "sessionScopedBean") HelloMessageGenerator sessionScopedBean; @RequestMapping ("/ scopes / session") javni String getSessionScopeMessage (konačni model modela) {model.addAttribute ("previousMessage", sessionScopedBean.getMessage ()); sessionScopedBean.setMessage ("Dobar dan!"); model.addAttribute ("currentMessage", sessionScopedBean.getMessage ()); povratak "scopesExample"; }}

4.3. Opseg primjene

The primjena scope stvara primjerak graha za životni ciklus a ServletContext.

Ovo je slično opsegu singletona, ali postoji vrlo važna razlika u pogledu opsega graha.

Kad su grah primjena opsega iste instance graha dijeli se kroz više aplikacija temeljenih na servletima koje se izvode u istoj ServletContext, dok se grah s jednim opsegom ograničava samo na jedan kontekst aplikacije.

Stvorimo grah sa primjena opseg:

@Bean @Scope (value = WebApplicationContext.SCOPE_APPLICATION, proxyMode = ScopedProxyMode.TARGET_CLASS) public HelloMessageGenerator applicationScopedBean () {return new HelloMessageGenerator (); }

Analogno kao i za zahtjev i sjednica opsega, možemo koristiti kraću verziju:

@Bean @ApplicationScope public HelloMessageGenerator applicationScopedBean () {return new HelloMessageGenerator (); }

Sada, kreirajmo kontroler koji upućuje na ovaj grah:

@Controller javna klasa ScopesController {@Resource (name = "applicationScopedBean") HelloMessageGenerator applicationScopedBean; @RequestMapping ("/ scopes / application") javni String getApplicationScopeMessage (konačni model modela) {model.addAttribute ("previousMessage", applicationScopedBean.getMessage ()); applicationScopedBean.setMessage ("Dobar dan!"); model.addAttribute ("currentMessage", applicationScopedBean.getMessage ()); povratak "scopesExample"; }}

U ovom slučaju vrijednost poruka jednom postavljen u applicationScopedBean zadržat će se za sve naredne zahtjeve, sesije, pa čak i za drugu aplikaciju servleta koja će pristupiti ovom grahu, pod uvjetom da se izvodi u istom ServletContext.

4.4. Opseg WebSocket

Konačno, stvorimo grah sa web utičnica opseg:

@Bean @Scope (scopeName = "websocket", proxyMode = ScopedProxyMode.TARGET_CLASS) javni HelloMessageGenerator websocketScopedBean () {return new HelloMessageGenerator (); }

Grah s opsegom WebSocket pri prvom pristupu pohranjuje se u WebSocket atributi sesije. Zatim se vraća ista instanca graha kad god se tom grahu pristupi tijekom cijele WebSocket sjednica.

Možemo također reći da pokazuje jednolično ponašanje, ali ograničeno na a WebSocket samo sesija.

5. Zaključak

Pokazali smo različite opsege graha koje nudi Spring i koje su namjene.

Provedbu ovog vodiča možete pronaći u projektu GitHub - ovo je projekt zasnovan na Eclipseu, pa bi ga trebalo lako uvesti i pokrenuti kakav jest.