动态代理、CGLIB 与 切面编程
跳到导航
跳到搜索
关于代理
代理,简单说就是:不直接操作对象,而使用代理对象来完成操作;
- 通过代理对象,可以对原对象进行方法扩展;
代理又可以分为
- 静态代理:通过聚合、继承的方式生成代理对象;
- 代理关系在编译时就确定了
- 动态代理:
- 运行期动态生成代理对象;
- Java动态代理:(针对实现了接口的类)
- CGLIB:(针对没有实现接口的类)
- AspectJ:(springframework的aop基于此实现)
Java动态代理
AspectJ
- 参见:Spring:AOP
CGLIB
CGLIB是一个功能强大,高性能的代码生成包。
- 使用CGLib实现动态代理,完全不受代理类必须实现接口的限制;
- CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。
原理
- 动态生成一个要代理类的子类,子类重写要代理的类的所有不是final的方法。
- 在子类中采用方法拦截的技术,拦截所有父类方法的调用,并织入横切逻辑。
- 为没有实现接口的类提供代理,比于JDK动态代理(只能代理接口)更加强大;
- 不能代理final方法;
CGLIB组成结构
CGLIB底层使用了ASM(一个短小精悍的字节码操作框架)来操作字节码生成新的类。
- 因为使用字节码技术生成代理类,所以CGLIB比java反射的JDK动态代理更快;
- 关于“ASM”:
- 除了CGLIB库外,脚本语言(如:“Groovy”、“BeanShell”)也使用ASM生成字节码;
- ASM使用类似SAX的解析器来实现高性能;
- (如果直接使用ASM,需要对Java字节码非常了解)
jar包
- “cglib-nodep-2.2.jar”:使用nodep包不需要关联asm的jar包,jar包内部包含asm的类.
- “cglib-2.2.jar”:使用此jar包需要关联asm的jar包,否则运行时报错.
类库
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.cglib.beans”:JavaBean相关的工具类;
常用的API
命令 | 说明 | 示例 |
---|---|---|
使用
-
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(); } }