JavaダイナミックエージェントとCGLib


Javaダイナミックエージェントメカニズムは、強力なコンパイル時にコードを生成するメカニズムです.
たとえば以下の例では,コンパイル後にHelloImplのエージェントクラスを生成する.エージェントに要求される方法は、例のHelloのような言い訳から来なければならない.

package org.mark.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TestDynamicProxy {
public static interface Hello {
public void sayHello();
}

public static class HelloImpl implements Hello {

@Override
public void sayHello() {
// TODO Auto-generated method stub
System.out.println("say hello");
}

}

public static class ProxyTest implements InvocationHandler {
Object originalObj;

Object bind(Object originalObj) {
this.originalObj = originalObj;

return Proxy.newProxyInstance(originalObj.getClass().getClassLoader(), originalObj.getClass().getInterfaces(), this);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("DynamicProxy invocated!");
return method.invoke(originalObj, args);
}

}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Hello hello = (Hello) new ProxyTest().bind(new HelloImpl());
hello.sayHello();
}

}

それでは問題が来て、掘削機の技術はどの家が強いですか?
一般的なクラスといえば、インタフェースを実装して得られない方法がありますが、動的エージェントはどうすればいいのでしょうか.まずJavaのJDKに動的エージェントを内蔵することはできません.エージェントの方法は言い訳から来なければならないので、CGLibでこのようなエージェントの動作をすることができます.CGLIBは簡単で使いやすく、JDKのProxyダイナミックエージェントよりもはるかに高速に動作します.
以下の例のプログラム

package org.mark.proxy;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class TestCGLib {
public static class InfoManager {
public void create() {
System.out.println("Create a record");
}
}

public static class InfoManagerFactory {
public static InfoManager getInstance(CGLibProxy proxy) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(InfoManager.class);
enhancer.setCallback(proxy);
return (InfoManager)enhancer.create();
}
}

public static class CGLibProxy implements MethodInterceptor {
private String name;

public CGLibProxy(String name) {
this.name = name;
}

@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
if(!name.equals("Test")) {
System.out.println("Name is not Test, cglib ignored");
return null;
}
System.out.println("cglib proxy called");
return arg3.invokeSuper(arg0, arg2);
}

}

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
InfoManager manager = InfoManagerFactory.getInstance(new CGLibProxy("Test"));
manager.create();

InfoManager manager2 = InfoManagerFactory.getInstance(new CGLibProxy("Test2"));
manager2.create();
}

}