CGLIB
来源:互联网 发布:搜狗五笔for mac下载 编辑:程序博客网 时间:2024/05/23 15:24
原理
CGLIB原理:动态生成一个要代理类的子类,子类重写代理类的所有不是final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入模切逻辑。它比使用java反射的JDK动态代理要快。
CGLIB底层:使用字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因数它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。
CGLIB的API
1.jar包
cglib-nodep.jar:不需要关联asm的jar包,jar包内部包含了asm的类。
cglib.jar:需要关联asm的jar包。
2.CGLIB类库
由于基本代码很少,学起来有一定的困难,主要是缺少文档和示例,这也是CGLIB的一个不足之处。
net.sf.cglib.core:底层字节码处理类,他们大部分与ASM有关系 。
net.sf.cglib.transform:编译期或运行期类和类文件的转换。
net.sf.cglib.proxy:实现创建代理和方法拦截器类。
net.sf.cglib.reflect:实现快速反射和C#风格代理的类
net.sf.cglib.util:集合排序等工具类
net.sf.cglibbeans:JavaBean相关的工具类。
下面介绍使用MethodInterceptor和Enhance实现一个动态代理。
一 JDK中的动态代理
JDK中的动态代理是通过反射类Proxy以及InvocationHandler回调接口实现的,但是,JDK中所要进行动态代理的类必须要实现一个接口,也就是说只能对该类所实现接口中定义的方法进行代理,这在实际编程中具有一定的局限性,而且使用反射的效率也并不是很高。
二 使用CGLIB实现
(1)被代理类
package com.zghw.cglib; /** * 没有实现接口,需要CGlib动态代理的目标类 * * @author zghw * */ public class TargetObject { public String method1(String paramName) { return paramName; } public int method2(int count) { return count; } public int method3(int count) { return count; } @Override public String toString() { return "TargetObject []"+ getClass(); } }
(2)拦截器
在调用目标方法时,CGLIB会回调MethodInterceptor接口方法拦截,来实现你自己的代理逻辑,类似于JDK中的InvocationHandler接口。
package com.zghw.cglib; import java.lang.reflect.Method; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /** * 目标对象拦截器,实现MethodInterceptor * @author zghw * */ public class TargetInterceptor implements MethodInterceptor{ /** * 重写方法拦截在方法前和方法后加入业务 * Object obj为目标对象 * Method method为目标方法 * Object[] params 为参数, * MethodProxy proxy CGlib方法代理对象 */ @Override public Object intercept(Object obj, Method method, Object[] params, MethodProxy proxy) throws Throwable { System.out.println("调用前"); Object result = proxy.invokeSuper(obj, params); System.out.println(" 调用后"+result); return result; } }
package com.zghw.cglib; import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.CallbackFilter; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.NoOp; public class TestCglib { public static void main(String args[]) { Enhancer enhancer =new Enhancer(); enhancer.setSuperclass(TargetObject.class); enhancer.setCallback(new TargetInterceptor()); TargetObject targetObject2=(TargetObject)enhancer.create(); System.out.println(targetObject2); System.out.println(targetObject2.method1("mmm1")); System.out.println(targetObject2.method2(100)); System.out.println(targetObject2.method3(200)); } }
这里Enhance类是CGLib中的一个这节码增强器,它可以方便的对你想要处理的类进行扩展,以后会经常看到它。
首先将被代理类TargetObject设置成父类,然后设置拦截器TargetInterceptor,最后执行enhance.create()动态生成一个代理类,并从Object强制转型成父类型 TargetObject。最后,在代理类上调用方法。
(4)回调过滤器
在CGLIB回调时可以设置对不同方法执行不同的回调逻辑,或者根本不执行回调。
package com.zghw.cglib; import java.lang.reflect.Method; import net.sf.cglib.proxy.CallbackFilter; /** * 回调方法过滤 * @author zghw * */ public class TargetMethodCallbackFilter implements CallbackFilter { /** * 过滤方法 * 返回的值为数字,代表了Callback数组中的索引位置,要到用的Callback */ @Override public int accept(Method method) { if(method.getName().equals("method1")){ System.out.println("filter method1 ==0"); return 0; } if(method.getName().equals("method2")){ System.out.println("filter method2 ==1"); return 1; } if(method.getName().equals("method3")){ System.out.println("filter method3 ==2"); return 2; } return 0; } }
package com.zghw.cglib; import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.CallbackFilter; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.NoOp; public class TestCglib { public static void main(String args[]) { Enhancer enhancer =new Enhancer(); enhancer.setSuperclass(TargetObject.class); CallbackFilter callbackFilter = new TargetMethodCallbackFilter(); /** * (1)callback1:方法拦截器 (2)NoOp.INSTANCE:这个NoOp表示no operator,即什么操作也不做,代理类直接调用被代理的方法不进行拦截。 (3)FixedValue:表示锁定方法返回值,无论被代理类的方法返回什么值,回调方法都返回固定值。 */ Callback noopCb=NoOp.INSTANCE; Callback callback1=new TargetInterceptor(); Callback fixedValue=new TargetResultFixed(); Callback[] cbarray=new Callback[]{callback1,noopCb,fixedValue}; //enhancer.setCallback(new TargetInterceptor()); enhancer.setCallbacks(cbarray); enhancer.setCallbackFilter(callbackFilter); TargetObject targetObject2=(TargetObject)enhancer.create(); System.out.println(targetObject2); System.out.println(targetObject2.method1("mmm1")); System.out.println(targetObject2.method2(100)); System.out.println(targetObject2.method3(100)); System.out.println(targetObject2.method3(200)); } }
package com.zghw.cglib; import net.sf.cglib.proxy.FixedValue; /** * 表示锁定方法返回值,无论被代理类的方法返回什么值,回调方法都返回固定值。 * @author zghw * */ public class TargetResultFixed implements FixedValue{ /** * 该类实现FixedValue接口,同时锁定回调值为999 * (整型,CallbackFilter中定义的使用FixedValue型回调的方法为getConcreteMethodFixedValue,该方法返回值为整型)。 */ @Override public Object loadObject() throws Exception { System.out.println("锁定结果"); Object obj = 999; return obj; } }
(5)延迟加载对象
LazyLoader接口继承了Callback,因此也算是CGLib中的一种Callback类型。另一种延迟加载接Dispatcher,Dispatcher同样继承于Callback,也是一种回调类型。不同的是:LazyLoader只在第一次访问延迟加载属性里触发代理类回调方法,而Dispatcher在每次访问加载属性时都会触发代理类回调方法。
package com.zghw.cglib; import net.sf.cglib.proxy.Enhancer; public class LazyBean { private String name; private int age; private PropertyBean propertyBean; private PropertyBean propertyBeanDispatcher; public LazyBean(String name, int age) { System.out.println("lazy bean init"); this.name = name; this.age = age; this.propertyBean = createPropertyBean(); this.propertyBeanDispatcher = createPropertyBeanDispatcher(); } /** * 只第一次懒加载 * @return */ private PropertyBean createPropertyBean() { /** * 使用cglib进行懒加载 对需要延迟加载的对象添加代理,在获取该对象属性时先通过代理类回调方法进行对象初始化。 * 在不需要加载该对象时,只要不去获取该对象内属性,该对象就不会被初始化了(在CGLib的实现中只要去访问该对象内属性的getter方法, * 就会自动触发代理类回调)。 */ Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(PropertyBean.class); PropertyBean pb = (PropertyBean) enhancer.create(PropertyBean.class, new ConcreteClassLazyLoader()); return pb; } /** * 每次都懒加载 * @return */ private PropertyBean createPropertyBeanDispatcher() { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(PropertyBean.class); PropertyBean pb = (PropertyBean) enhancer.create(PropertyBean.class, new ConcreteClassDispatcher()); return pb; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public PropertyBean getPropertyBean() { return propertyBean; } public void setPropertyBean(PropertyBean propertyBean) { this.propertyBean = propertyBean; } public PropertyBean getPropertyBeanDispatcher() { return propertyBeanDispatcher; } public void setPropertyBeanDispatcher(PropertyBean propertyBeanDispatcher) { this.propertyBeanDispatcher = propertyBeanDispatcher; } @Override public String toString() { return "LazyBean [name=" + name + ", age=" + age + ", propertyBean=" + propertyBean + "]"; } }
package com.zghw.cglib; public class PropertyBean { private String key; private Object value; public String getKey() { return key; } public void setKey(String key) { this.key = key; } public Object getValue() { return value; } public void setValue(Object value) { this.value = value; } @Override public String toString() { return "PropertyBean [key=" + key + ", value=" + value + "]" +getClass(); } }
package com.zghw.cglib; import net.sf.cglib.proxy.LazyLoader; public class ConcreteClassLazyLoader implements LazyLoader { /** * 对需要延迟加载的对象添加代理,在获取该对象属性时先通过代理类回调方法进行对象初始化。 * 在不需要加载该对象时,只要不去获取该对象内属性,该对象就不会被初始化了(在CGLib的实现中只要去访问该对象内属性的getter方法, * 就会自动触发代理类回调)。 */ @Override public Object loadObject() throws Exception { System.out.println("before lazyLoader..."); PropertyBean propertyBean = new PropertyBean(); propertyBean.setKey("zghw"); propertyBean.setValue(new TargetObject()); System.out.println("after lazyLoader..."); return propertyBean; } }
package com.zghw.cglib; import net.sf.cglib.proxy.Dispatcher; public class ConcreteClassDispatcher implements Dispatcher{ @Override public Object loadObject() throws Exception { System.out.println("before Dispatcher..."); PropertyBean propertyBean = new PropertyBean(); propertyBean.setKey("xxx"); propertyBean.setValue(new TargetObject()); System.out.println("after Dispatcher..."); return propertyBean; } }
会动态生成一个接口,该接口包含指定类定义的所有方法。
package com.zghw.cglib; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.InterfaceMaker; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class TestInterfaceMaker { public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { InterfaceMaker interfaceMaker =new InterfaceMaker(); //抽取某个类的方法生成接口方法 interfaceMaker.add(TargetObject.class); Class<?> targetInterface=interfaceMaker.create(); for(Method method : targetInterface.getMethods()){ System.out.println(method.getName()); } //接口代理并设置代理接口方法拦截 Object object = Enhancer.create(Object.class, new Class[]{targetInterface}, new MethodInterceptor(){ @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { if(method.getName().equals("method1")){ System.out.println("filter method1 "); return "mmmmmmmmm"; } if(method.getName().equals("method2")){ System.out.println("filter method2 "); return 1111111; } if(method.getName().equals("method3")){ System.out.println("filter method3 "); return 3333; } return "default"; }}); Method targetMethod1=object.getClass().getMethod("method3",new Class[]{int.class}); int i=(int)targetMethod1.invoke(object, new Object[]{33}); Method targetMethod=object.getClass().getMethod("method1",new Class[]{String.class}); System.out.println(targetMethod.invoke(object, new Object[]{"sdfs"})); } }
阅读全文
0 0
- cglib
- cglib
- cglib
- CGLIB
- cglib
- CGlib
- cglib
- cglib
- CGLIB
- cglib
- cglib
- CGLIB
- cglib 指南
- CGLIB模式
- CGLIB简介
- Java CGLIB
- CGlib 基础
- 深入浅出CGlib
- 入门到放弃node系列之微信公众号开发实战一(Express篇)
- Target Sum
- vuex新手教程(完整版整理)
- Oracle 设置表空间自增长
- 详解nohup和& 区别
- CGLIB
- 防火墙
- 在Centos 7 上 搭建 K8S --坑b)
- 阿里云https配置
- 用pandas按列合并两个文件
- mysql(三):mysql查询语句 和 多表关联查询 以及 子查询
- 数据分析
- 7.0权限处理
- 记录PHP编码规范