Java Reflection Proxy | 1 http://www.nerdammer.it La classe java

Java Reflection Proxy | 1
La classe java.lang.reflect.Proxy è, senza troppi preamboli, la
base di tutti i framework Java che si fondano sui principi della
programmazione ad aspetti, e forse anche di tutti quelli che
ne fanno a meno.
Attraverso questa classe, è possibile generare a runtime degli oggetti che implementano un
determinato insieme di interfacce, anche se tali interfacce sono sconosciute al momento
della compilazione o addirittura ancora non concepite dal programmatore. E’ attraverso
questa classe che l’application server riesce a fornire una implementazione per gli EJB della
nostra applicazione, arricchendo dei semplici metodi con funzioni definite dalle specifiche JPA,
JTA, JMS, JNDI etc. etc.
Per quanto riguarda il paradigma ad aspetti, la classe proxy si adatta perfettamente
all’implementazione di classi interceptor. Ad esempio, consideriamo la seguente interfaccia:
[JAVA]
public interface MyObject {
public void myMethod();
}
[/JAVA]
… ed una classe che la implementa:
[JAVA]
import java.util.logging.Logger;
public class MyObjectImpl implements MyObject {
@Override
http://www.nerdammer.it
Java Reflection Proxy | 2
public void myMethod() {
logger.severe(“Implementazione metodo”);
}
}
[/JAVA]
A questa semplice classe è possibile aggiungere delle funzionalità non previste dal
programmatore e senza effettivamente far riferimento ad essa, e nemmeno alla sua
interfaccia. Definiamo un interceptor che non fa altro che aggiungere delle righe di log prima
e dopo l’invocazione di ogni metodo della “classe intercettata”:
[JAVA]
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.logging.Logger;
public class LogInterceptor implements InvocationHandler {
private static Logger logger = Logger.getAnonymousLogger();
private Object target;
private LogInterceptor(Object target) {
this.target = target;
}
@SuppressWarnings(“unchecked”)
public static T getProxy(T target) {
Class[] interfaces = target.getClass().getInterfaces();
InvocationHandler handler = new LogInterceptor(target);
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), interfaces, handler);
}
http://www.nerdammer.it
Java Reflection Proxy | 3
@Override
public Object invoke(Object proxy, Method method, Object[] parameters) throws Throwable {
try {
logger.info(“Inizio invocazione metodo ” + method.getName());
Object result = method.invoke(target, parameters);
logger.info(“Fine metodo ” + method.getName());
return result;
} catch(Throwable t) {
logger.info(“Fine metodo ” + method.getName() + ” con errore”);
throw t;
}
}
}
[/JAVA]
L’interceptor appena creato può essere agganciato a qualsiasi oggetto per mezzo del metodo
statico getProxy, il quale utilizza la reflection (ed in particolare la classe Proxy) per creare
istanze virtuali degli oggetti specificati nei parametri.
Il tutto può essere utilizzato con le seguenti poche righe di codice:
[JAVA]
public class Test {
public static void main(String[] args) {
MyObject target = new MyObjectImpl();
MyObject interceptedInstance = LogInterceptor.getProxy(target);
interceptedInstance.myMethod();
}
}
http://www.nerdammer.it
Java Reflection Proxy | 4
[/JAVA]
Invocando il metodo myMethod sull’oggetto interceptedInstance verranno stampate sul log le
tre righe attese (due sono definite nella classe interceptor, una è presente nella classe
MyObjectImpl).
Poichè sia l’oggetto target che l’oggetto proxy (interceptedInstance) implementano la stessa
interfaccia (MyObject), il proxy può essere sostituito al target in tutti i punti del codice (se il
codice è scritto con tutti i crismi !!), aggiungendo funzionalità di log che non erano state
previste all’inizio.
Condividi:
Fai clic qui per condividere su Twitter (Si apre in una nuova finestra)
Fai clic per condividere su Facebook (Si apre in una nuova finestra)
Fai clic qui per condividere su Google+ (Si apre in una nuova finestra)
Fai clic qui per condividere su LinkedIn (Si apre in una nuova finestra)
Fai clic qui per inviare l'articolo via mail ad un amico (Si apre in una nuova finestra)
http://www.nerdammer.it