– Szia Amigo.

– Helló, Rishi.

"Ma egy új és nagyon érdekes témát fogok elmagyarázni Önnek: a dinamikus proxykat" .

"A Java többféle módon módosíthatja egy adott osztály funkcióit..."

– Az első módszer az öröklődés.

"Az osztály viselkedésének megváltoztatásának legegyszerűbb módja egy új osztály létrehozása, amely örökli az eredeti (alap)osztályt, és felülírja a metódusait. Ezután az eredeti osztály használata helyett a származtatott osztályt használja. Például:"

Reader reader = new UserCustomReader();

"A második módszer egy wrapper osztály használata."

" A BufferedReader egy példa erre az osztálytípusra. Először is örökli a Readert . Más szavakkal, a Reader helyett használható. Másodszor, minden hívást átirányít az eredeti Reader objektumra, amelyet át kell adni a BufferedReader objektum konstruktorának . Például:"

Reader readerOriginal = new UserCustomReader();
Reader reader = new BufferedReader(readerOriginal);

"A harmadik módszer egy dinamikus proxy (Proxy) létrehozása."

"Létezik egy speciális osztály a Java-ban (java.lang.reflect.Proxy), amely valójában lehetővé teszi egy objektum létrehozását a program végrehajtása során (dinamikusan), anélkül, hogy külön osztályt hozna létre neki."

"Ezt nagyon könnyű megtenni:"

Reader reader = (Reader)Proxy.newProxyInstance();

– Ez már újdonság számomra!

"De természetesen nincs szükségünk metódus nélküli objektumra. Szükségünk van az objektumra, hogy rendelkezzenek metódusokkal, és szükségünk van rájuk, hogy azt csinálják, amit akarunk. A Java ehhez egy speciális interfészt használ, az úgynevezett InvocationHandlert, amely képes elfogni az összes metódushívást a proxy objektumhoz társítva . Proxy objektum csak interfészek segítségével hozható létre."

" Invoke – egy olyan metódus vagy osztály szabványos neve, amelynek elsődleges feladata egy metódus egyszerű meghívása."

" Handler – egy adott eseményt kezelő osztály szabványos neve. Például az egérkattintásokat kezelő osztály neve MouseClickHandler stb.."

"Az InvocationHandler felület egyetlen meghívási metódussal rendelkezik, amelyre a proxy objektum összes hívása irányul . Például:"

Kód
Reader reader = (Reader)Proxy.newProxyInstance(new CustomInvocationHandler());
reader.close();
class CustomInvocationHandler implements InvocationHandler
{
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
 {
  System.out.println("yes!");
  return null;
 }
}

"A Reader . close () metódus meghívásakor az invoke metódus hívódik meg, és a képernyőn az "igen!"

"Tehát deklaráltunk egy CustomInvocationHandler osztályt, és megvalósítottuk az InvocationHandler felületet és annak meghívó metódusát. Az invoke metódus meghívásakor az "igen" jelenik meg. Ezután létrehoztunk egy CustomInvocationHandler objektumot, és létrehozásakor átadtuk a newProxyInstance metódusnak. egy proxy objektum."

– Igen, ez mind helyes.

"Ez egy nagyon hatékony eszköz. Általában ezeket a proxykat arra hozták létre, hogy szimulálják az objektumokat olyan programokban, amelyek fizikailag futnak egy másik számítógépen.  Vagy a hozzáférés szabályozására."

"Ezzel a módszerrel ellenőrizheti az aktuális felhasználó engedélyeit, kezelheti a hibákat, naplózhatja a hibákat és még sok mást."

"Íme egy példa, ahol az invoke metódus az eredeti objektum metódusait is meghívja:"

Kód
Reader original = new UserCustomReader();

Reader reader = (Reader)Proxy.newProxyInstance(new CustomInvocationHandler(original));
reader.close();
class CustomInvocationHandler implements InvocationHandler
{
 private Reader readerOriginal;

 CustomInvocationHandler(Reader readerOriginal)
 {
  this.readerOriginal = readerOriginal;
 }

 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
 {
  if (method.getName().equals("close"))
  {
   System.out.println("Reader closed!");
  }

  // This calls the readerOriginal object's close method.
  // The method's name and a description of its parameters are stored in the method variable.
  return method.invoke(readerOriginal, args);
 }
}

"Ennek a példának két különlegessége van."

"Először az «eredeti» Reader objektumot adják át a konstruktornak, és a rá vonatkozó hivatkozást elmentik a CustomInvocationHandlerben . "

"Másodszor, ugyanazt a metódust hívjuk meg újra az invoke metódusban, de ezúttal az «eredeti» objektumon."

"Ah. Más szavakkal, ez az utolsó sor ugyanazt a metódust hívja meg, de az eredeti objektumon:"

return method.invoke(readerOriginal, args);

"Igen."

"Nem mondanám, hogy rendkívül nyilvánvaló, de akkor is érthető. Legalábbis annak tűnik."

"Remek. Aztán még egy dolog. A newProxyInstance metódusban egy kicsivel több háztartási információt kell átadni egy proxy objektum létrehozásához. De mivel nem hozunk létre szörnyű proxy objektumokat, ez az információ könnyen beszerezhető magától az eredeti osztálytól. "

"Íme egy másik példa:"

Kód
Reader original = new UserCustomReader();

ClassLoader classLoader = original.getClass().getClassLoader();
Class<?>[] interfaces = original.getClass().getInterfaces();
CustomInvocationHandler invocationHandler = new CustomInvocationHandler(original);

Reader reader = (Reader)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
class CustomInvocationHandler implements InvocationHandler
{
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
 {
  return null;
 }
}

"Ah. ClassLoader és az interfészek listája. Ez valami a Reflectionből van, nem?"

"Igen."

"Értem. Nos, azt hiszem, tudok létrehozni egy primitív, szuper egyszerű proxy objektumot, ha szükségem lesz rá."

– Akkor menj be Diegóhoz.