Dynamic Delegation and Its Applications
Pages: 1, 2, 3
Exercise 5. Create Delegation Object for the Object of a Java Core Class
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.
Advanced Usage
Exercise 6. Simulate Proxy Behavior
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:
- The
Objectto be delegated.This can be
null. If it is notnull, it must be an instance of all of the given classes and interfaces. - An array of
Classto be delegated.This can contain multiple interfaces and, at most, one class.
- Delegation class name.
If
null, a system-generated name will be provided. - A
DelegationInvocationHandlerinstance, 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.
Exercise 7. Partial Delegation
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.
Conclusion
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.
Reference
- Dunamis project: dunamis.dev.java.net
- Download sample code for this article: sample code
- BCEL: jakarta.apache.org/bcel/index.html
Lu Jian is a senior Java architect/developer with four years of Java development experience.
Return to ONJava.com
-
Järjestää puhekuntoutusta
2004-11-22 12:46:58 DrHoliday [View]
- Trackback from http://sbserve/DotText/simon/archive/2004/11/19/3173.aspx
Dynamic Delegation and Its Applications
2004-11-18 19:25:55 [View]
-
AO formalizes a lot of the benefits of Dynamic Delegations, and does even more
2004-11-18 03:51:38 Russell Miles |
[View]