"Hi, Amigo."

"Hello, Rishi."

"Ngayon ay ipapaliwanag ko sa iyo ang isang bago at napaka-kawili-wiling paksa: mga dynamic na proxy" .

"May ilang paraan ang Java para baguhin ang functionality ng isang partikular na klase..."

"Ang unang paraan ay mana."

"Ang pinakamadaling paraan upang baguhin ang gawi ng isang klase ay ang lumikha ng bagong klase na nagmamana ng orihinal na (base) na klase, at i-override ang mga pamamaraan nito. Pagkatapos, sa halip na gamitin ang orihinal na klase, ginagamit mo ang nagmula na klase. Halimbawa:"

Reader reader = new UserCustomReader();

"Ang pangalawang paraan ay ang paggamit ng klase ng wrapper."

" Ang BufferedReader ay isang halimbawa ng ganitong uri ng klase. Una, namamana nito ang Reader . Sa madaling salita, maaari itong gamitin sa halip na Reader. Pangalawa, nire-redirect nito ang lahat ng tawag sa orihinal na object ng Reader , na dapat ipasa sa constructor ng object ng BufferedReader . Halimbawa:"

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

"Ang ikatlong paraan ay ang lumikha ng isang dynamic na proxy (Proxy)."

"May isang espesyal na klase sa Java (java.lang.reflect.Proxy) na talagang hinahayaan kang bumuo ng isang bagay sa panahon ng pagpapatupad ng programa (dynamic), nang hindi gumagawa ng hiwalay na klase para dito."

"Ito ay napakadaling gawin:"

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

"Iyan ay bago na sa akin!"

"Ngunit siyempre, hindi namin kailangan ang isang bagay na walang mga pamamaraan. Kailangan namin ang bagay na may mga pamamaraan, at kailangan namin ang mga ito upang gawin ang gusto namin. Gumagamit ang Java ng isang espesyal na interface para dito na tinatawag na InvocationHandler , na maaaring humarang sa lahat ng mga tawag sa pamamaraan nauugnay sa proxy object. Magagawa lang ang proxy object gamit ang mga interface."

" Invoke - ay ang karaniwang pangalan para sa isang pamamaraan o klase na ang pangunahing gawain ay tumawag lamang ng ilang pamamaraan."

" Handler – ay ang karaniwang pangalan para sa isang klase na humahawak ng ilang kaganapan. Halimbawa, ang isang klase na humahawak ng mga pag-click ng mouse ay tatawaging MouseClickHandler, atbp."

"Ang InvocationHandler interface ay may iisang paraan ng pag-invoke, kung saan ang lahat ng mga tawag sa proxy object ay nakadirekta . Halimbawa:"

Code
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;
 }
}

"Kapag tinawag ang reader na . close () method, ang invoke method ay tatawagin, at ang screen ay magpapakita ng 'oo!'"

"Kaya, nagdeklara kami ng CustomInvocationHandler, class, at ipinatupad ang InvocationHandler interface at ang invoke method nito. Kapag tinawag ang invoke method, ipinapakita nito ang 'yes!'. Pagkatapos ay gumawa kami ng CustomInvocationHandler object, at ipinasa ito sa newProxyInstance method kapag gumagawa isang proxy object."

"Oo, tama lahat iyan."

"Ito ay isang napakalakas na tool. Karaniwan, ang mga proxy na ito ay nilikha upang gayahin ang mga bagay sa mga program na aktwal na tumatakbo sa isa pang computer.  O upang kontrolin ang pag-access."

"Maaari mong suriin ang mga pahintulot ng kasalukuyang user, pangasiwaan ang mga error, mga error sa pag-log, at marami pang iba sa paraang ito."

"Narito ang isang halimbawa kung saan tinatawag din ng paraan ng pag-invoke ang mga pamamaraan ng orihinal na bagay:"

Code
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);
 }
}

"Ang halimbawang ito ay may dalawang espesyal na tampok."

"Una, ang «orihinal» Reader object ay ipinapasa sa constructor, at isang reference dito ay nai-save sa loob ng CustomInvocationHandler ."

"Pangalawa, tinatawag naming muli ang parehong paraan sa invoke method, ngunit sa «orihinal» object sa pagkakataong ito."

"Ah. Sa madaling salita, ang huling linyang ito ay tumatawag sa parehong paraan, ngunit sa orihinal na bagay:"

return method.invoke(readerOriginal, args);

"Oo."

"I wouldn't say na super obvious, pero understandable pa rin. O parang."

"Mahusay. Pagkatapos ng isa pang bagay. Sa bagongProxyInstance na paraan, kailangan mong magpasa ng kaunti pang impormasyon sa housekeeping upang lumikha ng proxy object. Ngunit dahil hindi kami gumagawa ng napakapangit na proxy object, ang impormasyong ito ay madaling makuha mula sa orihinal na klase mismo. "

"Narito ang isa pang halimbawa:"

Code
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 at listahan ng mga interface. This is something from Reflection, di ba?"

"Oo."

"I see. Well, I think I can create a primitive, super simple proxy object if I ever need one."

"Then go check in with Diego."