Java reflectie-dynamische Proxies

met Java reflectie maakt u dynamische implementaties van interfaces tijdens runtime. U doet dit met de klasse java.lang.reflect.Proxy. De naam van deze klasse is waarom ik refereer aan deze dynamische interface implementaties als dynamische proxies. Dynamische proxies kunnen worden gebruikt voor veel verschillende doeleinden, bijvoorbeeld database verbinding en transactiebeheer, dynamische mock objecten voor unit testen, en andere AOP-achtige methode onderschepping doeleinden.

Proxies

u maakt dynamische proxies met behulp van de methode Proxy.newProxyInstance(). De newProxyInstance() methoden hebben 3 parameters:

  1. de ClassLoader die de dynamische proxy-klasse moet” laden”.
  2. een reeks te implementeren interfaces.
  3. An InvocationHandler om alle methodenaanroepen op de proxy door te sturen naar.

hier is een voorbeeld:

na het uitvoeren van deze code bevat de variabele proxy een dynamische implementatie van de interface MyInterface. Alle oproepen naar de proxy worden doorgestuurd naar de handler implementatie van de Algemene InvocationHandler interface. Invocation Handler ‘ s worden behandeld i de volgende sectie.

InvocationHandler ‘ s

zoals eerder vermeld moet u een InvocationHandler implementatie doorgeven aan de Proxy.newProxyInstance() methode. Alle methodeaanroepen naar de dynamische proxy worden doorgestuurd naar deze InvocationHandler implementatie. Zo ziet de interface InvocationHandler eruit:

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

hier is een voorbeeld implementatie:

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

de parameter proxy die wordt doorgegeven aan de methode invoke() is het dynamische proxy-object dat de interface implementeert. Meestal heb je dit object niet nodig.

het Method object doorgegeven aan de invoke() methode vertegenwoordigt de methode aangeroepen op de interface die de dynamische proxy implementeert. Van het Method object kunt u de method name, parameter types, return type, etc. Zie de tekst over methoden voor meer informatie.

de Object args array bevat de parameterwaarden die aan de proxy zijn doorgegeven toen de methode in de geà mplementeerde interface werd aangeroepen. Opmerking: Primitieven (int, long etc) in de geà mplementeerde interface worden verpakt in hun object tegenhangers (Integer, Long etc.).

Bekend Use Cases

Dynamische proxy ‘ s zijn bekend om gebruikt te worden voor ten minste de volgende doeleinden:

  • Database Verbinding en Transaction Management
  • Dynamische Mock-Objecten voor Unit Testing
  • Aanpassing van DI-Container Custom Factory Interfaces
  • AOP-achtige Methode Onderschepping

Database Verbinding en Transaction Management

Het Spring framework is een transactie proxy kan beginnen en commit / rollback van een transactie voor u. Hoe dit werkt wordt in meer detail beschreven in de tekst Advanced Connection and Transaction Demarcation and Propagation, dus Ik zal het maar kort beschrijven. De aanroepvolgorde wordt iets in deze richting:

dynamische Mockobjecten voor Unit Testing

de Butterfly Testing Tools maakt gebruik van dynamische proxies om dynamische stubs, mocks en proxies voor unit testing te implementeren. Bij het testen van een klasse A die gebruik maakt van een andere klasse B (interface echt), kunt u een mock implementatie van B doorgeven aan A in plaats van een echte B. Alle methode aanroepen op B worden nu opgenomen, en u kunt instellen welke return waarden de mock B is om terug te keren.

verder staan Butterfly Testing Tools je toe om een echte B in een mock B te wikkelen, zodat alle methodeaanroepen op de mock worden opgenomen en vervolgens doorgestuurd naar de echte B. Dit maakt het mogelijk om te controleren welke methoden werden aangeroepen op een echt functionerende B. bijvoorbeeld, als je een DAO test kun je de database verbinding in een mock wikkelen. De DAO zal het verschil niet zien, en de DAO kan gegevens lezen/schrijven naar de database Zoals gebruikelijk omdat de mock alle oproepen doorstuurt naar de database. Maar nu kun je via de mock controleren of de DAO de verbinding correct gebruikt, bijvoorbeeld of de connection.close() wordt aangeroepen( of niet), als je dat verwachtte. Dit is normaal gesproken niet mogelijk om te bepalen aan de hand van de retourwaarde van een DAO.

aanpassing van DI-Container aan aangepaste Fabrieksinterfaces

de dependency injection container Butterfly Container heeft een krachtige functie waarmee u de hele container kunt injecteren in bonen die er worden geproduceerd. Maar omdat u niet afhankelijk wilt zijn van de container-interface, kan de container zich aanpassen aan een aangepaste fabrieksinterface van uw ontwerp. Je hebt alleen de interface nodig. Geen uitvoering. Dus de fabrieksinterface en je klas kunnen er ongeveer zo uitzien:

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

wanneer de MyAction class call methods op de IMyFactory instance geà njecteerd in de constructor door de container, worden de method calls vertaald in calls naar de IContainer.instance() method, dat is de methode die u gebruikt om instanties van de container te verkrijgen. Op die manier kan een object Butterfly Container gebruiken als een fabriek tijdens runtime, in plaats van alleen om afhankelijkheden geïnjecteerd in zichzelf op de creatie tijd. En dit zonder enige afhankelijkheden op een vlinder Container specifieke interfaces.

AOP-achtige methode onderschepping

het Spring framework maakt het mogelijk om methodeaanroepen naar een bepaalde bean te onderscheppen, op voorwaarde dat bean een interface implementeert. Het Spring framework wikkelt de boon in een dynamische proxy. Alle oproepen naar de bean worden dan onderschept door de proxy. De proxy kan besluiten om andere methoden op andere objecten aan te roepen, hetzij voor, in plaats van, of na het delegeren van de methode aanroep aan de bean wrapped.

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.