Sisällysluettelo
Johdanto
Dynamic Proxy API
Serialisointi
esimerkkejä
Johdanto
dynaaminen välityspalvelinluokka on luokka, joka toteuttaa suorituksen aikana määritellyn rajapintaluettelon siten, että menetelmä invocationin kautta johonkin luokan ilmentymään koodataan ja lähetetään toiseen objektiin uniform Interfacen kautta. Dynaamista välityspalvelinluokkaa voidaan siten käyttää luomaan atype-safe-välityspalvelinobjekti rajapintojen luetteloon ilman, että välityspalvelinluokan generointia vaaditaan, kuten compile-time-työkaluilla.Method invocations on a instance of a dynamic proxy class areispated to a single method in the instance ’ s invocationhandler, and they are encoded with ajava.lang.reflect.Method
object identifying the method that were invocationhandler and a array of type Object
containing the arguments.
dynaamiset välityspalvelinluokat ovat hyödyllisiä sovellukselle tai kirjastolle, jonka on tarjottava tyyppiturvallinen heijastava inventointilähetys kohteille, jotka esittävät Rajapintarajapintoja. Sovellus voi esimerkiksi käyttää dynaamista välityspalvelinluokkaa luodakseen objektin, joka toteuttaa useita mielivaltaisia tapahtumakuuntelijan rajapintoja– rajapintoja, jotka ulottuvat java.util.EventListener
— prosessoidakseen erityyppisiä tapahtumia yhdenmukaisesti, kuten kirjaamalla kaikki tällaiset tapahtumat tiedostoon.
Dynamic Proxy Class API
a dynamic proxy class (yksinkertaisesti kutsutaan proxyclass alla) on luokka, joka toteuttaa luettelon interfacesspecified suorituksen aikana, kun luokka luodaan.
välityspalvelinliittymä on sellainen rajapinta, jota toteuttaa välityspalvelinluokka.
proxy-instanssi on proksyklaasin instanssi.
Proxy-luokan luominen
Proxy-luokat sekä niiden esiintymät luodaan käyttäen Javan luokan staattisia menetelmiä.lang.heijastaa.Välityspalvelin.
Proxy.getProxyClass
– menetelmä palauttaajava.lang.Class
– objektin proxy-luokalle, jossa on luokkaladaaja ja joukko liittymiä. Välityspalvelinluokka määritellään määritetyssä luokkakuormaajassa ja se toteuttaa kaikki toimitetut liitännät. Jos välityspalvelinluokka samalle permutaatiolle on jo määritelty luokkakuormaajassa, nykyinen välityspalvelinluokka palautetaan; muussa tapauksessa välityspalvelinluokka forose interfaces luodaan dynaamisesti ja määritellään theclassic loader.
on olemassa useita rajoituksia parametreille, jotka voidaan laskea Proxy.getProxyClass
:
- kaikkien
Class
olioideninterfaces
joukossa tulee edustaa rajapintoja, ei-luokkia tai primitiivisiä tyyppejä. -
interfaces
joukon kaksi alkuainetta eivät voi viitata identtisiinClass
olioihin. - kaikkien liitäntätyyppien on oltava näkyvillä nimen mukaisesti määritellyn luokkakuormaajan kautta. Toisin sanoen luokkakuormaajan
cl
ja jokaisen rajapinnani
kohdalla seuraavan ilmaisun on oltava tosi:Class.forName(i.getName(), false, cl) == i
- kaikkien muiden kuin julkisten rajapintojen on oltava samassa paketissa;muutoin välityspalvelinluokan ei olisi mahdollista toteuttaa kaikkia rajapintoja riippumatta siitä, missä paketissa se on määritelty.
- mille tahansa määritettyjen rajapintojen jäsenmenetelmien joukolle, jolla on sama allekirjoitus:
- jos jonkin menetelmän paluutyyppi on alkeellinen orvoidi, kaikilla menetelmillä on oltava sama paluutyyppi.
- muussa tapauksessa jollakin menetelmistä on oltava palautustyyppi, joka on yhteensopiva kaikkien muiden menetelmien palautustyyppien kanssa.
- tuloksena oleva välityspalvelinluokka ei saa ylittää virtuaalikoneen asettamia luokkarajoja. VM voi esimerkiksi rajoittaa luokan toteuttamien liitäntöjen määrän 65535: een; tällöin taulukon
interfaces
koko ei saa ylittää 65535: tä.
jos jotakin näistä rajoituksista rikotaan,Proxy.getProxyClass
heittää IllegalArgumentException
. Josinterfaces
array-argumentti tai jokin sen alkuaineista onnull
, a NullPointerException
häviää.
huomaa, että määritettyjen välityspalvelinliittymien järjestys on merkittävä: kaksi välityspalvelinluokkaa koskevaa pyyntöä, joissa on sama rajapintojen yhdistelmä, mutta eri järjestyksessä, johtaa kahteen erilliseen välityspalvelinluokkaan. Välityspalvelinluokat erotetaan niiden välityspalvelinliittymien mukaan, jotta voidaan tarjota deterministinen method invocation-koodaus tapauksissa, joissa kaksi tai useampi proxyinterfaces jakaa saman nimisen menetelmän ja parametrisignatuurin; tätä perustelua kuvataan tarkemmin alla olevassa osiossa ”Methods Duplicated inMultiple Proxy Interfaces”.
jotta uutta välityspalvelinluokkaa ei tarvitse luoda joka kerta, kun Proxy.getProxyClass
vedotaan samaan lataajaan ja käyttöliittymäluetteloon, dynaamisen välityspalvelinluokan API: n toteutuksen tulisi pitää välimuisti luoduista proksyklasseista, jotka on näppäilty niiden vastaavilla kuormaajilla ja käyttöliittymäluettelolla.Toteutuksessa olisi varottava viittaamasta luokkalukijoihin, rajapintoihin ja välityspalvelinluokkiin siten, että estetään luokkakuormaajien ja kaikkien niiden luokkien kerääminen tarvittaessa.
Proxy-luokan ominaisuudet
proxy-luokalla on seuraavat ominaisuudet:
- Proxy-luokat ovat julkisia, lopullisia, eivätkä abstrakteja.
- proxy-luokan varaukseton nimi on määrittelemätön. Merkkijonolla
"$Proxy"
alkavien luokkanimien väli on kuitenkin varattava proxy-luokille. - proxy-Luokka ulottuu
java.lang.reflect.Proxy
. - välityspalvelinluokka toteuttaa täsmälleen määritellyt rajapinnat atitin luomisessa, samassa järjestyksessä.
- jos välityspalvelinluokka toteuttaa ei-julkisen rajapinnan, se määritellään samassa paketissa kyseisen rajapinnan kanssa. Muuten välityspalvelinluokan paketti on myös määrittelemätön. Huomaa, että pakkaussealing ei estä välityspalvelinluokan onnistumista tietyssä paketissa suorituksen aikana, eikä kumpikaan luokista, jotka on jo määritelty saman luokan kuormaimessa ja samassa paketissa tiettyjen allekirjoittajien kanssa.
- koska välityspalvelinluokka toteuttaa kaikki sen luomisessa määritellyt liitännät, kutsumalla
getInterfaces
senClass
objekti palauttaa rivin,joka sisältää saman luettelon liitännöistä (sen luonti-määräisessä järjestyksessä), kutsumallagetMethods
senClass
objectwill palauttaa joukonMethod
objekteja, jotka sisältävät kaikki kyseisten rajapintojen menetelmät, ja kutsumallagetMethod
löytää menetelmiä välityspalvelinliitännöistä, kuten odotettu. -
Proxy.isProxyClass
menetelmä palauttaa true-arvon, jos se läpäisee proxy-luokan — luokan, jonka palauttaaProxy.getProxyClass
, tai objektin luokan, jonka palauttaaProxy.newProxyInstance
— ja epätosi muuten. Tämän menetelmän luotettavuus on tärkeää, jotta sitä voidaan käyttää turvallisuuspäätösten tekemiseen, joten sen täytäntöönpanoa ei pitäisi vain testata, jos kyseinen luokka ulottuujava.lang.reflect.Proxy
. - proxyclassin
java.security.ProtectionDomain
on sama kuin bootstrapclass-kuormaimen lataamien järjestelmäluokkien, kutenjava.lang.Object
, koska välityspalvelinluokan koodi syntyy luotetusta järjestelmäkoodista. Tämä suojelualue myönnetään tyypillisestijava.security.AllPermission
.
Proxy-instanssin luominen
jokaisella proxy-luokalla on yksi julkinen rakentaja, joka ottaa opikseen, rajapinnan toteutuksen InvocationHandler
.
jokaisella proxy-instanssilla on siihen liittyvä invokaation käsittelijäobjekti,joka on siirretty sen rakentajalle. Sen sijaan, että reflection-sovellusliittymän avulla voitaisiin käyttää julkista rakentajaa, proxyinstance voidaan luoda myös kutsumallaProxy.newProxyInstance
– menetelmää, jossa yhdistyvät Proxy.getProxyClass
kutsumisen toiminnot ja rakentajan kutsuminen kutsujen käsittelijään.Proxy.newProxyInstance
heittääIllegalArgumentException
samoista syistä kuinProxy.getProxyClass
tekee.
Proxy-instanssin ominaisuudet
proxy-instanssilla on seuraavat ominaisuudet:
- kun otetaan huomioon proxy-esiintymä
proxy
ja yksi proxy-luokallaanFoo
toteutetuista tiloista, seuraava lauseke palaa todeksi:proxy instanceof Foo
ja seuraava cast-operaatio onnistuu (throwingan sijaan
ClassCastException
):(Foo) proxy
- staattinen
Proxy.getInvocationHandler
– menetelmä palauttaa argumenttinaan käytettyyn välityspalvelimeen liittyvän pyynnön käsittelijän. JosProxy.getInvocationHandler
Annettu objekti ei ole proxy-instanssi, niinIllegalArgumentException
heitetään. - rajapintamenetelmän kutsuminen välitysilmoituksella koodataan ja lähetetään kutsunkäsittelijän
invoke
– menetelmään alla kuvatulla tavalla.itse proxy-instanssi ohitetaan
invoke
ensimmäisenä argumenttina, joka on tyyppiäObject
.toinen
invoke
: lle siirretty argumentti onjava.lang.reflect.Method
instanssi, joka vastaa proxy-instanssissa käytettyä interface-menetelmää.Method
olion julistusluokka on rajapinta, jossa themethod julistettiin, joka voi olla proxyinterfacen superinterface, jonka kautta proxyinterface perii menetelmän.kolmas
invoke
: lle siirretty argumentti on joukko olioita, jotka sisältävät väli-instanssiin tehdyssä menetelmävetoomuksessa annettujen argumenttien arvot. Primitivetyyppien argumentit kääritään sopivan primitivewrapper-luokan instanssiin, kutenjava.lang.Integer
taijava.lang.Boolean
.invoke
– menetelmän toteutuksessa voidaan vapaasti muuttaa tämän säännön sisältöä.invoke
– menetelmällä palautetusta arvosta tulee proxy-ilmentymässä esiintyvän menetelmän palautusarvo. Jos rajapintamenetelmän ilmoitettu palautusarvo on primitivetyyppi,invoke
: llä palautetun arvon on oltava vastaavan primitiivisen kääreluokan laite; muussa tapauksessa sen on oltava ilmoitetulle palautustyypille siirrettävä tyyppi. Josinvoke
: n palauttama arvo onnull
ja interface-menetelmän palautustyyppi on primitiivinen, niinNullPointerException
heitetään methodinvokaatio proxy-ilmentymälle. Josinvoke
: n palauttama arvo ei muuten ole yhteensopiva edellä kuvatun menetelmän ilmoittaman palautustyypin kanssa, proxyinstance heittää arvonClassCastException
.jos poikkeuksen heittää
invoke
– menetelmä, se heitetään myös metodin kutsumisella proxy-instanssiin.Poikkeuksen tyypin on oltava siirrettävissä joko mihin tahansa liitäntämenetelmän allekirjoituksessa ilmoitettuun poikkeustyyppiin tai tarkistamattomiin poikkeustyyppeihinjava.lang.RuntimeException
taijava.lang.Error
. Josinvoke
heittää tarkistetun poikkeuksen, joka ei ole siirrettävissä mihinkään interfacemethodinthrows
lausekkeessa ilmoitetuista poikkeustyypeistä, niinUndeclaredThrowableException
heitetään menetelmän kutsulla välitysilmaisuun.UndeclaredThrowableException
konstruoidaaninvoke
– menetelmällä heitettyä poikkeusta lukuun ottamatta. -
hashCode
,equals
taitoString
proxy-instanssissajava.lang.Object
ilmoitetut menetelmät koodataan ja lähetetään kutsunkäsittelijäninvoke
– menetelmään samalla tavalla kuin rajapintamenetelmän kutsut koodataan ja lähetetään edellä kuvatulla tavalla.Method
kohteen ilmoitusluokkainvoke
tulee olemaanjava.lang.Object
. Muitajava.lang.Object
: ltä periytyviä julkisia proxyinstance-menetelmiä ei syrjitä proxy-luokka, joten näiden menetelmien käyttö on samanlaista kuinjava.lang.Object
: n kohdalla.
Moniproxy-liitännöissä Monistetut menetelmät
kun kaksi tai useampi välityspalvelinluokan rajapinta sisältää saman nimen ja parametrin allekirjoituksen sisältävän menetelmän, proxyclassin rajapintojen järjestys muuttuu merkittäväksi. Kun välityspalvelimen tapauksessa käytetään tällaista kahdentamismenetelmää, ei Method
kutsunkäsittelijälle Annettu objekti välttämättä ole se, jonka ilmoitusluokka voidaan siirtää sen rajapinnan viitetyypin perusteella, jonka kautta välityspalvelimen menetelmään on vedottu. Tämä rajoitus on olemassa, koska generoidun välityspalvelinluokan vastaava menetelmätoteutus ei voi määrittää, minkä rajapinnan kautta sitä käytettiin. Näin ollen, kun kaksoismenetelmää kutsutaan proxy-instanssiin, Method
– olio menetelmälle etummaisessa rajapinnassa, joka sisältää menetelmän (joko suoraan tai superinterfacen kautta perittynä) proxy-luokan väliluettelossa, siirretään kutsunkäsittelijäninvoke
– menetelmälle riippumatta siitä, millä viitetyypillä menetelmän kutsuminen tapahtui.
jos välityspalvelinliittymä sisältää menetelmän, jolla on sama nimi japarametri kuin hashCode
,equals
tai toString
java.lang.Object
: n menetelmillä, kun tällaiseen menetelmään vedotaan aproxy-instanssissa, Method
: n kutsukäsittelijälle välitetyllä objektilla on java.lang.Object
sen ilmoittamisluokka. Toisin sanoenjava.lang.Object
: n julkiset, ei-lopulliset menetelmät edeltävät loogisesti kaikkia niitä proxyinterferaaseja, joiden määrittämistä Method
vastustaa pyynnön käsittelijälle.
Huomaa myös, että kun kaksoiskappalemenetelmä lähetetään sijoitusten käsittelijälle, invoke
– menetelmä voi heittää vain tarkistettuja poikkeustyyppejä, jotka voidaan siirtää johonkin menetelmän throws
lausekkeessa mainittuun poikkeustyyppiin kaikissa välityspalvelinliitännöissä, joiden kautta sitä voidaan käyttää. Josinvoke
– menetelmä heittää tarkistetun poikkeuksen, jota ei voida merkitä mihinkään menetelmässä ilmoitettuun poikkeustyyppiin yhdessäkään välityspalvelinliitännässä, että siihen voidaan vedota, niin tarkistettu UndeclaredThrowableException
hylätään välityspalvelinilmoituksessa. Tämä rajoitus tarkoittaa sitä, että kaikkia poikkeustyyppejä ei voida palauttaa vetoamallagetExceptionTypes
Method
invoke
– menetelmän vastustukseen, koska invoke
– menetelmää ei voida välttämättä käyttää menestyksellisesti.
sarjasijoitus
koska java.lang.reflect.Proxy
toteuttaajava.io.Serializable
, proxy-instanssit voidaan luokitella tässä jaksossa kuvatulla tavalla. Jos välityspalvelimella on sellainen kutsunkäsittelijä, jota ei voida siirtääjava.io.Serializable
, kuitenkin java.io.NotSerializableException
heitetään, jos tällainen instanssi on kirjoitettu arvoonjava.io.ObjectOutputStream
. Huomaa, että proksyklasseissa toteutuksella java.io.Externalizable
on sama vaikutus sarjallistamisen osalta kuin toteutuksellajava.io.Serializable
: writeExternal
ja readExternal
Externalizable
– rajapinnan menetelmiä ei koskaan käytetä proxy-instanssissa (tai kutsujen käsittelijässä) osana itsserialisointiprosessia. Kuten kaikki Class
oliot, myösClass
proxy-luokan objekti on ainasosialisoituva.
proxy-luokalla ei ole sarjamuotoisia kenttiä ja serialVersionUID
0L
. Toisin sanoen kun proxy-luokan Class
objekti siirretään java.io.ObjectStreamClass
staattisellelookup
– menetelmälle, palautetullaObjectStreamClass
– ilmentymällä on seuraavat ominaisuudet:
-
getSerialVersionUID
– menetelmään vedoten0L
. - vedoten
getFields
– menetelmäänsä palauttaa arrayofin pituuden nollaksi. - vetoamalla
getField
menetelmäänsä millä tahansaString
argumentilla palaanull
.
striimausprotokolla objektien Sarjallistamiseen tukee TC_PROXYCLASSDESC
– nimistä tyyppikoodia, joka on striimimuodon kieliopissa terminaalimerkki; sen tyyppi ja arvo määritellään seuraavan vakiokentän avullajava.io.ObjectStreamConstants
– rajapinnassa:
final static byte TC_PROXYCLASSDESC = (byte)0x7D;
kielioppi sisältää myös seuraavat kaksi sääntöä, joista ensimmäinen on alkuperäisen newclassdescr:
newclassdescr:TC_PROXYCLASSDESC
newwhandle proxyClassDescInfo
proxyClassDescInfo:(int)<count>
proxyinterferacename classAnnotationsuperClassDesc
proxyinterferename:(utf)
kun ObjectOutputStream
serializes classdescriptor for a class, joka on proxy class, määritettynä ohittaen Class
objectProxy.isProxyClass
– menetelmän, se käyttääTC_PROXYCLASSDESC
– tyyppikoodiaTC_CLASSDESC
: n sijasta, noudattaen yllä olevia sääntöjä. Proxyclassdescinfon laajennuksessa proxyinterfacename – nimien järjestys on kaikkien proxy-luokan toteuttamien valheiden nimet siinä järjestyksessä, että ne palautetaan käyttämällä getInterfaces
– menetelmää Class
– objektissa. ClassAnnotation-ja supericlassdesc-erillä on sama merkitys kuin classdescinfo-säännössä. Proxy-luokan osalta superluokka on luokan asiasana sen superluokallejava.lang.reflect.Proxy
; mukaan lukien tämä asiasana mahdollistaa luokan sarjallistetun edustuksen kehityksen Proxy
proxy-instansseille.
muiden kuin proxy-luokkien osalta ObjectOutputStream
kutsuu itsprotected annotateClass
method to allow subclasss towriitti custom data to stream tietyn luokan. Proksyklasseille annotateClass
: n sijasta java.io.ObjectOutputStream
: n seuraavaa metodia kutsutaan proksyklodiksi Class
proksiluokan objektiksi:
protected void annotateProxyClass(Class cl) throws IOException;
annotateProxyClass
: n oletustoteutusObjectOutputStream
ei tee mitään.
kun ObjectInputStream
kohtaa tyyppikoodinTC_PROXYCLASSDESC
, se deserializes classdescriptor for a proxy class from the stream, formated asdekcreded over. Sen sijaan, että resolveClass
– menetelmää kutsuttaisiin Class
– objektin ratkaisemiseen luokkadescriptorille,java.io.ObjectInputStream
: ssä seuraavaa menetelmää kutsutaan:
protected Class resolveProxyClass(String interfaces) throws IOException, ClassNotFoundException;
proksyklassisessa asiasanassa deserialisoituneiden rajapintanimien luettelo ohitetaan interfaces
argumenttina resolveProxyClass
.
resolveProxyClass
: n oletustoteutusObjectInputStream
palauttaaProxy.getProxyClass
kutsumisen tuloksetClass
– objektien luettelollainterfaces
– parametrissa nimetyille rajapinnoille. Class
objekti, jota käytetään jokaiselle liittymän nimelle i
, on arvo, joka on retusoitu kelaamalla
Class.forName(i, false, loader)
, jossaloader
on ensimmäinen ei-null-luokan kuormaaja pinossa tainull
, jos pinossa ei ole ei-null-luokan kuormaajia. Kyseessä on saman luokan kuormaajavalinta, jonka on tehnytresolveClass
– metodin kytkykäyttäytyminen. Tämäloader
: n samevalue on myösProxy.getProxyClass
: lle siirretty luokkakuormaaja. JosProxy.getProxyClass
heittääIllegalArgumentException
,resolveClass
heittääClassNotFoundException
, joka sisältääIllegalArgumentException
.
koska proxy-luokalla ei koskaan ole omia sarjoitettavia kenttiä, proxy-instanssin striimiesedustuksen classdata sisältää kokonaan sen superluokan instanssitiedot,java.lang.reflect.Proxy
. Proxy
oneserialisable kenttä, h
, joka sisältää invocationhandler for proxy instance.
esimerkit
tässä on yksinkertainen esimerkki, joka tulostaa viestin ennen ja jälkeen method invocation on objekti, joka toteuttaa arbitrarylist rajapintojen:
public interface Foo { Object bar(Object obj) throws BazException;}public class FooImpl implements Foo { Object bar(Object obj) throws BazException { // ... }}public class DebugProxy implements java.lang.reflect.InvocationHandler { private Object obj; public static Object newInstance(Object obj) { return java.lang.reflect.Proxy.newProxyInstance( obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new DebugProxy(obj)); } private DebugProxy(Object obj) { this.obj = obj; } public Object invoke(Object proxy, Method m, Object args) throws Throwable { Object result; try { System.out.println("before method " + m.getName()); result = m.invoke(obj, args); } catch (InvocationTargetException e) { throw e.getTargetException(); } catch (Exception e) { throw new RuntimeException("unexpected invocation exception: " + e.getMessage()); } finally { System.out.println("after method " + m.getName()); } return result; }}
rakentaa DebugProxy
Foo
liittymän toteuttamista varten ja soittaa jollekin sen menetelmistä:
Foo foo = (Foo) DebugProxy.newInstance(new FooImpl()); foo.bar(null);
tässä on esimerkki utility invocation handler-luokasta, joka tarjoaa oletuksena välityspalvelinkäyttäytymisen menetelmille, jotka on perittyjava.lang.Object
ja toteuttaa tiettyjen proxy method invocationien delegoinnin erillisille olioille riippuen kutsutun menetelmän käyttöalueesta:
import java.lang.reflect.*;public class Delegator implements InvocationHandler { // preloaded Method objects for the methods in java.lang.Object private static Method hashCodeMethod; private static Method equalsMethod; private static Method toStringMethod; static { try { hashCodeMethod = Object.class.getMethod("hashCode", null); equalsMethod = Object.class.getMethod("equals", new Class { Object.class }); toStringMethod = Object.class.getMethod("toString", null); } catch (NoSuchMethodException e) { throw new NoSuchMethodError(e.getMessage()); } } private Class interfaces; private Object delegates; public Delegator(Class interfaces, Object delegates) { this.interfaces = (Class) interfaces.clone(); this.delegates = (Object) delegates.clone(); } public Object invoke(Object proxy, Method m, Object args) throws Throwable { Class declaringClass = m.getDeclaringClass(); if (declaringClass == Object.class) { if (m.equals(hashCodeMethod)) { return proxyHashCode(proxy); } else if (m.equals(equalsMethod)) { return proxyEquals(proxy, args); } else if (m.equals(toStringMethod)) { return proxyToString(proxy); } else { throw new InternalError( "unexpected Object method dispatched: " + m); } } else { for (int i = 0; i < interfaces.length; i++) { if (declaringClass.isAssignableFrom(interfaces)) { try { return m.invoke(delegates, args); } catch (InvocationTargetException e) { throw e.getTargetException(); } } } return invokeNotDelegated(proxy, m, args); } } protected Object invokeNotDelegated(Object proxy, Method m, Object args) throws Throwable { throw new InternalError("unexpected method dispatched: " + m); } protected Integer proxyHashCode(Object proxy) { return new Integer(System.identityHashCode(proxy)); } protected Boolean proxyEquals(Object proxy, Object other) { return (proxy == other ? Boolean.TRUE : Boolean.FALSE); } protected String proxyToString(Object proxy) { return proxy.getClass().getName() + '@' + Integer.toHexString(proxy.hashCode()); }}
Delegator
alaluokat voivat ohittaainvokeNotDelegated
toteuttaakseen proxymethod-kutsujen käyttäytymisen,jota ei saa suoraan delegoida muille olioille, ja ne voivat kumota proxyHashCode
,proxyEquals
ja proxyToString
tooverrata niiden menetelmien oletuskäyttäytymisen, jotka proxy perii java.lang.Object
.
rakentaa Delegator
Foo
liittymän toteuttamista varten:
Class proxyInterfaces = new Class { Foo.class }; Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), proxyInterfaces, new Delegator(proxyInterfaces, new Object { new FooImpl() }));
huomaa, että edellä mainitun Delegator
– luokan toteutus on tarkoitettu enemmän havainnollistavaksi kuin optimoiduksi; esimerkiksi hashCode
, equals
ja toString
menetelmienMethod
objektien välimuistin ja vertailun sijaan se voisi vain vastata niitä niiden string-nimillä, koska yksikään näistä menetelmän nimistä ei ole ylikuormitettujava.lang.Object
.