Click here to Skip to main content
Click here to Skip to main content

Alternate Proxy class with bytecode manipulation

, 20 May 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
This article provides alternative to Java's Proxy class with bytecode manipulation.

Introduction 

A proxy forces object method calls to occur indirectly through the proxy object, which acts as a surrogate or delegate for the underlying object being proxied. Proxy objects are usually declared so that the client objects have no indication that they have a proxy object instance.

java.lang.reflect.Proxy class has a few drawbacks:

  1. It uses reflection extensively.
  2. Code written to handle methods is not clean.

The invoke method becomes ugly at times.

Using the code  

Proxy.newProxyInstance(Class clazz, Map<Class, Object> interfaceMap, Object... args)

clazz - Proxy base class  

interfaceMap - key is interface class and value is 

  • either object implementing the interface 
  • or concrete class (not abstract) implementing the respective interface and having public zero argument constructor 
args - Arguments passed to constructor to create instance of proxy class (same give in clazz parameter)

Base class is just a simple class (with at least one non private constructor). If signature of method is same as one of the interfaces then that function will be called instead of the one provided in actual implementation (i.e. value in interfaceMap). 

You can also make Base class abstract implementing the interfaces and defining only selective methods.

Example,

public /*abstract*/ class Base /*implements Runnable, Callable, Comparable*/  {
 
    //method from Callable
    public Object call() throws Exception {
        System.out.println("Call start");
        Object o = (Proxy.<Callable> getInnerObject(this, Callable.class))
                .call();
        System.out.println("Call end");
        return o;
    }
 
    //method from Comparable
    public int compareTo(Object o) {
        System.out.println("compareTo called with argument - " + o);
        return 0;
    }
}

The above compareTo will be called instead implementation passed in interfaceMap

interfaceMap.put(Comparable.class, new Comparable(){
    @Override
    public int compareTo(Object o) {
        System.out.println("This will not be called as inner object is not accessed from base class.");
        return 0;
    }
});
 
interfaceMap.put(Runnable.class, MyRunnable.class);
interfaceMap.put(Callable.class, MyCallable.class);
Runnable runnable = (Runnable)Proxy.newProxyInstance(Base.class, interfaceMap);
Thread thread = new Thread(runnable);
thread.start(); 

You can access the actual implementation object (i.e. value in interfaceMap) by using something like:

Callable callable = Proxy.<Callable> getInnerObject(this, Callable.class); 

Where this is the instance of base class and Callable.class is the key passed in interfaceMap. 

If you want that nobody else should be able to access you inner objects directly (i.e. by using Proxy.<Callable> getInnerObject) you can use an overloaded method of newProxyInstance which restricts of calling this function of any other class other than Base class.  

Bytecode manipulation is used only first time newProxyInstance is called. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

abhinav_soni

India India
No Biography provided

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.1411023.1 | Last Updated 20 May 2012
Article Copyright 2012 by abhinav_soni
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid