A prototípus babjának beadása Singleton-példányba tavasszal

1. Áttekintés

Ebben a rövid cikkben különböző megközelítéseket mutatunk be a prototípus babot egyetlen példányba injektálják. Megbeszéljük az egyes forgatókönyvek felhasználási eseteit és előnyeit / hátrányait.

Alapértelmezés szerint a tavaszi bab egyedülálló. A probléma akkor merül fel, amikor megpróbálunk különböző hatókörű babokat drótozni. Például egy babot egy szingulettbe. Ez az úgynevezetthatókörű babinjekciós probléma.

Ha többet szeretne megtudni a bab hatóköréről, akkor ez az írás jó kezdetnek számít.

2. A bab prototípusának injekciós problémája

A probléma leírása érdekében konfiguráljuk a következő babokat:

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

Figyelje meg, hogy az első bab prototípus hatóköre, a másik egyszemélyes.

Most fecskendezzük be a prototípus hatókörű babot a szingulettbe - majd tegyük ki, ha a getPrototypeBean () módszer:

nyilvános osztály SingletonBean {// .. @Autowired private PrototypeBean prototípusBean; public SingletonBean () {logger.info ("Singleton-példány létrehozva"); } public PrototypeBean getPrototypeBean () {logger.info (String.valueOf (LocalTime.now ())); return prototípusBean; }}

Ezután töltsük fel a ApplicationContext és kétszer kapd meg az egyszemű babot:

public static void main (String [] args) dobja az InterruptedException {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext (AppConfig.class); SingletonBean firstSingleton = context.getBean (SingletonBean.class); PrototypeBean firstPrototype = firstSingleton.getPrototypeBean (); // még egyszer megkapja a singletoni bab példányt PrototypeBean secondPrototype = secondSingleton.getPrototypeBean (); isTrue (firstPrototype.equals (secondPrototype), "Ugyanazon példányt vissza kell adni"); }

Itt van a konzol kimenete:

Singleton Bean létrehozta a Bean prototípust 11: 06: 57.894 // // itt kell létrehoznia egy másik prototípus bab példányt.

Mindkét babot csak egyszer inicializálták, az alkalmazáskörnyezet indításakor.

3. Injekció ApplicationContext

Injektálhatjuk a ApplicationContext közvetlenül egy babba.

Ennek eléréséhez vagy használja a @Autowire kommentár vagy végrehajtja a ApplicationContextAware felület:

public class SingletonAppContextBean implementálja az ApplicationContextAware {private ApplicationContext applicationContext; public PrototypeBean getPrototypeBean () {return applicationContext.getBean (PrototypeBean.class); } @Orride public void setApplicationContext (ApplicationContext applicationContext) dobja a BeansException {this.applicationContext = applicationContext; }}

Minden alkalommal, amikor a getPrototypeBean () metódust hívjuk, a PrototípusBab visszatér a ApplicationContext.

Ennek a megközelítésnek azonban komoly hátrányai vannak. Ellentmond a vezérlés inverziójának elvével, mivel a függőségeket közvetlenül a konténertől kérjük.

Ezenkívül lekérjük a bab prototípusát applicationContext belül SingletonAppcontextBean osztály. Ez azt jelenti, hogya kód és a Spring Framework összekapcsolása.

4. Módszer injekció

A probléma megoldásának másik módja a @Nézz fel annotáció:

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

A tavasz felülírja a getPrototypeBean () metódussal kiegészítve @Nézz fel. Ezután bejegyzi a babot az alkalmazás kontextusába. Valahányszor kérjük a getPrototypeBean () metódust ad vissza PrototípusBab példa.

A byg-kódot a CGLIB segítségével fogja létrehozni felelős a PrototípusBab az alkalmazás kontextusából.

5. javax.injekció API

A beállítást és a szükséges függőségeket a tavaszi kábelezési cikk ismerteti.

Íme a szinglik bab:

public class SingletonProviderBean {@Autowired private Provider myPrototypeBeanProvider; public PrototypeBean getPrototypeInstance () {return myPrototypeBeanProvider.get (); }}

Használunk Szolgáltatófelület hogy beadja a prototípus babot. Az egyes getPrototypeInstance () metódushívás, a myPrototypeBeanProvider.get () metódus a. új példányát adja vissza PrototípusBab.

6. Hatókörrel rendelkező proxy

Alapértelmezés szerint Spring hivatkozást tartalmaz a valódi objektumra az injekció végrehajtásához. Itt létrehozunk egy proxyobjektumot, amely összekapcsolja a valós objektumot a függõvel.

A proxyobjektum metódusának minden egyes meghívásakor a proxy maga dönti el, hogy a valós objektum új példányát hozza-e létre, vagy újból felhasználja-e a meglévőt.

Ennek beállításához módosítjuk a Appconfig osztály új hozzáadásához @Scope kommentár:

@Scope (érték = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)

Alapértelmezés szerint a Spring a CGLIB könyvtárat használja az objektumok közvetlen alosztályozásához. A CGLIB használat elkerülése érdekében a proxy módot a gombbal konfigurálhatjuk ScopedProxyMode.INTERFESZEK, a JDK dinamikus proxy használata helyett.

7. ObjectFactory Felület

A Spring biztosítja az ObjectFactory felületet az adott típusú igény szerinti objektumok előállításához:

public class SingletonObjectFactoryBean {@Autowired private ObjectFactory prototípusBeanObjectFactory; public PrototypeBean getPrototypeInstance () {return prototypeBeanObjectFactory.getObject (); }}

Nézzük meg getPrototypeInstance () módszer; getObject () a vadonatúj példányát adja vissza PrototípusBean minden egyes kéréshez. Itt jobban ellenőrizhetjük a prototípus inicializálását.

Továbbá a ObjectFactory a keret része; ez azt jelenti, hogy elkerüljük a további beállításokat ennek az opciónak a használatához.

8. Hozzon létre egy babot futás közben java.util.Function

Egy másik lehetőség a prototípus babpéldányok futás közbeni létrehozása, amely lehetővé teszi számunkra, hogy paramétereket adjunk a példányokhoz.

Ha erre példát akarunk látni, adjunk hozzá egy névmezőt a mezőnkhöz PrototípusBab osztály:

public class PrototypeBean {private String name; public PrototypeBean (karakterlánc neve) {this.name = név; logger.info ("Prototípus példány" + név + "létrehozva"); } // ...}

Ezután egy babgyárat fogunk befecskendezni a szingulbabunkba a java.util.Function felület:

public class SingletonFunctionBean {@Autowired private Function beanFactory; public PrototypeBean getPrototypeInstance (String name) {PrototypeBean bab = beanFactory.apply (név); visszatérő bab; }}

Végül meg kell határoznunk a gyári babot, a prototípust és az egyszemű babot a konfigurációnkban:

@Configuration public class AppConfig {@Bean public Function beanFactory () {return name -> prototypeBeanWithParam (név); } @Bean @Scope (value = "prototípus") public PrototypeBean prototípusBeanWithParam (karakterlánc neve) {return new PrototypeBean (name); } @Bean public SingletonFunctionBean singletonFunctionBean () {return new SingletonFunctionBean (); } // ...}

9. Tesztelés

Írjunk most egy egyszerű JUnit tesztet az eset gyakorlásához ObjectFactory felület:

@Test public void 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 ("Új példány várható", firstInstance! = secondInstance); }

A teszt sikeres elindítása után ezt minden alkalommal láthatjuk getPrototypeInstance () nevezett metódust hoztak létre egy új prototípus bab példányt.

10. Következtetés

Ebben a rövid bemutatóban számos módszert tanultunk meg, hogy a prototípus babot miként injektálhatjuk a szingulettek közé.

Mint mindig, az oktatóanyag teljes kódja megtalálható a GitHub projektben.


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