Java Reflection-dinamikus proxyk

a Java Reflection használatával dinamikus implementációkat hozhat létre futásidőben. Ezt a java.lang.reflect.Proxy osztály használatával teheti meg. Ennek az osztálynak a neve az, amiért ezeket a dinamikus interfész implementációkat dinamikus proxyknak nevezem. A dinamikus proxyk sokféle célra használhatók, pl. adatbázis-kapcsolat és tranzakciókezelés, dinamikus mock objektumok egységteszteléshez és más AOP-szerű metódus-elfogási célokra.

proxyk létrehozása

dinamikus proxykat hoz létre az Proxy.newProxyInstance() módszerrel. A newProxyInstance() módszerek 3 paramétert vesznek fel:

  1. a ClassLoader, azaz a dinamikus proxy osztály “betöltése”.
  2. a megvalósítandó interfészek tömbje.
  3. An InvocationHandler a proxy összes metódusának továbbításához.

íme egy példa:

a kód futtatása után a proxy változó a MyInterface interfész dinamikus megvalósítását tartalmazza. A proxyhoz intézett összes hívás az Általános handler interfész InvocationHandler implementációjához kerül továbbításra. InvocationHandler által lefedett i a következő részben.

InvocationHandler ‘ s

mint korábban említettük, át kell adnia egy InvocationHandler implementációt a Proxy.newProxyInstance() metódusnak. A dinamikus proxyhoz intézett összes metódushívás erre a InvocationHandler megvalósításra kerül. Így néz ki a InvocationHandler felület:

public interface InvocationHandler{ Object invoke(Object proxy, Method method, Object args) throws Throwable;}

íme egy példa a megvalósításra:

public class MyInvocationHandler implements InvocationHandler{ public Object invoke(Object proxy, Method method, Object args) throws Throwable { //do something "dynamic" }}

a proxy paraméter, amelyet a invoke() metódusnak adtak át, az interfészt megvalósító dinamikus proxyobjektum. Leggyakrabban nincs szüksége erre az objektumra.

a Method objektum, amelyet a invoke() metódusnak adtak át, azt a metódust képviseli, amelyet az interfészen a dinamikus proxyalkalmazások hívnak meg. A Method objektumból megkaphatja a metódus nevét, paraméter típusait, visszatérési típusát stb. További információkért lásd a módszerek szövegét.

a Object args tömb tartalmazza a proxynak átadott paraméterértékeket, amikor a megvalósított interfészen lévő metódust meghívták. Megjegyzés: a megvalósított felületen lévő primitívek (int, long stb.) Az objektum megfelelőikbe vannak csomagolva (Integer, Long stb.).

ismert felhasználási esetek

a dinamikus proxykat legalább a következő célokra használják:

  • adatbázis-kapcsolat és Tranzakciókezelés
  • dinamikus Mock objektumok Egységteszteléshez
  • di konténer adaptálása egyéni gyári interfészekhez
  • AOP-szerű módszer lehallgatás

adatbázis-kapcsolat és Tranzakciókezelés

a Spring keretrendszer rendelkezik egy tranzakciós proxyval, amely elindíthat és végrehajthat / visszavonhat egy tranzakciót az Ön számára. Ennek működését részletesebben az Advanced Connection and Transaction Demarkation and Propagation szöveg írja le, ezért csak röviden írom le. A hívássorozat ezen a módon válik valamivé:

dinamikus Mock objektumok az egység teszteléséhez

a Butterfly Testing Tools dinamikus proxykat használ a dinamikus csonkok, gúnyok és proxyk megvalósításához az egység teszteléséhez. Egy olyan A osztály tesztelésekor, amely egy másik B osztályt használ (interfész valóban), átadhatja a B ál implementációját A-nak a valódi B helyett. Az összes B metódushívás rögzítésre kerül, és beállíthatja, hogy milyen visszatérési értékeket adjon vissza a mock B.

továbbá pillangó vizsgálati eszközök lehetővé teszik, hogy lezárja a valódi B egy ál B, úgy, hogy az összes módszer felhívja a ál rögzítésre kerül, majd továbbítja az igazi B. Ez lehetővé teszi, hogy ellenőrizze, milyen módszereket hívtak egy valós működő B. például, ha a tesztelés egy DAO akkor csomagolja az adatbázis-kapcsolat egy ál. A DAO nem fogja látni a különbséget, és a DAO a szokásos módon képes adatokat olvasni/írni az adatbázisba, mivel a mock minden hívást továbbít az adatbázisba. De most ellenőrizheti a mock segítségével, hogy a DAO megfelelően használja-e a kapcsolatot, például ha a connection.close() hívják (vagy nem hívják), ha erre számítottál. Ezt általában nem lehet meghatározni a Dao visszatérési értékéből.

a DI konténer adaptálása az egyedi gyári interfészekhez

a dependency injection container Butterfly Container erőteljes funkcióval rendelkezik, amely lehetővé teszi az egész tartály befecskendezését az általa termelt Babba. De mivel nem akar függőséget a konténer interfésztől, a konténer képes alkalmazkodni a tervezés egyéni gyári felületéhez. Csak az interfészre van szüksége. Nincs megvalósítás. Így a gyári felület és az osztályod valahogy így nézhet ki:

public interface IMyFactory { Bean bean1(); Person person(); ...}

amikor a MyAction osztály meghívja a IMyFactory példány metódusait, amelyeket a tároló injektál a konstruktorába, a metódushívások a IContainer.instance() metódusra történő hívásokká alakulnak, amely módszer a példányok beszerzésére szolgál a tárolóból. Így egy objektum futásidőben gyárként használhatja a Butterfly Container-t, nem pedig csak azért, hogy függőségeket injektáljon önmagába a létrehozás idején. És ez anélkül, hogy bármilyen függőség bármilyen pillangó konténer specifikus interfészek.

AOP-szerű módszer lehallgatás

a Spring keret lehetővé teszi, hogy lehallgatják módszer hívások egy adott bean, feltéve, hogy bean megvalósítja valamilyen interfész. A tavaszi keret a babot dinamikus proxyba csomagolja. Ezután a meghatalmazott elfogja a babhoz intézett összes hívást. A proxy dönthet úgy, hogy más módszereket hív meg más objektumokon, akár a metódushívás delegálása előtt, helyett vagy után a Bean csomagolva.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.