Java Reflection-Dynamic Proxies

Ved Hjelp Av Java Reflection oppretter du dynamiske implementeringer av grensesnitt under kjøring. Du gjør det ved å bruke klassen java.lang.reflect.Proxy. Navnet på denne klassen er grunnen til at jeg refererer til disse dynamiske grensesnittimplementeringene som dynamiske proxyer. Dynamiske proxyer kan brukes til mange forskjellige formål, for eksempel databaseforbindelse og transaksjonsadministrasjon, dynamiske mockobjekter for enhetstesting og andre aop-lignende metoder som avskjærer formål.

Opprette Proxyer

du oppretter dynamiske proxyer ved hjelp av metoden Proxy.newProxyInstance(). Metodene newProxyInstance() tar 3 parametere:

  1. ClassLoader som er å “laste” den dynamiske proxy-klassen.
  2. en rekke grensesnitt å implementere.
  3. En InvocationHandler for å videresende alle metoder kaller proxyen til.

her er et eksempel:

etter å ha kjørt denne koden inneholder proxy variabelen en dynamisk implementering av MyInterface – grensesnittet. Alle samtaler til proxyen vil bli videresendt til implementeringen av det generelle grensesnittet handler. InvocationHandler er dekket i neste avsnitt.

InvocationHandler ‘ s

som nevnt tidligere må du sende en InvocationHandler implementering til Proxy.newProxyInstance() – metoden. Alle metodekall til den dynamiske proxyen videresendes til denne InvocationHandler – implementeringen. Slik ser InvocationHandler – grensesnittet ut:

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

Her er et eksempel implementering:

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

parameteren proxy overført til metoden invoke() er det dynamiske proxy-objektet som implementerer grensesnittet. Oftest trenger du ikke dette objektet.

Method – objektet som overføres til invoke() – metoden, representerer metoden som kalles grensesnittet som den dynamiske proxyen implementerer. Fra Method – objektet kan du få metodenavn, parametertyper, returtype, etc. Se teksten På Metoder for mer informasjon.

matrisen Object args inneholder parameterverdiene som sendes til proxyen når metoden i det implementerte grensesnittet ble kalt. Merk: Primitiver (int, lang etc) i implementert grensesnitt er pakket inn i sine objekt kolleger(Heltall, Lang etc.).

Kjente Brukstilfeller

Dynamiske proxyer er kjent for å brukes til minst følgende formål:

  • Databasetilkobling Og Transaksjonsbehandling
  • Dynamiske Mock Objekter For Enhetstesting
  • Tilpasning AV Di Container Til Egendefinerte Fabrikkgrensesnitt
  • Aop-lignende Metode Avskjæring

Databasetilkobling Og Transaksjonsbehandling

Fjærrammeverket har en transaksjonsproxy som kan starte og forplikte / tilbakeføre en transaksjon for deg. Hvordan dette fungerer er beskrevet mer detaljert i teksten Advanced Connection And Transaction Demarcation and Propagation, så jeg vil bare beskrive det kort. Anropssekvensen blir noe langs dette:

Dynamiske Mockobjekter For Enhetstesting

Butterfly-Testverktøyene bruker dynamiske proxyer for å implementere dynamiske stubber, mocks og proxyer for enhetstesting. Når du tester en klasse A som bruker en annen klasse b (grensesnitt virkelig), kan du sende en mock implementering Av B til A i stedet For en ekte B. Alle metodekall På B registreres nå, og du kan angi hvilke returverdier mock B skal returnere.

Videre Butterfly Testverktøy lar deg pakke inn en ekte B i en mock B, slik at alle metodekall på mock blir registrert, og deretter videresendt til den virkelige B. Dette gjør det mulig å sjekke hvilke metoder som ble kalt på en ekte fungerende B. For eksempel, hvis du tester EN DAO, kan du pakke databaseforbindelsen i en mock. DAO vil ikke se forskjellen, OG DAO kan lese / skrive data til databasen som vanlig siden mock videresender alle anrop til databasen. Men nå kan du sjekke via mock hvis DAO bruker tilkoblingen riktig, for eksempel hvis connection.close() kalles (eller ikke kalt), hvis du forventet det. Dette er normalt ikke mulig å bestemme fra returverdien til EN DAO.

Tilpasning AV Di Container Til Tilpassede Fabrikkgrensesnitt

Dependency injection container Butterfly Container har en kraftig funksjon som lar deg injisere hele beholderen i bønner produsert av den. Men siden du ikke vil ha en avhengighet av beholdergrensesnittet, er beholderen i stand til å tilpasse seg et tilpasset fabrikkgrensesnitt av designet ditt. Du trenger bare grensesnittet. Ingen implementering. Dermed kan fabrikkgrensesnittet og klassen din se noe ut som dette:

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

når klassen MyAction kaller metoder på forekomsten IMyFactory injisert i konstruktøren av beholderen, oversettes metodekall til kall til metoden IContainer.instance(), som er metoden du bruker til å hente forekomster fra beholderen. På den måten kan et objekt bruke Sommerfuglbeholder som en fabrikk under kjøring, i stedet for bare å ha avhengigheter injisert i seg selv ved opprettelsestid. Og dette uten å ha noen avhengigheter på Noen Butterfly Container spesifikke grensesnitt.

Aop-lignende Metode Avskjæring

Fjærrammen gjør Det mulig å avskjære metodekall til en gitt bønne, forutsatt at bønne implementerer noe grensesnitt. Vårrammen bryter bønnen i en dynamisk proxy. Alle anrop til bønnen blir deretter oppfanget av proxyen. Proxyen kan bestemme seg for å ringe andre metoder på andre objekter enten før, i stedet for, eller etter å delegere metodekallet til bønnen innpakket.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert.