前言
前几天使用公司项目,分析到某个代码接口实现类扫包增强型执行,就是使用的cglib动态代理模式,用来实现对日志打印、分布式锁、事务和异步线程池执行的增强。这里的底层原理是怎样,我下文进行表述。
使用
maven依赖引入
创建一个maven项目,pom.xml文件引入如下的依赖。
<dependencies>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.12</version>
</dependency>
</dependencies>
拦截类说明和创建
创建一个拦截器类CglibMethodInterceptor,实现接口net.sf.cglib.proxy.MethodInterceptor,对应的方法如下:
public class CglibMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("<<<<<日志收集开始...>>>>>>>");
Object reuslt = proxy.invokeSuper(obj, args);
System.out.println("<<<<<日志收集结束...>>>>>>>");
return reuslt;
}
}
proxy为代理类,obj为代理对象,args为目标参数。proxy.invokeSuper(obj,args)为执行代理对象的目标方法。method为目标方法。
如果需要使用代理,则编写如下的方法:
public class TestProxy {
public static void main(String[] args) {
//System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "E:\\code");
CglibMethodInterceptor cglibMethodInterceptor = new CglibMethodInterceptor();
Enhancer enhancer = new Enhancer();
// 设置代理类的父类
enhancer.setSuperclass(HelloServiceImpl.class);
// 设置回调对象
enhancer.setCallback(cglibMethodInterceptor);
// 创建代理对象
HelloService orderService = (HelloServiceImpl) enhancer.create();
orderService.hello();
}
}
Enhancer这里要加入回调拦截器,就是通过setCallback方法进行的,被代理类在setSuperclass来传入的。代理对象通过enhancer#create()方法来创建的。这里可以看到cglib动态代理是通过继承法来进行代理的。那这里底层原理是怎样的,下一节可以展示的。
cglib动态代理原理
如图所示,cglib动态代理生成三个类,第一个的父类才是被代理的类,另外两个是cglib包的enhancer和fastClass的子类。当调用被代理类的方法hello时,走如下的代码:
public final void hello() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
var10000.intercept(this, CGLIB$hello$0$Method, CGLIB$emptyArgs, CGLIB$hello$0$Proxy);
} else {
super.hello();
}
}
这里MethodInterceptor 是上面的实现子类,它为null则直接执行被代理类对应的方法,如果不为空则执行对应的intercept方法。而fastClass如何调用对应的代理类呢?那请看下面的代码:
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
init();
FastClassInfo fci = fastClassInfo;
return fci.f2.invoke(fci.i2, obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
private static class FastClassInfo
{
FastClass f1;
FastClass f2;
int i1;
int i2;
}
Fastclass类的作用是创建索引机制。他的子类就是上面的第二个,对应生成代码如下:
public int getIndex(Class[] var1) {
switch(var1.length) {
case 0:
return 0;
default:
return -1;
}
}
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
HelloServiceImpl var10000 = (HelloServiceImpl)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
var10000.hello();
return null;
case 1:
return new Boolean(var10000.equals(var3[0]));
case 2:
return var10000.toString();
case 3:
return new Integer(var10000.hashCode());
}
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
如果index为0,则执行被代理类的hello。从这里可以看出对应的实现不是通过反射而是通过继承。