Ubrizgavanje prototipa graha u pojedinačnu primjerak u proljeće

1. Pregled

U ovom brzom članku prikazat ćemo različite pristupe ubrizgavanje prototipa graha u pojedinačnu instancu. Razgovarat ćemo o slučajevima korištenja i prednostima / nedostacima svakog scenarija.

Prema zadanim postavkama proljetni grah je jednostruki. Problem nastaje kada pokušavamo povezati grah različitih opsega. Na primjer, prototip graha u singleton. Ovo je poznato kaoproblem injekcije graha s opsegom.

Da biste saznali više o opsegu graha, ovo je dobro mjesto za početak.

2. Problem ubrizgavanja prototipa graha

Da bismo opisali problem, konfigurirajmo sljedeći grah:

@Configuration javna klasa AppConfig {@Bean @Scope (ConfigurableBeanFactory.SCOPE_PROTOTYPE) public PrototypeBean prototypeBean () {return new PrototypeBean (); } @Bean public SingletonBean singletonBean () {return new SingletonBean (); }}

Primijetite da prvi grah ima prototip opsega, drugi je singleton.

Sada, ubrizgimo grah s opsegom prototipa u singleton - a zatim izlažemo ako putem getPrototypeBean () metoda:

javna klasa SingletonBean {// .. @Autowired private PrototypeBean prototypeBean; public SingletonBean () {logger.info ("Stvorena instanca Singletona"); } javni PrototypeBean getPrototypeBean () {logger.info (String.valueOf (LocalTime.now ())); return prototypeBean; }}

Zatim, učitajmo ApplicationContext i dvaput uzmite grah singleton:

javna statička void glavna (String [] args) baca InterruptedException {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext (AppConfig.class); SingletonBean firstSingleton = context.getBean (SingletonBean.class); PrototypeBean firstPrototype = firstSingleton.getPrototypeBean (); // još jednom dobiti instancu benda singletona SingletonBean secondSingleton = context.getBean (SingletonBean.class); PrototypeBean secondPrototype = secondSingleton.getPrototypeBean (); isTrue (firstPrototype.equals (secondPrototype), "Treba vratiti istu instancu"); }

Evo rezultata s konzole:

Singleton Bean stvorio je prototip Bean stvoren 11: 06: 57.894 // trebao bi stvoriti još jedan primjerak prototipa graha ovdje 11: 06: 58.895

Oba graha su inicijalizirana samo jednom, pri pokretanju konteksta aplikacije.

3. Ubrizgavanje ApplicationContext

Također možemo ubrizgati ApplicationContext izravno u grah.

Da biste to postigli, upotrijebite @Autowire napomena ili implementirati ApplicationContextAware sučelje:

javna klasa SingletonAppContextBean implementira ApplicationContextAware {private ApplicationContext applicationContext; javni PrototypeBean getPrototypeBean () {povratak applicationContext.getBean (PrototypeBean.class); } @Override javna void setApplicationContext (ApplicationContext applicationContext) baca BeansException {this.applicationContext = applicationContext; }}

Svaki put kad getPrototypeBean () poziva se nova metoda PrototypeBean bit će vraćen iz ApplicationContext.

Međutim, ovaj pristup ima ozbiljnih nedostataka. To je u suprotnosti s načelom inverzije upravljanja, jer ovisnosti izravno tražimo od spremnika.

Također, prototipirani grah dohvaćamo iz applicationContext unutar SingletonAppcontextBean razred. To značispajanje koda s Spring Frameworkom.

4. Metoda ubrizgavanja

Drugi način rješavanja problema je ubrizgavanje metode s @Pogledaj bilješka:

@Component javna klasa SingletonLookupBean {@Lookup public PrototypeBean getPrototypeBean () {return null; }}

Proljeće će nadvladati getPrototypeBean () metoda označena sa @Pogledaj. Zatim registrira grah u kontekst aplikacije. Kad god zatražimo getPrototypeBean () metoda, vraća novu PrototypeBean primjer.

Za generiranje bajt-koda upotrebljavat će CGLIB odgovoran za dohvaćanje PrototypeBean iz konteksta aplikacije.

5. javax.injekt API

Postavljanje zajedno s potrebnim ovisnostima opisano je u ovom članku o ožičenju proljeća.

Evo graha singletona:

javna klasa SingletonProviderBean {@Autowired privatni davatelj myPrototypeBeanProvider; javni PrototypeBean getPrototypeInstance () {return myPrototypeBeanProvider.get (); }}

Koristimo Pružatelj uslugasučelje ubrizgati prototip graha. Za svakoga getPrototypeInstance () poziv metode, myPrototypeBeanProvider.get () metoda vraća novu instancu PrototypeBean.

6. Obuhvaćeni proxy

Prema zadanim postavkama Spring sadrži referencu na stvarni objekt za izvođenje ubrizgavanja. Ovdje stvaramo proxy objekt za povezivanje stvarnog objekta s ovisnim.

Svaki put kad se pozove metoda na proxy objektu, proxy sam odlučuje hoće li stvoriti novu instancu stvarnog objekta ili ponovno upotrijebiti postojeću.

Da bismo to postavili, mijenjamo Appconfig razred za dodavanje novog @Skop napomena:

@Scope (vrijednost = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)

Prema zadanim postavkama Spring koristi CGLIB knjižnicu za izravnu potklasu objekata. Da bismo izbjegli upotrebu CGLIB-a, način rada proxyja možemo konfigurirati s ScopedProxyMode.SUČELJA, umjesto toga koristiti JDK dinamički proxy.

7. ObjectFactory Sučelje

Spring pruža ObjectFactory sučelje za proizvodnju objekata na zahtjev dane vrste:

javna klasa SingletonObjectFactoryBean {@Autowired private ObjectFactory prototypeBeanObjectFactory; javni PrototypeBean getPrototypeInstance () {vratiti prototypeBeanObjectFactory.getObject (); }}

Pogledajmo getPrototypeInstance () metoda; getObject () vraća potpuno novi primjerak PrototypeBean za svaki zahtjev. Ovdje imamo veću kontrolu nad inicijalizacijom prototipa.

Također, ObjectFactory je dio okvira; to znači izbjegavanje dodatnih postavki kako biste koristili ovu opciju.

8. Stvorite grah tijekom izvođenja koristeći java.util.Funkcija

Druga je mogućnost stvoriti prototipove instanci graha tijekom izvođenja, što nam također omogućuje dodavanje parametara instancama.

Da bismo vidjeli primjer toga, dodajmo polje imena u naš PrototypeBean razred:

javna klasa PrototypeBean {naziv privatnog niza; javni PrototypeBean (ime niza) {this.name = name; logger.info ("Instanca prototipa" + ime + "stvoreno"); } // ...}

Dalje, ubrizgat ćemo tvornicu graha u naš singleton grah koristeći se java.util.Funkcija sučelje:

javna klasa SingletonFunctionBean {@Autowired private Function beanFactory; public PrototypeBean getPrototypeInstance (naziv niza) {PrototypeBean bean = beanFactory.apply (name); grah za povratak; }}

Konačno, moramo definirati tvornički grah, prototip i singleton grah u našoj konfiguraciji:

@Configuration javna klasa AppConfig {@Bean javna funkcija beanFactory () {return name -> prototypeBeanWithParam (name); } @Bean @Scope (value = "prototype") public PrototypeBean prototypeBeanWithParam (naziv niza) {return new PrototypeBean (name); } @Bean public SingletonFunctionBean singletonFunctionBean () {return new SingletonFunctionBean (); } // ...}

9. Ispitivanje

Napišimo sada jednostavan JUnit test s kojim ćemo vježbati slučaj ObjectFactory sučelje:

@Test javna praznina givenPrototypeInjection_WhenObjectFactory_ThenNewInstanceReturn () {AbstractApplicationContext context = new AnnotationConfigApplicationContext (AppConfig.class); SingletonObjectFactoryBean firstContext = context.getBean (SingletonObjectFactoryBean.class); SingletonObjectFactoryBean secondContext = context.getBean (SingletonObjectFactoryBean.class); PrototypeBean firstInstance = firstContext.getPrototypeInstance (); PrototypeBean secondInstance = secondContext.getPrototypeInstance (); assertTrue ("Očekuje se nova instanca", firstInstance! = secondInstance); }

Nakon uspješnog pokretanja testa to možemo vidjeti svaki put getPrototypeInstance () pozvana metoda, stvoren je novi prototip instance graha.

10. Zaključak

U ovom kratkom vodiču naučili smo nekoliko načina za ubrizgavanje prototipa graha u pojedinačnu instancu.

Kao i uvijek, cjelovit kôd za ovu lekciju možete pronaći na GitHub projektu.


$config[zx-auto] not found$config[zx-overlay] not found