dinamikus proxy
Néhány elmélet ... proxy osztály jön létre hívja Proxy.getProxyClass módszer, amely elfogadja osztálybetöltője és egy sor interfész (interfészek), és visszatér java.lang.Class objektum osztály, amely betöltésre útján továbbított class-loader és eszközök továbbított interfészek tömb .
Az átadott paraméterek számos korlátozás:
- Minden objektum egy sor interfészek kell lennie interfészeket. Ezeket nem lehet osztályok vagy primitívek.
- A tömb interfészek nem lehet két azonos tárgyat.
- Minden interfészek az interfaces tömbben kell betölteni a osztálybetöltő, továbbítjuk a getProxyClass módszer.
- Az összes nem nyilvános interfész kell meghatározni az egyazon csomagban, különben a generált proxy osztály nem lesz képes végrehajtani mindet.
- Mindenesetre két interfész lehet a módszer az azonos név és aláírás paramétereket, de a különböző típusú visszatérési érték.
- Array hossza korlátozott interfészek 65535 th interfészek. Nem Java-osztály nem valósíthat meg több, mint 65.535 interfészek (és szeretné!).
Ha a fentiek közül bármelyik korlátozások megsértése esetén - lesz dobni IllegalArgumentException. és ha egy sor interfészek interfész null, akkor egy NullPointerException dobni.
Tulajdonságok dinamikus proxy osztály
- A proxy osztály nyilvános, fel van szerelve egy módosító végleges és nem absztrakt.
- Meghatalmazott neve osztály alapértelmezés szerint nincs meghatározva, de kezdődik $ Proxy. Minden névtér kezdve a Proxy $ a proxy osztály.
- A proxy osztály örökli java.lang.reflect.Proxy.
- A proxy osztály megvalósítja az összes interfész továbbított létrehozásában, az átviteli sorrendben.
- Ha proxy osztály hajtja végre, nem nyilvános interfész, akkor jön létre a csomag, amely meghatározza a leginkább nem nyilvános felületen. Általában a csomag, amelyben a proxy osztály bizonytalanságot.
- Proxy.isProxyClass módszer visszaadja igaz az osztályok, segítségével létrehozott Proxy.getProxyClass és osztályok számára létrehozott objektumok segítségével Proxy.newProxyInstance és egyébként false. Ez a módszer a Java biztonsági alrendszer és meg kell érteniük, hogy egy osztály csak örökölt java.lang.reflect.Proxy hamis értékkel tér vissza.
- java.security.ProtectionDomain a proxy osztály megegyezik a rendszer osztályok letöltött bootstrap-rakodó, például - a java.lang.Object. Ez logikus, mert a proxy osztály kódját által létrehozott JVM és nincs ok, hogy ne bízz magadban.
Egy példa a dinamikus proxy osztályt és tulajdonságai
proxy osztály konstruktor egy paramétert - a végrehajtás InvocationHandler felületen. Ennek megfelelően a proxy objektum osztály hozható létre reflexió hívja newInstance Class osztály objektum. Azonban van egy másik módja - okoz Proxy.newProxyInstance módszer. aki a rakodó osztály tartalmaz egy sor felületek, amelyek végrehajtják a proxy osztály, és a tárgy, amely megvalósítja InvocationHandler. Tény, hogy ez a módszer kombinálja, így a proxy osztály segítségével Proxy.getProxyClass, és hozzon létre egy példányt ebbe az osztályba keresztül reflexió.
A tulajdonságait a proxy osztályt létre például a következőképpen:
- Object proxy osztályt vezet az összes interfész az interfaces tömb telt el. Ha Idemo - az egyik a továbbított interfészek, proxy instanceof Idemo művelet mindig igaz értéket ad vissza. és a művelet (Idemo) proxy kitölteni.
- Proxy.getInvocationHandler statikus módszer visszaadja a híváskezelő telt létrehozásakor egy példányt a proxy osztály. Ha átment ez a módszer nem egy tárgy egy példánya a proxy osztály, akkor dobott IllegalArgumentException kivétel.
- híváskezelő osztály megvalósítja InvocationHandler felület. amely meghatározza a Invoke módszerrel. amely a következő aláírás:
public Object Invoke (Object proxy. módszer Módszer. Object [] args) dob Kiváltható
Ott proxy - a proxy osztály például, hogy lehet használni a hívás feldolgozása vagy más módszerrel. A második lehetőség - a módszer egy példánya java.lang.reflect.Method. A paraméter értéke - az egyik módszerek bármelyikében meghatározott továbbított létrehozásakor egy proxy osztályt interfészek vagy szuper-interfészek. A harmadik lehetőség - a tömb módszer érveket. Érvek primitív típusok helyébe esetekben az osztályokba, pakolások, például java.lang.Integer vagy java.lang.Boolean. A konkrét végrehajtás hivatkozhat a módszer sem változtathatja meg a tömbben.
A visszaadott érték meghívási legyen olyan típusú összeegyeztethető típusú által visszaadott érték a felület, amelyre ezt nevezik wrapper. Különösen, ha az interfész metódus visszaad egy primitív típusú érték - szükség van, hogy visszatérjen a példány a borítás a primitív típus. Ha visszatér null, és a várható érték egy primitív típus - hogy el kell dobni NullPointerException. Abban az esetben, nem primitív típusok, egy osztály módszer hivatkozhat a visszatérési érték jelen kell lennie, hogy az osztály a visszatérési értéke a felület módszer, különben nem fog kidobják ClassCastException.
Belül meghívási módszert csak dobja ellenőrzött kivételek, amelyek meghatározása az aláírásra nevezett módszer vagy felületet adott nekik. Amellett, hogy az ilyen típusú kivételek engedélyezettek csak hogy dobja ellenőrizetlen kivételek (mint például java.lang.RuntimeException), vagy egy hiba (például, java.lang.Error). Ha hivatkozhat olyan eljárás belsejében egy ellenőrzött kivételt dobott páratlan leírtakkal módszer aláírás felület - ez lesz csak egy kivételt dob UndeclaredThrowableException.
Hash kód módszerek, a egyenlők és a toString, meghatározott Object osztályban, azonos lesz az úgynevezett nem közvetlenül, hanem hivatkozhat egy eljárás egy par minden a felület módszereket. Egyéb közösségi módszerek az Object osztály közvetlenül hívható.
Object felhasználó - teljesen normális, nincs varázslat.
Proxy.newProxyInstance - maguk az eredetét a mágia, a hívás paraméterei a következők:
- ClassLoader class User, róla egy kicsit kisebb;
- TipaClass tömb. Meg kell venni egy sor interfészek. amely végrehajtja a mi osztály (Felhasználó). Módszerek Ezen interfészek lesz elfogott (invocationHandler-th).
- Példának InvocationHandler. ami miatt egy tárgy perehvatyvatmetody felhasználó (sőt, a hívások megy át az újonnan létrehozott userProxy).
A kimenet egy példánya egy bizonyos osztály (proxy), amely egy mágikus következő funkciókat:
- Ellátja az összes interfész módszerek továbbított második bemeneti paraméter a hívás Proxy.newProxyInstance (ebben a példában getName, setName, átnevezés). Ebben hasonlít a személy;
- Amikor hívja ezeket a módszereket, a mintát (például userProxy.setName) okozott InvocationHandler-INVOKE () módszer. InvocationHandler már döntöttek, hogyan jár -
- hívja a megfelelő módszert a valós személy osztály
- Ahhoz, hogy a valami mást, ebben az esetben,
Azaz, a mi InvocationHandler például egyszerűen megjeleníti a nevét a hívott eljárás a konzolt, és azt okozza, hogy az objektum tárolására. Így minden végrehajtása előtt a felhasználó módszerek nevét jeleníti meg a hívott eljárás.
Mondjuk van „kövér” osztály egy csomó olyan eljárások, amelyekben szeretnénk ugyanazt a műveletet - mint például a fakitermelés, az ellenőrzési nyomvonal, a biztonság, a sorozatba eredményeket. A klasszikus OOP, ez a probléma megoldódott, vagy a másolás és beillesztés, vagy a kibocsátás az egyes módszerek egy osztály, ami nem kényelmes. És ebben a pillanatban, hogy a támogatás a mágia, az úgynevezett reflexiós formájában Proxy. osztály interfész módszerek kiosztani elég létrehozni egy átalakító, amely ugyanazt a műveletet az összes módszert (előtt vagy után azt a módszert, logika). Általában ez egy dzsungel AOP, akik details'm itt.
Amennyiben ezt tette „egy osztály”, amelynek egy példányát megkaptuk a kimeneten Proxy.newProxyInstance?
Ez egy dinamikusan létrehozott osztály létre a byte tömböt.
Hívjon Lánc: Proxy.newProxyInstance -> Proxy.getProxyClass -> sun.misc.ProxyGenerator.generateProxyClass
Ez utóbbi módszer visszaadja egy byte tömböt, amelyet azután átalakítja ClassLoader.defineClass osztályba. és tovább newInstance.
Az eredmény egy olyan program, amely létrehozza önmagát.
Természetesen szeretném látni, mi generált Peter Jones.Szerencsére, akkor kap egy bytecode generált osztály, amelyben egy mágikus (és senki nem tudja) rendszer tulajdon «sun.misc.ProxyGenerator.saveGeneratedFi les» true létrehozása előtt az osztályban.
Kapcsolódó cikkek