| Sign In/My Account | View Cart |
Dynamic Delegation and Its Applications
Pages: 1, 2, 3
Did you ever want to delegate an object of an existing Java core class? Delegate it as usual.
//DateTest.java
package org.jingle.util.dydelegation.sample;
import java.lang.reflect.Method;
import java.util.Date;
import org.jingle.util.dydelegation.DelegationGenerator;
import org.jingle.util.dydelegation.DelegationInvocationHandler;
import org.jingle.util.dydelegation.DummyInvocationHandler;
public class DateTest {
public static void main(String[] args) {
Date date = new Date();
DelegationInvocationHandler handler =
new DateClassHandler();
Date delegation = (Date) DelegationGenerator
.newDelegationInstance(date, handler);
System.out.println("Delegation class = " +
delegation.getClass().getName());
System.out.println("True date = " +
date.getTime());
System.out.println("Delegation date = " +
delegation.getTime());
}
}
class DateClassHandler extends DummyInvocationHandler {
public Object invokeAfter(Object bean,
Method method, Object[] args,
Object result) throws Throwable {
if (method.getName().equals("getTime")) {
return new Long(((Long)result).longValue() - 1000);
}
return super.invokeAfter(bean, method, args, result);
}
}
Output:
Delegation class = org.jingle.util.dydelegation.Date_Delegation_0
True date = 1099380377665
Delegation date = 1099380376665
When creating a delegation class for a Java core class, the delegation class will not be in the same
package as the Java core class, because the Java security model does not allow a user-defined ClassLoader
to define a class in a package starting with java.
DateClassHandler catches the getTime() method call in invokeAfter(), and
makes the return value 1000 less than the normal return value.
Can Dynamic Delegation do what Proxy does? Absolutely! Dynamic Delegation
covers the functions of Proxy. Given a proper delegation handler, it can simulate the behavior
of a Java Proxy.
// ProxyTest.java
package org.jingle.util.dydelegation.sample;
import java.lang.reflect.Method;
import org.jingle.util.dydelegation.DelegationGenerator;
import org.jingle.util.dydelegation.DelegationInvocationHandler;
import org.jingle.util.dydelegation.DummyInvocationHandler;
import org.jingle.util.dydelegation.sample.bean.Idel1;
import org.jingle.util.dydelegation.sample.bean.Idel2;
public class ProxyTest {
public static void main(String[] args) {
DelegationInvocationHandler handler = new ProxyHandler();
Object delegation =
DelegationGenerator.newDelegationInstance(null,
new Class[] { Idel1.class, Idel2.class },
null, handler);
((Idel1) delegation).idel1();
((Idel2) delegation).idel2();
}
}
class ProxyHandler extends DummyInvocationHandler {
public boolean invokeBefore(Object bean,
Method method, Object[] args)
throws Throwable {
return false;
}
public Object invokeAfter(Object bean,
Method method, Object[] args,
Object result) throws Throwable {
String name = method.getName();
if (name.equals("idel1"))
System.out.println("Hello from idel1");
else if (name.equals("idel2"))
System.out.println("Hello from idel2");
return super.invokeAfter(bean, method, args, result);
}
}
Output:
Hello from idel1
Hello from idel2
ProxyHandler returns false in invokeBefore(), which means all of the method calls on the
delegation object will not be delegated to the original object. It uses invokeAfter() to define
the delegation behavior as being what Proxy does.
DelegationGenerator.newDelegationInstance() has another version. It contains four arguments:
Object to be delegated.
This can be null. If it is not null, it must be an instance of
all of the given classes and interfaces.
Class to be delegated.
This can contain multiple interfaces and, at most, one class.
If null, a system-generated name will be provided.
DelegationInvocationHandler instance, which is used to define the delegation's behavior.From the output, we can see that the delegation object is an instance of both Idel1
and Idel2. Its behavior is just what is defined in the handler.
Until now, we've delegated all of the functions of the specific object. How about just delegating part of the object's functions?
//MyDate.java
package org.jingle.util.dydelegation.sample.bean;
import java.util.Date;
public class MyDate extends Date implements Idel1, Idel2 {
public void idel1() {
}
public void idel2() {
}
}
// MyDateTest.java
package org.jingle.util.dydelegation.sample;
import java.util.Date;
import org.jingle.util.dydelegation.DelegationGenerator;
import org.jingle.util.dydelegation.DelegationInvocationHandler;
import org.jingle.util.dydelegation.DummyInvocationHandler;
import org.jingle.util.dydelegation.sample.bean.Idel1;
import org.jingle.util.dydelegation.sample.bean.Idel2;
import org.jingle.util.dydelegation.sample.bean.MyDate;
public class MyDateTest {
public static void main(String[] args) {
MyDate inst = new MyDate();
DelegationInvocationHandler handler =
new DummyInvocationHandler();
Object delegation =
DelegationGenerator.newDelegationInstance(inst,
new Class[] { Idel1.class, Idel2.class },
null, handler);
System.out.println(delegation instanceof Idel1);
System.out.println(delegation instanceof Idel2);
System.out.println(delegation instanceof Date);
}
}
Output:
true
true
false
MyDate extends Date and implements the Idel1 and Idel2
interfaces. DelegationGenerator.newDelegationInstance() uses a MyDate instance as
the object instance to be delegated, and limits the delegation scope in Idel1 and
Idel2. In other words, the generated delegation object is an instance of Idel1
and Idel2, but not an instance of Date.
The Dunamis project introduces Dynamic Delegation to extend the function of the Java
Proxy reflection utility. It can generate delegation for both classes
and interfaces at runtime. This article introduces Dynamic Delegation in brief with
simple examples. In the real world, Dynamic Delegation can be used in many areas,
such as mock objects in unit testing, Java GUI MVC framework, and more.
Lu Jian is a senior Java architect/developer with four years of Java development experience.
Return to ONJava.com
Showing messages 1 through 2 of 2.
AO formalizes a lot of the benefits of Dynamic Delegations, and does even more