标签:
本文的例子全部来自github上cglib的官方文档,有关cglib的教程少之又少,如果想学习觉得还是看看诸如Hibernate和Spring的源码来的实在。
package com.tang; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotSame; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import net.sf.cglib.beans.BeanCopier; import net.sf.cglib.beans.BeanGenerator; import net.sf.cglib.beans.BeanMap; import net.sf.cglib.beans.BulkBean; import net.sf.cglib.beans.ImmutableBean; import net.sf.cglib.core.KeyFactory; import net.sf.cglib.core.Signature; import net.sf.cglib.proxy.CallbackHelper; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.FixedValue; import net.sf.cglib.proxy.InterfaceMaker; import net.sf.cglib.proxy.InvocationHandler; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import net.sf.cglib.proxy.Mixin; import net.sf.cglib.proxy.NoOp; import net.sf.cglib.reflect.ConstructorDelegate; import net.sf.cglib.reflect.FastClass; import net.sf.cglib.reflect.FastMethod; import net.sf.cglib.reflect.MethodDelegate; import net.sf.cglib.reflect.MulticastDelegate; import net.sf.cglib.util.ParallelSorter; import net.sf.cglib.util.StringSwitcher; import org.junit.Test; import org.objectweb.asm.Type; import com.pojo.BeanDelegate; import com.pojo.Class1; import com.pojo.Class2; import com.pojo.DelegatationProvider; import com.pojo.Interface1; import com.pojo.Interface2; import com.pojo.MixinInterface; import com.pojo.OtherSampleClass; import com.pojo.SampleBeanConstructorDelegate; import com.pojo.SampleClass; import com.pojo.SimpleMulticastBean; /** * 字节码增强类 * * @author Administrator * */ public class Cglib { /** * 将一个方法的返回值设置为固定的值 使用FixedValue,SimpleClass类的所有方法包括父类的 方法都试图返回"Hello cglib" */ @Test public void testFixedValue() { Enhancer e = new Enhancer(); e.setSuperclass(SampleClass.class); e.setCallback(new FixedValue() { @Override public Object loadObject() throws Exception { return "Hello cglib"; } }); SampleClass proxy = (SampleClass) e.create(); assertEquals("Hello cglib", proxy.test(null)); assertEquals("Hello cglib", proxy.toString()); // 调用hashCode方法将返回ClassCastException try { proxy.hashCode(); } catch (Exception e1) { assertEquals(e1.getClass(), ClassCastException.class); } // getClass方法为final修饰的,cglib不会对final的方法修饰。 proxy.getClass(); } /* * 测试InvocationHandler */ @Test public void testInvocationHandler() { Enhancer e = new Enhancer(); e.setSuperclass(SampleClass.class); e.setCallback(new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 对非Object类并且方法的返回值是String类型的方法增强 if (method.getDeclaringClass() != Object.class && method.getReturnType() == String.class) { return "Hello cglib!"; } else { // 其他方法抛异常 throw new RuntimeException("Do not know what to do."); // 如果写成下面这种调用本类中的其他方法,则会出现死循环。后面的方法能够解决这个问题 /* * System.out.println("else"); return method.invoke(proxy, * args); */ } } }); SampleClass proxy = (SampleClass) e.create(); assertEquals("Hello cglib!", proxy.test(null)); try { proxy.hashCode(); } catch (Exception e1) { assertEquals(e1.getMessage(), "Do not know what to do."); } } /** * 该方法比InvocationHandler更常用,因为InvocationHandler有死循环的危险 */ @Test public void testMethodInterceptor() { Enhancer e = new Enhancer(); e.setSuperclass(SampleClass.class); e.setCallback(new MethodInterceptor() { // 相比invoke方法多出一个MethodProxy,为被代理类原方法的一个包装,有时候因为性能问题我们需要调用原类中的方法 @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // 对非Object类并且方法的返回值是String类型的方法增强 if (method.getDeclaringClass() != Object.class && method.getReturnType() == String.class) { return "Hello cglib!"; } else { // 调用原方法 return proxy.invokeSuper(obj, args); } } }); SampleClass proxy = (SampleClass) e.create(); assertEquals("Hello cglib!", proxy.test(null)); assertEquals(1, proxy.random()); } /** * callback的回调可以指定多个,既然有多个回调,那么需要指定一个策略来决定本次 调用要回调哪个 * 下面这个例子类似上面testMethodInterceptor方法。 */ @Test public void testCallbackFilter() { Enhancer e = new Enhancer(); CallbackHelper callbackHelper = new CallbackHelper(SampleClass.class, new Class[0]) { /** * 根据不同的情况返回不同的callback类 */ @Override protected Object getCallback(Method method) { if (method.getDeclaringClass() != Object.class && method.getReturnType() == String.class) { return new FixedValue() { @Override public Object loadObject() throws Exception { return "Hello cglib!"; } }; // 返回原类默认的方法实现 } else { return NoOp.INSTANCE; // A singleton provided by NoOp. } } }; e.setSuperclass(SampleClass.class); e.setCallbackFilter(callbackHelper); e.setCallbacks(callbackHelper.getCallbacks()); SampleClass proxy = (SampleClass) e.create(); assertEquals("Hello cglib!", proxy.test(null)); assertNotSame("Hello cglib!", proxy.random()); } /** * 创建不可变的bean */ @Test public void testImmutableBean() { SampleClass sample = new SampleClass(); sample.setValue("Hello world!"); SampleClass immutable = (SampleClass) ImmutableBean.create(sample); assertEquals("Hello world!", immutable.getValue()); sample.setValue("Hello world again!"); assertEquals("Hello world again!", sample.getValue()); immutable.setValue("!");// 报错,因为immutable是不可变的bean } /** * bean生成器,动态生成bean * * @throws NoSuchMethodException * @throws SecurityException */ @Test public void testBeanGenerator() throws Exception { BeanGenerator generator = new BeanGenerator(); generator.addProperty("value", String.class); Object bean = generator.create(); Method setter = bean.getClass().getMethod("setValue", String.class); setter.invoke(bean, "Hello world!"); Method getter = bean.getClass().getMethod("getValue"); assertEquals("Hello world!", getter.invoke(bean)); } /** * 属性拷贝器,如果两个类有相同的属性,则该拷贝器起作用 */ @Test public void testBeanCopier() { BeanCopier copier = BeanCopier.create(SampleClass.class, OtherSampleClass.class, false); SampleClass bean = new SampleClass(); bean.setValue("Hello cglib!"); OtherSampleClass otherBean = new OtherSampleClass(); copier.copy(bean, otherBean, null); assertEquals("Hello cglib!", otherBean.getValue()); } /** * bulkbean将一个bean中的get,set,返回值 分别看做一一对应的数组 */ @Test public void testBulkBean() { BulkBean bulkBean = BulkBean.create(SampleClass.class, new String[] { "getValue" }, new String[] { "setValue" }, new Class[] { String.class }); SampleClass bean = new SampleClass(); bean.setValue("Hello world!"); assertEquals(1, bulkBean.getPropertyValues(bean).length); assertEquals("Hello world!", bulkBean.getPropertyValues(bean)[0]); bulkBean.setPropertyValues(bean, new Object[] { "Hello cglib!" }); assertEquals("Hello cglib!", bean.getValue()); } /** * cglib中的最后一个工具类,将bean的所有属性转换成key-map的形式 */ @Test public void testBeanMap() { SampleClass bean = new SampleClass(); bean.setValue("Hello world!"); BeanMap map = BeanMap.create(bean); assertEquals("Hello world!", map.get("value")); } /** * keyfactory能够创建key的实例,key可以由不同的值组成,能够被map来使用 * 想要使用该功能需要定义一个接口,该接口必须有一个newInstance方法,且返回Object */ @Test public void testKeyFactory() { SampleKeyFactory keyFactory = (SampleKeyFactory) KeyFactory .create(SampleKeyFactory.class); // foo和42共同作为key Object key = keyFactory.newInstance("foo", 42); Map<Object, String> map = new HashMap<Object, String>(); map.put(key, "Hello cglib!"); assertEquals("Hello cglib!", map.get(keyFactory.newInstance("foo", 42))); } /** * Mixin可以对多个对象进行代理,需要同时指定多个接口和者多个接口对应的代理对象 */ @Test public void testMixin() { Mixin mixin = Mixin.create(new Class[] { Interface1.class, Interface2.class, MixinInterface.class }, new Object[] { new Class1(), new Class2() }); MixinInterface mixinDelegate = (MixinInterface) mixin; assertEquals("first", mixinDelegate.first()); assertEquals("second", mixinDelegate.second()); } /** * stringswitcher将在string和int之间建立一种映射,java 7已经内建的支持该 功能了。 * * @throws Exception */ @Test public void testStringSwitcher() throws Exception { String[] strings = new String[] { "one", "two" }; int[] values = new int[] { 10, 20 }; StringSwitcher stringSwitcher = StringSwitcher.create(strings, values, true); assertEquals(10, stringSwitcher.intValue("one")); assertEquals(20, stringSwitcher.intValue("two")); assertEquals(-1, stringSwitcher.intValue("three")); } /** * 运行时生成接口,依赖ASM */ @Test public void testInterfaceMaker() { Signature signature = new Signature("foo", Type.DOUBLE_TYPE, new Type[] { Type.INT_TYPE }); InterfaceMaker maker = new InterfaceMaker(); maker.add(signature, new Type[0]); Class iface = maker.create(); assertEquals(1, iface.getMethods().length); assertEquals("foo", iface.getMethods()[0].getName()); assertEquals(double.class, iface.getMethods()[0].getReturnType()); } /** * 方法代理 * * @throws Exception */ @Test public void testMethodDelegate() throws Exception { SampleClass bean = new SampleClass(); bean.setValue("Hello cglib!"); // 使用BeanDelegate代理sampleclass的getValue方法 BeanDelegate delegate = (BeanDelegate) MethodDelegate.create(bean, "getValue", BeanDelegate.class); assertEquals("Hello cglib!", delegate.getValue()); } /** * 可以代理多个对象 被代理的对象需要实现一个只有一个方法的对象。 * * @throws Exception */ @Test public void testMulticastDelegate() throws Exception { MulticastDelegate multicastDelegate = MulticastDelegate .create(DelegatationProvider.class); SimpleMulticastBean first = new SimpleMulticastBean(); SimpleMulticastBean second = new SimpleMulticastBean(); // 链式编程 multicastDelegate = multicastDelegate.add(first).add(second); DelegatationProvider provider = (DelegatationProvider) multicastDelegate; // 代理first和second provider.setValue("Hello world!"); assertEquals("Hello world!", first.getValue()); assertEquals("Hello world!", second.getValue()); } /** * 构造方法代理,需要有一个newInstance方法,并且该方法返回object的接口 * @throws Exception */ @Test public void testConstructorDelegate() throws Exception { SampleBeanConstructorDelegate constructorDelegate = (SampleBeanConstructorDelegate) ConstructorDelegate .create(SampleClass.class, SampleBeanConstructorDelegate.class); //通过接口的newInstance返回实例 SampleClass bean = (SampleClass) constructorDelegate.newInstance(); assertEquals(true, SampleClass.class.isAssignableFrom(bean.getClass())); } /** * 排序器,声称比jdk的默认排序器速度快 * @throws Exception */ @Test public void testParallelSorter() throws Exception { Integer[][] value = { {4, 3, 9, 0}, {2, 1, 6, 0} }; ParallelSorter.create(value).mergeSort(0); for(Integer[] row : value) { int former = -1; for(int val : row) { assertEquals(true, former < val); former = val; } } } /** * Fastclass声称比jdk原始的反射速度快,目前不推荐使用 * @throws Exception */ @Test public void testFastClass() throws Exception { FastClass fastClass = FastClass.create(SampleClass.class); FastMethod fastMethod = fastClass.getMethod(SampleClass.class.getMethod("getValue")); SampleClass myBean = new SampleClass(); myBean.setValue("Hello cglib!"); assertEquals("Hello cglib!", fastMethod.invoke(myBean, new Object[0])); } }cglib基于ASM做了一层封装使得开发变得简单,但是性能上肯定是比asm差一些的,asm的api全是基于字节码层面的,如果对jvm的字节码不熟悉很难去使用。
标签:
原文地址:http://blog.csdn.net/tangyongzhe/article/details/44888171