2009-06-01 10 views

Odpowiedz

13

Gorąco polecam ten resource.

Przede wszystkim musisz zrozumieć, co jest wzorcem użycia proxy.Pamiętaj, że głównym zamiarem proxy jest kontrolowanie dostępu do obiektu docelowego w celu uzyskania dostępu do obiektu docelowego . Kontrola dostępu obejmuje synchronizację, uwierzytelnianie, dostęp zdalny (RPC), leniwe tworzenie wystąpień (Hibernate, Mybatis), AOP (transakcja).

W przeciwieństwie do statycznego proxy, dynamiczne proxy generuje kod bajtowy, który wymaga odbicia Java w czasie wykonywania. Dzięki dynamice nie musisz tworzyć klasy proxy, co może prowadzić do większej wygody.

+0

i link jest zepsuty – bvdb

+0

Dzięki za link ... Bardzo pomocne. – worked

+0

Myślę, że to najlepsza odpowiedź. Inne odpowiedzi zawierają bardzo długie trudne trudności, których nigdy nie będę w stanie zrozumieć w moim życiu. Link właśnie mi pomógł, krok po kroku. – SWIIWII

5

Jednym z przypadków użycia jest hibernacja - daje obiekty implementujące interfejs klas modeli, ale w ramach programów pobierających i ustawiających znajduje się kod związany z db. To znaczy. używasz ich tak, jakby były po prostu POJO, ale w rzeczywistości wiele się dzieje pod osłoną.

Na przykład - po prostu wywołujemy getter z leniwie ładowanej właściwości, ale tak naprawdę właściwość (prawdopodobnie cała duża struktura obiektu) zostaje pobrana z bazy danych. Aby uzyskać więcej informacji, należy sprawdzić bibliotekę cglib, aby uzyskać więcej informacji.

28

klasa dynamiczna Pełnomocnik to klasa realizuje lista interfejsów określone w czasie pracy tak, że wariant a wywołanie przez jednym z interfejsów na przykład klasy będą zakodowane wysłana do innego obiekt przez jednolity interfejs. Może być to użyte do utworzenia bezpiecznego obiektu proxy typu dla listy interfejsów bez potrzeby wstępnego generowania klasy proxy. Dynamiczne proxy klasy są użyteczne dla aplikacji lub biblioteki, które muszą zapewniać odbieranie bezpiecznych typów wywołań typuna obiektach, które oferują interfejsy API interfejsu .

Dynamic Proxy Classes

+0

Dobra odpowiedź, a dobrym przykładem tej samej rzeczy jest Wiosna Remoting, który ma wbudowane możliwości serwera proxy dla HTTP, RMI, EJB i JMS . – Robin

16

właśnie wymyślił jakieś ciekawe zastosowanie dla dynamicznego proxy.

Mieliśmy problemy z niekrytyczną usługą, która jest powiązana z inną zależną usługą i chcieliśmy zbadać sposoby zachowania odporności na awarie, gdy ta zależna usługa staje się niedostępna.

Tak więc napisałem LoadSheddingProxy, który przyjmuje dwóch uczestników - jeden jest zdalnym imp dla "normalnej" usługi (po wyszukiwaniu JNDI). Drugi obiekt to "sztuczny" impond zrzucający obciążenie. Istnieje prosta logika otaczająca każdą metodę invoke, która łapie limity czasu i przenosi się do manekina przez określony czas, zanim spróbujesz ponownie. Oto jak go używać:

// This is part of your ServiceLocator class 
public static MyServiceInterface getMyService() throws Exception 
{ 
    MyServiceInterface loadShedder = new MyServiceInterface() { 
     public Thingy[] getThingys(Stuff[] whatever) throws Exception { 
      return new Thingy[0]; 
     } 
     //... etc - basically a dummy version of your service goes here 
    }   
    Context ctx = JndiUtil.getJNDIContext(MY_CLUSTER); 
    try { 
     MyServiceInterface impl = ((MyServiceHome) PortableRemoteObject.narrow(
       ctx.lookup(MyServiceHome.JNDI_NAME), 
       MyServiceHome.class)).create(); 
     // Here's where the proxy comes in 
     return (MyService) Proxy.newProxyInstance(
      MyServiceHome.class.getClassLoader(), 
     new Class[] { MyServiceInterface.class }, 
     new LoadSheddingProxy(MyServiceHome.JNDI_NAME, impl, loadShedder, 60000)); // 10 minute retry 
    } catch (RemoteException e) { // If we can't even look up the service we can fail by shedding load too 
     logger.warn("Shedding load"); 
     return loadShedder; 
    } finally { 
     if (ctx != null) { 
     ctx.close(); 
     } 
    } 
} 

A oto proxy:

public class LoadSheddingProxy implements InvocationHandler { 

static final Logger logger = ApplicationLogger.getLogger(LoadSheddingProxy.class); 

Object primaryImpl, loadDumpingImpl; 
long retry; 
String serviceName; 
// map is static because we may have many instances of a proxy around repeatedly looked-up remote objects 
static final Map<String, Long> servicesLastTimedOut = new HashMap<String, Long>(); 

public LoadSheddingProxy(String serviceName, Object primaryImpl, Object loadDumpingImpl, long retry) 
{ 
    this.serviceName = serviceName; 
    this.primaryImpl = primaryImpl; 
    this.loadDumpingImpl = loadDumpingImpl; 
    this.retry = retry; 
} 

public Object invoke(Object obj, Method m, Object[] args) throws Throwable 
{ 
    try 
    { 
     if (!servicesLastTimedOut.containsKey(serviceName) || timeToRetry()) { 
      Object ret = m.invoke(primaryImpl, args); 
      servicesLastTimedOut.remove(serviceName); 
      return ret; 
     } 
     return m.invoke(loadDumpingImpl, args); 
    } 
    catch (InvocationTargetException e) 
    { 
     Throwable targetException = e.getTargetException(); 

     // DETECT TIMEOUT HERE SOMEHOW - not sure this is the way to do it??? 
     if (targetException instanceof RemoteException) { 
      servicesLastTimedOut.put(serviceName, Long.valueOf(System.currentTimeMillis())); 
     } 
     throw targetException; 
    }      
} 

private boolean timeToRetry() { 
    long lastFailedAt = servicesLastTimedOut.get(serviceName).longValue(); 
    return (System.currentTimeMillis() - lastFailedAt) > retry; 
} 
}