ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Dynamic Delegation and Its Applications
Pages: 1, 2, 3

Exercise 1. Create a Delegation Class for a Concrete Class

Suppose there is a concrete class named ConcreteClass:


//ConcreteClass.java
package org.jingle.util.dydelegation.sample;

public class ConcreteClass {
    public void hello() {
        System.out.println("Hello from ConcreteClass");
    }
    
    protected void hello2() {
        System.out.println("Hello again from ConcreteClass");
    }
}

The following code generates a delegation class for ConcreteClass.


//ConcreteClassTest.java
package org.jingle.util.dydelegation.sample;

import org.jingle.util.dydelegation.DelegationGenerator;

public class ConcreteClassTest {
    public static void main(String[] args) {
        Class clazz = DelegationGenerator
                .getDelegationClass(new Class[] { ConcreteClass.class });
        System.out.println("Delegation class name = " +
                            clazz.getName());
        System.out.println(
            ConcreteClass.class.isAssignableFrom(clazz));
    }
}

The output shows:


Delegation class name =
org.jingle.util.dydelegation.sample.ConcreteClass_Delegation_0
true

DelegationGenerator.getDelegationClass() accepts a class array as parameter and return a Java Class that extends/implements the given class/interfaces. By default, the generated delegation class is in the same package as the class to be delegated.

The delegation class can be instantiated as below:


//object to be delegated
Object obj = ...; 
//some concrete invocation handler instance
DelegationInvocationHandler h = ...; 

Constructor c = clazz.getConstructor(new Class[] { Object.class });
Object inst = c.newInstance(new Object[] {obj});
((Delegation) inst)._setInvocationHandler(h);

Exercise 2. Create a Delegation Class for an Abstract Class

DelegationGenerator can also generate a concrete delegation class for an abstract class.


//AbstractClass.java
package org.jingle.util.dydelegation.sample;

public abstract class AbstractClass {
    public abstract void wave();
}


//AbstractClassTest.java
package org.jingle.util.dydelegation.sample;

import java.lang.reflect.Modifier;

import org.jingle.util.dydelegation.DelegationGenerator;

public class AbstractClassTest {
    public static void main(String[] args) {
        Class clazz = DelegationGenerator
                .getDelegationClass(new Class[] { AbstractClass.class });
        System.out.println("Delegation class name = " +
            clazz.getName());
        System.out.println(
            Modifier.isAbstract(clazz.getModifiers()));
    }
}

Output:


Delegation class name = 
org.jingle.util.dydelegation.sample.AbstractClass_Delegation_0
false

The generated delegation class is a concrete class instead of an abstract class.

Exercise 3. Create a Delegation Class for Both a Class and Multiple Interfaces

DelegationGenerator.getDelegationClass() can accept a class and multiple interfaces simultaneously to generate a delegation class to delegate the given class and interfaces. Duplicate interfaces will be eliminated.


//Idel1.java
package org.jingle.util.dydelegation.sample.bean;

public interface Idel1 {
    public void idel1();
}


//Idel2.java
package org.jingle.util.dydelegation.sample.bean;

public interface Idel2 {
    public void idel2();
}


//ComplexClassTest.java
package org.jingle.util.dydelegation.sample;

import org.jingle.util.dydelegation.DelegationGenerator;
import org.jingle.util.dydelegation.sample.bean.Idel1;
import org.jingle.util.dydelegation.sample.bean.Idel2;

public class ComplexClassTest {
    public static void main(String[] args) {
        Class clazz = DelegationGenerator.getDelegationClass(new Class[] {
                ConcreteClass.class, Idel1.class, Idel2.class });
        System.out.println(
            Idel1.class.isAssignableFrom(clazz));
        System.out.println(
            Idel2.class.isAssignableFrom(clazz));
        System.out.println(
            ConcreteClass.class.isAssignableFrom(clazz));
    }
}

Output:


true
true
true

The generated delegation class extends the given class ConcreteClass and implements all of the given interfaces: Idel1 and Idel2.

Exercise 4. Create a Delegation Object for a Specific Object

DelegationGenerator can generate a delegation object directly, according to a specific object to be delegated.


// ConcreteClassTest2.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;

public class ConcreteClassTest2 {
    public static void main(String[] args) {
        ConcreteClass inst = new ConcreteClass();
        DelegationInvocationHandler handler =
            new SimpleHandler();
        ConcreteClass delegation = (ConcreteClass)
            DelegationGenerator.newDelegationInstance(inst, handler);
        delegation.hello();
        delegation.hello2();
        System.out.println(delegation.toString());
    }
}

class SimpleHandler extends DummyInvocationHandler {
    public boolean invokeBefore(Object bean,
                                Method method, Object[] args)
            throws Throwable {
        System.out.println("Interrupted by SimpleHandler");
        return super.invokeBefore(bean, method, args);
    }
}

Output:


Interrupted by SimpleHandler
Hello from ConcreteClass
Hello again from ConcreteClass
Interrupted by SimpleHandler
org.jingle.util.dydelegation.sample.ConcreteClass@ef5502

DummyInvocationHandler is a dummy implementation of DelegationInvocationHandler. It always returns true in invokeBefore(), returns the input result directly in invokeAfter(), and throws the input throwable directly in invokeAfterException(). The delegation object with DummyInvocationHandler has same behavior as the object to be delegated.

DelegationGenerator.newDelegationInstance() accepts an object and an DelegationInvocationHandler instance as parameters. It returns a delegation object to delegate the given object.

All of the methods called on the delegation object will be delegated to the DelegationInvocationHandler instance, except:

  • Methods without a public modifier.
  • Methods with a final modifier.
  • Methods with a static modifier.
  • Methods declared in the Object class, other than hashCode(), equals(), and toString().

Pages: 1, 2, 3

Next Pagearrow