Javassist
package aop; import java.util.*; import java.lang.reflect.*; import javassist.*; public class TestJavassist { public static void main(String[] args) throws Exception { ClassLoader usingClassLoader = Thread.currentThread().getContextClassLoader(); // System.out.println( usingClassLoader ); ClassPool pool = new ClassPool(true); CtClass ctSuper = pool.get("java.util.ArrayList"); CtClass ctProxy = pool.makeClass("$$AopProxy$$",ctSuper); Method add = java.util.ArrayList.class.getMethod("add", new Class[]{Object.class}); CtMethod ctAdd = CtNewMethod.make( add.getModifiers() , toCtClass(pool,add.getReturnType()) , add.getName() , toCtClassArray(pool,add.getParameterTypes()) , toCtClassArray(pool,add.getExceptionTypes()) , "{ System.out.println(\"[BEFORE]\\n\" + aop.TestJavassist#dumpParams($args) ); return ($r)super.add($$); }" , ctProxy ); ctProxy.addMethod(ctAdd); Class proxyType = ctProxy.toClass( usingClassLoader ); pool = null; ArrayList list = (ArrayList)proxyType.newInstance(); list.add("aaa"); } //////////////////////////////////////////////////////// public static CtClass toCtClass(ClassPool pool, Class src) throws NotFoundException { return pool.get(toString(src)); } public static CtClass[] toCtClassArray(ClassPool pool, Class[] src) throws NotFoundException { String[] srcs = new String[src.length]; for(int i=0, len=src.length; i<len; ++i) srcs[i] = toString(src[i]); return pool.get(srcs); } public static String toString(Class type) { return type.isArray() ? toString( type.getComponentType() ) + "[]" : type.getName(); } public static String dumpParams(Object[] params) { if( params == null || params.length == 0 ) return ""; StringBuffer b = new StringBuffer(1024); for(int i=0, len=params.length; i<len; ++i) { b.append("[").append(i).append("]type='"); if( params[i] == null ) b.append("', value='null'\n"); else b.append( toString(params[i].getClass()) ).append("', value='").append( params[i] ).append("'"); } return b.toString(); } }
実行結果
[BEFORE] [0]type='java.lang.String', value='aaa'
aopalliance のMethodInterceptorやMethodInvocationインターフェースを突っ込めるようにするには、Javassistの用意している変数だけではむりっぽそうだ。少々面倒な文字列操作が必要か。