cglib动态代理原理分析
cglib动态代理原理分析
从一下四个方面深入理解cglib原理。
1、代码示例
2、代理类分析
3、fastClass机制分析
4、执行流程分析
一、代码示例
被代理的类
public class Target {
public void f(){
System.out.println("Target f()");
}
public void g(){
System.out.println("Target g()");
}
}
拦截器
public class MyInterceptor implements MethodInterceptor {
//参数说明1、obj(代理类对象) 2、method(被拦截方法的对象)3、objects(方法的参数) 4、methodProx(用于调用被连接方法的方法代理对象)
@Override
public Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("调用目标类前的增强处理");
//此方法不是通过反射机制调用目标方法而是FastClass机制调用代理类的CGLIB$g$0方法,在通过CGLIB$g$0方法的super.g()调用被代理类的g()
methodProxy.invokeSuper(obj,objects);//三
System.out.println("调用目标类后的增强处理");
return null;
}
}
测试类
public class Test {
public static void main(String[] args) {
//打印代理对象文件到本地
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/Users/xuhuanhuan");
//实例化一个增强器
Enhancer enhancer = new Enhancer()
//设置目标类
enhancer.setSuperclass(Target.class);
//设置回调类(该拦回调的方法在代理类中调用)
enhancer.setCallback(new MyInterceptor());
//生成一个代理类
Target target =(Target) enhancer.create();
//调用代理类的方法(代理类重写被代理类的对应方法)
target.g();//一
}
}
二、代理类分析
cglib动态代理的原理是利用增强器,代码运行时生成一个继承被代理类的一个子类,通过重写被代理类的方法来达到扩展的目的。
在测试用例使用
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/Users/xuhuanhuan");
打印我们运行时生成的代理类的class文件,反编译结果:public class Target$$EnhancerByCGLIB$$788444a0 extends Target implements Factory {
private boolean CGLIB$BOUND;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private static final Method CGLIB$g$0$Method;
private static final MethodProxy CGLIB$g$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$f$1$Method;
private static final MethodProxy CGLIB$f$1$Proxy;
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class localClass1 = Class.forName("net.sf.cglib. test. Target$$EnhancerByCGLIB$$788444a0");
Class localClass2;
Method[] tmp60_57 = ReflectUtils.findMethods(new String[] { "g", "()V", "f", "()V" }, (localClass2 = Class.forName("net.sf.cglib. test. Target")).getDeclaredMethods());
CGLIB$g$0$Method = tmp60_57[0];
CGLIB$g$0$Proxy = MethodProxy.create(localClass2, localClass1, "()V", "g", "CGLIB$g$0");
CGLIB$f$1$Method = tmp60_57[1];
CGLIB$f$1$Proxy = MethodProxy.create(localClass2, localClass1, "() V", "f", "CGLIB$f$1");
}
//调用被代理对象的g方法和被FastClass的invoke方法调用
final void CGLIB$g$0() {
super.g();//六
}
public final void g() {
MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
if (tmp4_1 == null) {
CGLIB$BIND_CALLBACKS(this);
tmp4_1 = this. CGLIB$CALLBACK_0;
}
if (this.CGLIB$CALLBACK_0 != null) {
//调用拦截器的intercept拦截方法
tmp4_1.intercept(this, CGLIB$g$0$Method, CGLIB$emptyArgs, CGLIB$g$0$Proxy);//二
}
else{
super.g();
}
}
}
FastClass机制分析
jdk动态代理是通过反射机制来调用被拦截的方法,因为效率比较低,所以cglib动态代理是通过Fastclass机制来调用被拦截的方法,
Fastclass是通过对类的方法建立索引,通过索引直接调用响应的方法。
通过小例子通俗描述下:
public class test10 {
public static void main(String[] args){
Test tt = new Test();
Test2 fc = new Test2();
int index = fc. getIndex("f()V");
fc.invoke(index, tt, null);
}
}
class Test{
public void f(){
System. out.println("f method");
}
public void g(){
System. out.println("g method");
}
}
class Test2{
public Object invoke(int index, Object o, Object[] ol){
Test t = (Test) o;
switch(index){
case 1:
t. f();
return null;
case 2:
t. g();
return null;
}
return null;
}
public int getIndex(String signature){
switch(signature.hashCode()){
case 3078479:
return 1;
case 3108270:
return 2;
}
return -1;
}
}
源码展示
net.sf.cglib.proxy.MethodProxy#invokeSuper源码
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();
}
}
//init函数干了什么
private void init()
{
/*
单例模式实现
*/
if (fastClassInfo == null)
{
synchronized (initLock)
{
if (fastClassInfo == null)
{
CreateInfo ci = createInfo;
FastClassInfo fci = new FastClassInfo();
/*
生成fastClass f1,f2,结合class文件分析
*/
// System.out.println("net.sf.cglib.proxy.MethodProxy.helper " + ci.c1.getName() + " " + ci.c2.getName() + " " + this.sig1 + " " + this.sig2);
fci.f1 = helper(ci, ci.c1);
fci.f2 = helper(ci, ci.c2);
/*
获取当前方法在f1,f2中的签名,得到一个index(方法与签名,index是一一对应的关系)
可以根据index映射对应类的对应方法
*/
fci.i1 = fci.f1.getIndex(sig1);
fci.i2 = fci.f2.getIndex(sig2);
fastClassInfo = fci;
createInfo = null;
}
}
}
}
//helper函数干了什么
private static FastClass helper(CreateInfo ci, Class type) {
//根据ci得到该方法的委托类,实现类,分别生成这两个类的fastClass
FastClass.Generator g = new FastClass.Generator();
g.setType(type);
g.setClassLoader(ci.c2.getClassLoader());
g.setNamingPolicy(ci.namingPolicy);
g.setStrategy(ci.strategy);
g.setAttemptLoad(ci.attemptLoad);
return g.create();
}
FastClass
fci.f2.invoke(fci.i2, obj, args)分析源码
public int getIndex(Signature signature) {
String obj = signature.toString();
switch (obj.hashCode()) {
case 1540695073:
if (obj.equals("CGLIB$g$0()V")) {
return 17;
}
break;
}
}
public Object invoke(int i, Object obj, Object[] objArr) throws InvocationTargetException {
InvocationTargetException invocationTargetException;
b2e6ff51 cglib_CglibLearn_serviceImpl__EnhancerByCGLIB__b2e6ff51 = (b2e6ff51) obj;
switch (i) {
case 17:
cglib_CglibLearn_serviceImpl__EnhancerByCGLIB__b2e6ff51.CGLIB$g$0();//五
return null;
default:
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
}
//cglib_CglibLearn_serviceImpl__EnhancerByCGLIB__b2e6ff51.CGLIB$say$0()函数
final void CGLIB$g$0() {
super.g();//即CglibLearn.serviceImpl.g()方法
}
执行流程分析
步骤一、Target target =(Target) enhancer.create();//生成代理类
步骤二、target.g();//调用代理里的过g()
步骤三、在g()的方法里判断CGLIB$CALLBACK_0(创建代理对象时传入的拦截器对象)如果不为空,调用intercept拦截器的回调方法
步骤四、执行拦截器的回调方法methodProxy.invokeSuper(obj,objects);其实时调用代理类创建CGLIB$g$0$Proxy(MethodProxy)里的invokeSuper方法
步骤五、fci.f2.invoke(fci.i2,obj,args);//FastClass类的方法
步骤六、匹配方法对应的索引,然后调用cglib_CglibLearn_serviceImpl__EnhancerByCGLIB__b2e6ff51.CGLIB$g$0();
步骤七、super.g(),真正执行被代理类的方法。
参考连接
1、http://www.doc88.com/p-59416940590088.html
2、https://blog.csdn.net/xf_87/article/details/102949359

浙公网安备 33010602011771号