Skip to content

mdre/EasyProxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

EasyProxy

EasyProxy is a Java method proxy that mimic the behavior of CGLib. It creates a new instance of an Object that have all the methods redirected to the same interceptor. This is achieved by creating a subclass of the base class where all the methods are overridden and redirected. Final Methods and Syntetic Methods are ignored.

To intecept the calls, you need to provide an object that implements the interface IEasyProxyInteceptor. This object will receive all the calls to the instance.

The interface define the method intecept that receives all the calls to the instance and here you can decide what to do with it. As a parameter it receives the reference to the original method call in the superMethod reference. You can invoke it when you want.

You can also define extra methods, add it to the subclass and process it in the interceptor. To do this you must define an interface and pass it as a parameter with the target class. All the methods in the interface will be implemented in the subclass and redirected to the interceptor. The superMethod will be null in this case.

Here is an example:

Suppose you hava a base class like this:

public class ASMFoo {

    String name;
    
    public ASMFoo() {
    }

    public void setName(String name) {
        this.name = name;
    }

    public void sayHello() {
        System.out.println("Hello "+this.name);
    }
}

To intercept all the calls, you must implement the IEasyProxy interface in a class and pass it as a parameter to the new instance.

public class ObjectProxyImpl implements  IEasyProxyInterceptor {

    @Override
    public Object intercept(Object target, Method method, Method superMethod, Object... args) throws Throwable {
        System.out.println("Intercepted: "+method.toString());
        System.out.println("superMethod: "+superMethod);
        System.out.println("anotations: "+Arrays.toString(method.getAnnotations()));
        
        Object result = null;
        switch(method.getName()) {
            case "setName":
                args[0] = "*" + args[0] + "*";
                result = superMethod.invoke(target, args);
                break;
            
            default:
                result = superMethod.invoke(target, args);
                
        }
        return result;
    }
}

To create a intercepted proxy class just do the following:

EasyProxy ep = new EasyProxy();
ObjectProxyImpl op = new ObjectProxyImpl();
Class<ASMFoo> ft = (Class<ASMFoo>)ep.getProxyClass(ASMFoo.class, IObjectProxy.class);
System.out.println("class generated!!");
System.out.println("");
System.out.println("");
System.out.println("creating a new instance ...");
ASMFoo  fti = ft.getConstructor(IEasyProxyInterceptor.class).newInstance(op);

Now the instance has all the methods redirection, but you can use it as a normal object.

fti.setName("Bart");
fti.sayHello("");

and the output is:

Hello *Bart* 

It is also possible to add methods to the subclass and implement it in the inteceptor. Just define an interface and pass it to the getProxyClass.

public interface IObjectProxy { 
    public String ___getLast();
}
public class ObjectProxyImpl implements IObjetProxy,  IEasyProxyInterceptor {

    String lastMethod = "";

    @Override
    public Object intercept(Object target, Method method, Method superMethod, Object... args) throws Throwable {
        System.out.println("Intercepted: "+method.toString());
        System.out.println("superMethod: "+superMethod);
        System.out.println("anotations: "+Arrays.toString(method.getAnnotations()));
        
        lastMethod = method.getName();

        Object result = null;
        switch(method.getName()) {
            case "setName":
                args[0] = "*" + args[0] + "*";
                result = superMethod.invoke(target, args);
                break;
                
            case "___getLast":
                result = this.___getLast();
                break;

            default:
                result = superMethod.invoke(target, args);
                
        }
        return result;
    }

    @Override
    public String ___getLast() {
        return this.lastMethod;
    }
}

Now when you create an instance you can do this:

Class<ASMFoo> ft = (Class<ASMFoo>)ep.getProxyClass(ASMFoo.class, IObjectProxy.class);
ASMFoo  foo = ft.getConstructor(IEasyProxyInterceptor.class).newInstance(op);

foo.setName("Bart");
System.out.println(((IObjectProxy)foo).___getLast());

and the output is:

setName

About

A Java proxy method handler.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages