CDI hordozható kiterjesztés és repülõút
1. Áttekintés
Ebben az oktatóanyagban áttekintjük a CDI (Context and Dependency Injection) érdekes tulajdonságát, a CDI hordozható kiterjesztést.
Először azzal kezdjük, hogy megértsük a működését, majd meglátjuk, hogyan kell írni egy kiterjesztést. Végig fogjuk hajtani a CDI integrációs modul Flyway megvalósításának lépéseit, így egy adatbázis-migrációt futtathatunk egy CDI-tároló indításakor.
Ez az oktatóanyag feltételezi a CDI alapvető ismereteit. A CDI bemutatásához tekintse meg ezt a cikket.
2. Mi az a CDI hordozható kiterjesztés?
A hordozható CDI kiterjesztés olyan mechanizmus, amellyel további funkciókat tudunk megvalósítani a CDI konténer tetején. Indításkor a CDI tároló beolvassa az osztályútvonalat, és metaadatokat készít a felfedezett osztályokról.
A beolvasási folyamat során a CDI-tároló sok inicializálási eseményt indít el, amelyeket csak a kiterjesztések figyelhetnek meg. Itt jelenik meg a CDI hordozható kiterjesztés.
A CDI Portable kiterjesztés figyeli ezeket az eseményeket, majd módosítja vagy hozzáadja az információkat a tároló által létrehozott metaadatokhoz.
3. Maven-függőségek
Kezdjük azzal, hogy hozzáadjuk a CDI API szükséges függőségét a pom.xml. Ez elég egy üres kiterjesztés megvalósításához.
javax.enterprise cdi-api 2.0.SP1
Az alkalmazás futtatásához pedig bármilyen kompatibilis CDI megvalósítást használhatunk. Ebben a cikkben a Weld megvalósítást fogjuk használni.
org.jboss.weld.se hegesztett se-core 3.0.5.Végső futási idő
A Maven Centralon ellenőrizheti, hogy az API és az implementáció új verziói megjelentek-e.
4. Repülőút futtatása nem CDI környezetben
Mielőtt nekilátnánk az integrációnak Repülőút és a CDI, először meg kell vizsgálnunk, hogyan futtassuk nem CDI kontextusban.
Vessünk egy pillantást az alábbi hivatalos példára, amely a Repülőút:
DataSource dataSource = // ... Flyway flyway = new Flyway (); flyway.setDataSource (dataSource); flyway.migrate ();
Mint láthatjuk, csak a-t használjuk Repülőút példány, amelyre szükség van a Adatforrás példa.
A CDI hordozható kiterjesztésünk később elkészíti a Repülőút és Adatforrás bab. A minta alkalmazásához beágyazott H2 adatbázist fogunk használni, és megadjuk Adatforrás tulajdonságait a DataSourceDefinition annotáció.
5. CDI konténer inicializálási események
Az alkalmazás indításakor a CDI-tároló az összes CDI hordozható kiterjesztés betöltésével és példányosításával indul. Ezután minden kiterjesztésben megkeresi és regisztrálja az inicializálási események megfigyelői módszereit, ha vannak ilyenek. Ezt követően a következő lépéseket hajtja végre:
- Tűz BeforeBeanDiscovery esemény a szkennelési folyamat megkezdése előtt
- Elvégzi azt a típusfelfedezést, amelyben az archív babokat beolvassa, és minden felfedezett típusra lő ProcessAnnotatedType esemény
- Tűz a AfterTypeDiscovery esemény
- Végzi a bab felfedezését
- Tűz a AfterBeanDiscovery esemény
- Végzi a bab ellenőrzését és észleli a definíciós hibákat
- Tűz a AfterDeploymentValidation esemény
A CDI hordozható kiterjesztés célja ezután megfigyelni ezeket az eseményeket, ellenőrizni a felfedezett babok metaadatait, módosítani vagy kiegészíteni ezeket.
Egy CDI hordozható kiterjesztésben csak ezeket az eseményeket figyelhetjük meg.
6. A CDI Portable Extension írása
Lássuk, hogyan tudunk bekapcsolódni néhány ilyen eseménybe saját CDI hordozható kiterjesztésünk megépítésével.
6.1. Az SPI-szolgáltató megvalósítása
A CDI hordozható kiterjesztés a felület Java SPI szolgáltatója javax.enterprise.inject.spi.Extension. A Java SPI bemutatásához olvassa el ezt a cikket.
Először a Kiterjesztés végrehajtás. Később megfigyelő módszereket adunk a CDI tároló bootstrap eseményeihez:
nyilvános osztályú FlywayExtension valósítja meg a kiterjesztést {}
Ezután hozzáadunk egy fájlnevet META-INF / services / javax.enterprise.inject.spi.Extension ezzel a tartalommal:
com.baeldung.cdi.extension.FlywayExtension
SPI-ként ez Kiterjesztés a konténer csomagtartója előtt töltődik be. Tehát megfigyelő módszerek regisztrálhatók a CDI bootstrap eseményein.
6.2. Az események inicializálásának megfigyelői módszereinek meghatározása
Ebben a példában a Repülőút osztály, amelyet a CDI konténer ismert a beolvasás megkezdése előtt. Ez a registerFlywayType () megfigyelő módszer:
public void registerFlywayType (@Observes BeforeBeanDiscovery bbdEvent) {bbdEvent.addAnnotatedType (Flyway.class, Flyway.class.getName ()); }
Itt metaadatokat adtunk a Repülőút osztály. Mostantól úgy fog viselkedni, mintha a tároló vizsgálta volna meg. Erre a célra használtuk a addAnnotatedType () módszer.
Ezután megfigyeljük a ProcessAnnotatedType esemény, hogy a Repülőút osztály CDI kezelt babként:
public void processAnnotatedType (@Observes ProcessAnnotatedType patEvent) {patEvent.configureAnnotatedType () .add (ApplicationScoped.Literal.INSTANCE) .add (new AnnotationLiteral () {}) .filterMethods (annotatedMethod -> ) == 1 && annotatedMethod.getParameters (). Get (0) .getBaseType () .equals (javax.sql.DataSource.class);}). FindFirst (). Get (). Add (InjectLiteral.INSTANCE); }
Először feljegyezzük a Repülőút osztályban @ApplicationScoped és @FlywayType annotációk, majd a Flyway.setDataSource (DataSource dataSource) módszerrel és annotáljuk @ Injekció.
A fenti műveletek végeredményének ugyanaz a hatása, mintha a tároló a következőket vizsgálná Repülőút bab:
@ApplicationScoped @FlywayType public class Flyway {// ... @Inject public void setDataSource (DataSource dataSource) {// ...}}
A következő lépés az, hogy a Adatforrás az injekcióhoz kapható bab Repülőút bab függ a Adatforrás bab.
Ehhez feldolgozzuk a Adatforrás Bean a tartályba, és mi használjuk a AfterBeanDiscovery esemény:
void afterBeanDiscovery (@Observes AfterBeanDiscovery abdEvent, BeanManager bm) {abdEvent.addBean () .types (javax.sql.DataSource.class, DataSource.class) .qualifiers (új AnnotationLiteral () {}, új AnnotationLiteral () hatókör (ApplicationScoped.class) .name (DataSource.class.getName ()) .beanClass (DataSource.class) .createWith (creationalContext -> {DataSource példány = új DataSource (); instance.setUrl (dataSourceDefinition.url ()); instance.setDriverClassName (dataSourceDefinition.className ()); visszatérési példány;}); }
Mint láthatjuk, szükségünk van a DataSourceDefinition amely biztosítja a DataSource tulajdonságokat.
Bármely kezelt babot a következő felirattal jelölhetjük:
@DataSourceDefinition (név = "ds", osztálynév = "org.h2.Driver", url = "jdbc: h2: mem: testdb")
Ezen tulajdonságok kinyerése érdekében megfigyeljük a ProcessAnnotatedType esemény a @Annotációkkal kommentár:
public void DetectDataSourceDefinition (@Observes @WithAnnotations (DataSourceDefinition.class) ProcessAnnotatedType patEvent) {AnnotatedType at = patEvent.getAnnotatedType (); dataSourceDefinition = at.getAnnotation (DataSourceDefinition.class); }
És végül meghallgatjuk a AfterDeployementValidation esemény, hogy megszerezzék a keresett személyeket Repülőút babot a CDI konténerből, majd hívja meg a vándorol() módszer:
void runFlywayMigration (@Observes AfterDeploymentValidation adv, BeanManager manager) {Flyway flyway = manager.createInstance () .select (Flyway.class, new AnnotationLiteral () {}). get (); flyway.migrate (); }
7. Következtetés
A CDI hordozható kiterjesztés felépítése elsőre nehézkesnek tűnik, de miután megértettük a tároló inicializálási életciklusát és a kiterjesztéseknek szentelt SPI-t, ez egy nagyon hatékony eszközzé válik, amelyet felhasználhatunk keretrendszerek felépítésére a Jakarta EE tetején.
Szokás szerint a cikkben bemutatott összes kódminta megtalálható a GitHubon.