每天看看新东西,心情也要好上许多
问题
- cglib是如何实现动态代理的
- cglib如何支持类的代理
- cglib和jdk的动态代理有什么区别
使用方式
cglib不属于jdk的一部分,因此要使用需要先引入相应的包,maven依赖如下
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.0</version>
</dependency>
另外因为spring的aop有使用cglib的实现,因此如果项目引入了spring-core包,那么spring-core包下面已经包含了cglib
使用例子
Test.java
public class Test {
public static void main(String args[]){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(TestCglib.class);
enhancer.setCallback(new CglibMethodInterceptor());
TestCglib testCglib = (TestCglib)enhancer.create();
testCglib.sayBye("asdsd");
}
}
TestCglib.java
public class TestCglib {
public String sayHi(String str){
System.out.println("我是被代理的sayHi方法");
return str;
}
public String sayBye(String str){
System.out.println("我是被代理的sayBye方法");
return str;
}
}
CglibMethodInterceptor.java
public class CglibMethodInterceptor implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println(method.getName()+"执行之前做一些准备工作");
Object result = methodProxy.invokeSuper(o,objects);
System.out.println(method.getName()+"执行之后做一些准备的工作");
return result;
}
}
实现
和jdk的代理一样,我们先来看看生成的代理类长什么样:
TestCglib$$EnhancerByCGLIB$$8b20fd94.class(代理类)
public class TestCglib$$EnhancerByCGLIB$$8b20fd94 extends TestCglib implements Factory {
private static final Method CGLIB$sayHi$1$Method;
private static final MethodProxy CGLIB$sayHi$1$Proxy;
static void CGLIB$STATICHOOK1() {
Class var0 = Class.forName("TestCglib$$EnhancerByCGLIB$$8b20fd94");
Class var1;
Method[] var10000 = ReflectUtils.findMethods(new String[]{"sayBye", "(Ljava/lang/String;)Ljava/lang/String;", "sayHi", "(Ljava/lang/String;)Ljava/lang/String;"}, (var1 = Class.forName("TestCglib")).getDeclaredMethods());
CGLIB$sayHi$1$Method = var10000[1];
CGLIB$sayHi$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/String;)Ljava/lang/String;", "sayHi", "CGLIB$sayHi$1");
}
final String CGLIB$sayHi$1(String var1) {
return super.sayHi(var1);
}
public final String sayHi(String var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? (String)var10000.intercept(this, CGLIB$sayHi$1$Method, new Object[]{var1}, CGLIB$sayHi$1$Proxy) : super.sayHi(var1);
}
}
TestCglib$$EnhancerByCGLIB$$8b20fd94$$FastClassByCGLIB$$2ada1598(代理类的FastClass类)
public class TestCglib$$EnhancerByCGLIB$$8b20fd94$$FastClassByCGLIB$$2ada1598 extends FastClass {
public TestCglib$$EnhancerByCGLIB$$8b20fd94$$FastClassByCGLIB$$2ada1598(Class var1) {
super(var1);
}
public int getIndex(Signature var1) {
String var10000 = var1.toString();
switch(var10000.hashCode()) {
case 481426893:
if (var10000.equals("sayHi(Ljava/lang/String;)Ljava/lang/String;")) {
return 7;
}
break;
case 2082116023:
if (var10000.equals("CGLIB$sayHi$1(Ljava/lang/String;)Ljava/lang/String;")) {
return 11;
}
}
return -1;
}
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
8b20fd94 var10000 = (8b20fd94)var2;
int var10001 = var1;
try {
switch(var10001) {
case 7:
return var10000.sayHi((String)var3[0]);
case 11:
return var10000.CGLIB$sayHi$1((String)var3[0]);
}
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
}
TestCglib$$FastClassByCGLIB$$2f8a820f(原始类的FastClass类)
public class TestCglib$$FastClassByCGLIB$$2f8a820f extends FastClass {
public TestCglib$$FastClassByCGLIB$$2f8a820f(Class var1) {
super(var1);
}
public int getIndex(Signature var1) {
String var10000 = var1.toString();
switch(var10000.hashCode()) {
case 481426893:
if (var10000.equals("sayHi(Ljava/lang/String;)Ljava/lang/String;")) {
return 1;
}
break;
return -1;
}
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
TestCglib var10000 = (TestCglib)var2;
int var10001 = var1;
try {
switch(var10001) {
case 1:
return var10000.sayHi((String)var3[0]);
}
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
}
可以看到上面一共生成了三个类,为了突出重点我只保留了和sayHi
这个方法相关的部分,这三个类的作用如下:
- 代理类
- 代理类的FastClass类
- 原始类的FastClass类
其中FastClass的类的作用是提前将需要执行的类的所有方法排序,为每个方法生成index,后续直接通过index定位方法执行调用,相对反射而言减少了查询方法的步骤。
ps:由实现可见一共有两个fastClass类,分别对应原始类和代理类,其使用场景分别对应MethodProxy(方法代理类)的invoke 和 invokeSuper类,这两个方法的区别是当调用invoke的时候会直接使用原始类来执行方法,而使用invokeSuper时是采用的代理类执行方法
假设我们访问的方法是sayHi
,其调用过程用语言描述如下:
- 调用代理类的
sayHi
方法,代理类中会为每个方法生成一个方法代理类
- 代理类将方法调用转发至拦截器的
intercept
方法 - 拦截器在
intercept
方法中调用sayHi
的方法代理类
的invokeSuper
方法 方法代理类
使用代理类的FastClass类调用代理类的CGLIB$sayHi$1 方法- 代理类调用super.sayHi()
- 执行原始类的
sayHi
方法
流程图如下:
结论
Q:cglib是如何实现动态代理的
利用asm在运行时动态生成和注册代理类,代理类采用继承的方式实现原始类的所有接口,并为每个接口实现方法代理,当调用代理类的方法时会先将所有请求转发至拦截器,后在拦截器中调用方法代理,在方法代理中再通过fastclass类回调回代理类
Q:cglib如何支持类的代理
生成的代理类会继承原始类
Q:cglib和jdk的动态代理有什么区别
- cglib 采用继承实现,jdk采用实现接口
- cglib 底层依赖asm,jdk不依赖