Java Reflection-dynamiske fuldmagter

Brug Java Reflection du oprette dynamiske implementeringer af grænseflader på runtime. Du gør det ved hjælp af klassen java.lang.reflect.Proxy. Navnet på denne klasse er grunden til, at jeg henviser til disse dynamiske interfaceimplementeringer som dynamiske fuldmagter. Dynamiske fuldmagter kan bruges til mange forskellige formål, f.eks. databaseforbindelse og transaktionsstyring, dynamiske mock-objekter til enhedstest og andre AOP-lignende metode-aflytningsformål.

oprettelse af fuldmagter

du opretter dynamiske fuldmagter ved hjælp af metoden Proxy.newProxyInstance(). newProxyInstance() metoderne tager 3 parametre:

  1. den ClassLoader, der er at” indlæse ” den dynamiske fuldmagtsklasse.
  2. en række grænseflader til implementering.
  3. en InvocationHandler for at videresende alle metoder opfordrer fuldmagten til.

her er et eksempel:

efter at have kørt denne kode indeholder variablen proxy en dynamisk implementering af grænsefladen MyInterface. Alle opkald til fuldmagten vil blive videresendt til handler implementeringen af den generelle InvocationHandler grænseflade. InvocationHandler er dækket i det næste afsnit.

InvocationHandler ‘ s

som tidligere nævnt skal du bestå en InvocationHandler implementering til Proxy.newProxyInstance() metoden. Alle metodeopkald til den dynamiske fuldmagt videresendes til denne InvocationHandler implementering. Her er hvordan InvocationHandler interface ser ud:

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, der overføres til metoden invoke(), er det dynamiske fuldmagtsobjekt, der implementerer grænsefladen. Ofte har du ikke brug for dette objekt.

Method – objektet, der overføres til invoke() – metoden, repræsenterer den metode, der kaldes på grænsefladen, som den dynamiske fuldmægtig implementerer. Fra Method objektet kan du få metodenavnet, parametertyperne, returtypen osv. Se teksten om metoder for mere information.

arrayet Object args indeholder parameterværdierne, der blev sendt til fuldmagten, da metoden i den implementerede grænseflade blev kaldt. Bemærk: primitiver (int, lang osv.) i den implementerede grænseflade er pakket ind i deres objektmodeller (heltal, lang osv.).

kendte brugssager

dynamiske fuldmagter vides at blive brugt til mindst følgende formål:

  • databaseforbindelse og transaktionsstyring
  • dynamiske Mock-objekter til enhedstest
  • tilpasning af DI Container til brugerdefinerede Fabriksgrænseflader
  • AOP-lignende metode aflytning

databaseforbindelse og transaktionsstyring

Fjederrammen har en transaktionsrepræsentant, der kan starte og begå / tilbagekalde en transaktion for dig. Hvordan dette fungerer er beskrevet mere detaljeret i teksten avanceret forbindelse og Transaktionsafgrænsning og udbredelse , så jeg beskriver det kun kort. Opkaldssekvensen bliver noget langs dette:

dynamiske Mock-objekter til enhedstest

Sommerfugletestværktøjerne bruger dynamiske fuldmagter til at implementere dynamiske stubber, mocks og fuldmagter til enhedstest. Når du tester en klasse A, der bruger en anden klasse B (interface virkelig), kan du overføre en mock-implementering af B til A i stedet for en rigtig B. Alle metodeopkald på B registreres nu, og du kan indstille, hvilke returværdier mock B skal returnere.

desuden Sommerfugletestværktøjer giver dig mulighed for at pakke en rigtig B i en mock B, så alle metodeopkald på mocken registreres og derefter videresendes til den rigtige B. Dette gør det muligt at kontrollere, hvilke metoder der blev kaldt på en rigtig fungerende B. For eksempel, hvis du tester en DAO, kan du pakke databaseforbindelsen i en mock. DAO vil ikke se forskellen, og DAO kan læse/skrive data til databasen som sædvanlig, da mock videresender alle opkald til databasen. Men nu Kan du tjekke via mock, om DAO bruger forbindelsen korrekt, for eksempel hvis connection.close() kaldes (eller ikke kaldes), hvis du forventede det. Dette er normalt ikke muligt at bestemme ud fra returværdien af en DAO.

tilpasning af DI Container til brugerdefinerede Fabriksgrænseflader

Dependency injection container Butterfly Container har en kraftfuld funktion, der giver dig mulighed for at injicere hele beholderen i bønner produceret af den. Men da du ikke ønsker en afhængighed af containergrænsefladen, er containeren i stand til at tilpasse sig en brugerdefineret fabriksgrænseflade i dit design. Du har kun brug for grænsefladen. Ingen implementering. Således fabrikken interface og din klasse kunne se noget som dette:

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

når klassen MyAction kalder metoder på forekomsten IMyFactory injiceret i dens konstruktør af containeren, oversættes metodeopkaldene til opkald til metoden IContainer.instance(), som er den metode, du bruger til at hente forekomster fra containeren. På den måde kan et objekt bruge Sommerfuglbeholder som en fabrik ved kørsel, snarere end kun at få afhængigheder injiceret i sig selv på oprettelsestidspunktet. Og dette uden at have nogen afhængigheder på nogen Butterfly Container specifikke grænseflader.

AOP-lignende metode aflytning

Fjederrammen gør det muligt at opfange metodeopkald til en given bønne, forudsat at bean implementerer en vis grænseflade. Fjederrammen indpakker bønnen i en dynamisk fuldmagt. Alle opkald til bønnen opfanges derefter af fuldmagten. Fuldmægtigen kan beslutte at kalde andre metoder på andre objekter enten før, i stedet for eller efter delegering af metodeopkaldet til bønne indpakket.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.