“动态代理、CGLIB 与 切面编程”的版本间差异
跳到导航
跳到搜索
(→CGLIB) |
(→常用的API) |
||
第59行: | 第59行: | ||
! 命令 !! 说明 !! 示例 | ! 命令 !! 说明 !! 示例 | ||
|- | |- | ||
| | | '''Enhancer''' | ||
| Enhancer创建一个被代理对象的子类并且拦截所有的方法调用(包括从Object中继承的toString和hashCode方法) | |||
* 作用类似Proxy类;但Enhancer既能够代理普通的class,也能够代理接口;(不能代理final方法) | |||
# Enhancer.setSuperclass():设置父类型; | |||
# Enhancer.create(Object…):创建增强对象; | |||
# Enhancer.createClass():创建字节码(.class); | |||
# setCallback():设置回调; | |||
#* “InvocationHandler”可以作为回调,但必须防止死循环 | |||
#*:(invoke中调用的任何原代理类方法,均会重新代理到invoke方法中) | |||
#* “MethodInterceptor”可以作为回调,且不会出现死循环 | |||
| | | | ||
<syntaxhighlight lang="java"> | <syntaxhighlight lang="java"> | ||
public class SampleClass { | |||
public void test(){ | |||
System.out.println("hello world"); | |||
} | |||
public static void main(String[] args) { | |||
Enhancer enhancer = new Enhancer(); | |||
enhancer.setSuperclass(SampleClass.class); | |||
enhancer.setCallback(new MethodInterceptor() { | |||
@Override | |||
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { | |||
System.out.println("before method run..."); | |||
Object result = proxy.invokeSuper(obj, args); | |||
System.out.println("after method run..."); | |||
return result; | |||
} | |||
}); | |||
SampleClass sample = (SampleClass) enhancer.create(); | |||
sample.test(); | |||
} | |||
} | |||
</syntaxhighlight> | |||
输出: | |||
<syntaxhighlight lang="xml"> | |||
before method run... | |||
hello world | |||
after method run... | |||
</syntaxhighlight> | </syntaxhighlight> | ||
|- | |- | ||
| | | | ||
第75行: | 第111行: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|- | |- | ||
| | |||
| | | | ||
第81行: | 第118行: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|- | |- | ||
| | | | ||
第91行: | 第127行: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|- | |- | ||
| | |||
| | | | ||
第97行: | 第134行: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|- | |- | ||
| | | | ||
第107行: | 第143行: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|- | |- | ||
| | |||
| | | | ||
第113行: | 第150行: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|- | |- | ||
| | | | ||
第123行: | 第159行: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|- | |- | ||
| | |||
| | | | ||
第129行: | 第166行: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|- | |- | ||
| | | | ||
第139行: | 第175行: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|- | |- | ||
| | |||
| | | | ||
第145行: | 第182行: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|- | |- | ||
| | | | ||
第155行: | 第191行: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|- | |- | ||
| | |||
| | | | ||
第161行: | 第198行: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|- | |- | ||
| | | | ||
第184行: | 第220行: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== 使用 === | === 使用 === |
2020年10月29日 (四) 01:54的版本
关于代理
代理,简单说就是:不直接操作对象,而使用代理对象来完成操作;
- 通过代理对象,可以对原对象进行方法扩展;
代理又可以分为
- 静态代理:通过聚合、继承的方式生成代理对象;
- 代理关系在编译时就确定了
- 动态代理:
- 运行期动态生成代理对象;
- 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
命令 | 说明 | 示例 |
---|---|---|
Enhancer | Enhancer创建一个被代理对象的子类并且拦截所有的方法调用(包括从Object中继承的toString和hashCode方法)
|
public class SampleClass {
public void test(){
System.out.println("hello world");
}
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(SampleClass.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("before method run...");
Object result = proxy.invokeSuper(obj, args);
System.out.println("after method run...");
return result;
}
});
SampleClass sample = (SampleClass) enhancer.create();
sample.test();
}
}
输出: before method run...
hello world
after method run...
|
使用
-
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(); } }