Dynaamiset Välityspalvelinluokat

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 Objectcontaining 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:

  • kaikkienClass olioiden interfaces joukossa tulee edustaa rajapintoja, ei-luokkia tai primitiivisiä tyyppejä.
  • interfaces joukon kaksi alkuainetta eivät voi viitata identtisiin Class olioihin.
  • kaikkien liitäntätyyppien on oltava näkyvillä nimen mukaisesti määritellyn luokkakuormaajan kautta. Toisin sanoen luokkakuormaajancl ja jokaisen rajapinnan i 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ä), kutsumalla getMethods sen Class objectwill palauttaa joukon Method 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 palauttaa Proxy.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, kuten java.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-luokallaan Foo 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, niin IllegalArgumentException heitetään.
  • rajapintamenetelmän kutsuminen välitysilmoituksella koodataan ja lähetetään kutsunkäsittelijäninvoke – 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, kuten java.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. Jos invoke: n palauttama arvo on null 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 interfacemethodin throws lausekkeessa ilmoitetuista poikkeustyypeistä, niin UndeclaredThrowableExceptionheitetään menetelmän kutsulla välitysilmaisuun. UndeclaredThrowableException konstruoidaan invoke – menetelmällä heitettyä poikkeusta lukuun ottamatta.

  • hashCode,equals tai toString proxy-instanssissajava.lang.Object ilmoitetut menetelmät koodataan ja lähetetään kutsunkäsittelijän invoke – menetelmään samalla tavalla kuin rajapintamenetelmän kutsut koodataan ja lähetetään edellä kuvatulla tavalla. Method kohteen ilmoitusluokka invoke tulee olemaan java.lang.Object. Muita java.lang.Object: ltä periytyviä julkisia proxyinstance-menetelmiä ei syrjitä proxy-luokka, joten näiden menetelmien käyttö on samanlaista kuin java.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 Methodkutsunkä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 toStringjava.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ä Methodvastustaa 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: writeExternalja readExternalExternalizable – 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 serialVersionUID0L. Toisin sanoen kun proxy-luokan Class objekti siirretään java.io.ObjectStreamClass staattisellelookup – menetelmälle, palautetullaObjectStreamClass – ilmentymällä on seuraavat ominaisuudet:

  • getSerialVersionUID – menetelmään vedoten 0L.
  • vedoten getFields – menetelmäänsä palauttaa arrayofin pituuden nollaksi.
  • vetoamalla getField menetelmäänsä millä tahansaString argumentilla palaa null.

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_PROXYCLASSDESCnewwhandle 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)

, jossaloaderon 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.getProxyClassheittääIllegalArgumentException,resolveClassheittää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.

Vastaa

Sähköpostiosoitettasi ei julkaista.