CGLIB基础

CGLIB

CGLIB(Code Generation Library)底层使用了ASM来进行操控字节码,用于生成新的Class文件。CGLIB的原理时代理,动态生成一个要代理类的子类,子类重写要代理类的所有除final方法以外的方法。

1
2
3
4
5
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>

CGLIB不能代理final方法是因为其本质是通过继承父类并重写父类的方法从而达到生成代理类的目的,并且由于其是继承父类重写父类方法的原理故其无法访问到父类的private方法,也无法代理父类的私有方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class A {
public static void main(String[] args) {
A a = new B();
a.print();//A
B b = new B();
b.print();//B
}
private void print() {
System.out.println("A");
}
}
class B extends A {
public void print() {
System.out.println("B");
}
}

常用类

  • Enhancer:Enhancer用于创建动态代理,它允许为非接口类型创建一个Java代理。
  • Callback:回调接口
  • MethodInterceptor:方法拦截器,此接口中只有intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)方法,其中MethodProxy有一个invokeSuper可以调用被代理类的方法。
  • CallbackFilter:回调过滤器,在CGLIB回调时可以设置不同的回调逻辑,实现此接口的int accept(Method method)方法返回一个代表回调数组Callback的下标索引。
  • CallbackHelper:使用CallbackFilter回调时需要关联Callback数组容易出错,而使用CallbackHelper时则不需要担心这个问题,因为CallbackHelper使用getCallback方法来获取需要使用的拦截代理。
  • InterfaceMaker:动态创建接口。

例子

被代理对象TargetObject:

1
2
3
4
public class TargetObject {
private String name;
//省略get、set、toString方法
}

拦截方法继承MethodIntercept:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class TargetInterceptor implements MethodInterceptor {

@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("========================================================================");
System.out.println("o=" + o.getClass());
System.out.println("methodProxy=" + methodProxy.getClass());
System.out.println("========================================================================");
System.out.println("开始执行【" + method.getName() + "】方法");
Object res = methodProxy.invokeSuper(o, objects);
System.out.println("结束调用");
return res;
}
}

使用Enhancer类来创建代理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Main {
public static void main(String[] args) {
//创建代理类
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(TargetObject.class);
enhancer.setCallback(new TargetInterceptor());
TargetObject to = (TargetObject) enhancer.create();

//测试
System.out.println("-------------------------------");
to.setName("你好");
System.out.println("-------------------------------");
System.out.println(to.getName());
System.out.println("-------------------------------");
System.out.println(to);
}
}