cglib动态代理

Cglib动态代理

具体类对象

package cn.huangwei.classLoader.Proxy;

public class CglibService {

    public CglibService(){

       System.out.println("CglibService构造器");

    }

    public void getCglib(){

       System.out.println("CglibServiceget方法");

    }

}

拦截器对象

package cn.huangwei.classLoader.Proxy;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.MethodInterceptor;

import net.sf.cglib.proxy.MethodProxy;

public class CglibIntercepter implements MethodInterceptor{

    @Override

    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {

       // TODO Auto-generated method stub

       System.out.println("执行前。。。。");

       Object object = proxy.invokeSuper(obj, args);

       System.out.println("执行后。。。。");

       return object;

    }

}

 

测试类

package cn.huangwei.classLoader.Proxy;

import net.sf.cglib.proxy.Enhancer;

public class TestCglibProxy {

    public static void main(String[] args) {

       //实例化增强器,类生成器

       Enhancer eh = new Enhancer();

       //设置目标类

       eh.setSuperclass(CglibService.class);

       //设置拦截对象

       CglibIntercepter ci = new CglibIntercepter();

       eh.setCallback(ci);

       //生成代理类对象,返回实例

       CglibService cs = (CglibService) eh.create();

       cs.getCglib();

    }

}

 

 

 

 

 

可以得到Cglib生成的三个文件

第一个是代理类的fastclass,第二个是被代理类CglibService的fastclass

Aaaed75.class就是cglib生成的代理类,继承了CglibService类(CglibService类)实现了Factory,只给出部分关键代码

public class CglibService$$EnhancerByCGLIB$$eaaaed75

  extends CglibService

  implements Factory

{

 

  private MethodInterceptor CGLIB$CALLBACK_0;//拦截器

  private static final Method CGLIB$ getCglib $0$Method;//被代理方法

  private static final MethodProxy CGLIB$ getCglib $0$Proxy;//代理方法

 

 

  static void CGLIB$STATICHOOK1()

  {

    CGLIB$THREAD_CALLBACKS = new ThreadLocal();

    CGLIB$emptyArgs = new Object[0];

Class localClass1 = Class.forName("cn.huangwei.classLoader.Proxy. CglibService $$EnhancerByCGLIB$$eaaaed75");//代理类

    Class localClass2;//被代理类CglibService

。。。

 

Method[] tmp223_220 = ReflectUtils.findMethods(new String[] { " getCglib ", "()V" }, (localClass2 =

Class.forName("cn.huangwei.classLoader.Proxy. CglibService ")).getDeclared- Methods());

    CGLIB$ getCglib $0$Method = tmp223_220[0];

    CGLIB$ getCglib $0$Proxy = MethodProxy.create(localClass2, localClass1, "()V", " getCglib ", "CGLIB$ getCglib $0");

    tmp223_220;

    return;

  }

 

 

public class MethodProxy {

    private Signature sig1;

    private Signature sig2;

    private MethodProxy.CreateInfo createInfo;

    private final Object initLock = new Object();

    private volatile MethodProxy.FastClassInfo fastClassInfo;

    //c1:被代理对象Class
    //c2:代理对象Class
    //desc:入参类型
    //name1:被代理方法名
    //name2:代理方法名

    public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {

        MethodProxy proxy = new MethodProxy();

        proxy.sig1 = new Signature(name1, desc);//被代理方法签名

        proxy.sig2 = new Signature(name2, desc);//代理方法签名

        proxy.createInfo = new MethodProxy.CreateInfo(c1, c2);

        return proxy;

    }

private static class CreateInfo {
    Class c1;
    Class c2;
    NamingPolicy namingPolicy;
    GeneratorStrategy strategy;
    boolean attemptLoad;

    public CreateInfo(Class c1, Class c2) {
        this.c1 = c1;
        this.c2 = c2;
        AbstractClassGenerator fromEnhancer = AbstractClassGenerator.getCurrent();
        if(fromEnhancer != null) {
            this.namingPolicy = fromEnhancer.getNamingPolicy();
            this.strategy = fromEnhancer.getStrategy();
            this.attemptLoad = fromEnhancer.getAttemptLoad();
        }

    }
}

我们通过代理类的源码可以看到,代理类会获得所有在父类继承来的方法,并且会有MethodProxy与之对应,比如 Method CGLIB$getCglib $0$Method、MethodProxy CGLIB$getCglib $0$Proxy;

 

//被代理方法(methodProxy.invokeSuper会调用)
   final void CGLIB$ getCglib $0() {

      super. getCglib ();

   }

   //代理方法

   public final void getCglib () {

      MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;

      if(this.CGLIB$CALLBACK_0 == null) {

         CGLIB$BIND_CALLBACKS(this);

         var10000 = this.CGLIB$CALLBACK_0;

      }

 

      if(var10000 != null) {
       
 //调用拦截器

         var10000.intercept(this, CGLIB$setPerson$0$Method, CGLIB$emptyArgs, CGLIB$setPerson$0$Proxy);

      } else {

         super. getCglib ();

      }

   }

主函数使用代理对象调用getCglib方法->调用拦截器->methodProxy.invokeSuper->CGLIB$getCglib $0->被代理对象getCglib方法

 

public class MethodProxy {
    private Signature sig1;
    private Signature sig2;
    private MethodProxy.CreateInfo createInfo;
    private final Object initLock = new Object();
    private volatile MethodProxy.FastClassInfo fastClassInfo;
    //c1:被代理对象Class

      //c2:代理对象Class

      //desc:入参类型

      //name1:被代理方法名

      //name2:代理方法名
    public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
        MethodProxy proxy = new MethodProxy();
        proxy.sig1 = new Signature(name1, desc);//被代理方法签名
        proxy.sig2 = new Signature(name2, desc);//代理方法签名
        proxy.createInfo = new MethodProxy.CreateInfo(c1, c2);
        return proxy;
    }
private static class CreateInfo {

    Class c1;

    Class c2;

    NamingPolicy namingPolicy;

    GeneratorStrategy strategy;

    boolean attemptLoad;

  

    public CreateInfo(Class c1, Class c2) {

        this.c1 = c1;

        this.c2 = c2;

        AbstractClassGenerator fromEnhancer = AbstractClassGenerator.getCurrent();

        if(fromEnhancer != null) {

            this.namingPolicy = fromEnhancer.getNamingPolicy();

            this.strategy = fromEnhancer.getStrategy();

            this.attemptLoad = fromEnhancer.getAttemptLoad();

        }

  

    }

}

public Object invoke(Object obj, Object[] args) throws Throwable {

        try {

            init();

            FastClassInfo fci = fastClassInfo;

            return fci.f1.invoke(fci.i1, obj, args);

        } catch (InvocationTargetException e) {

            throw e.getTargetException();

        } catch (IllegalArgumentException e) {

            if (fastClassInfo.i1 < 0)

                throw new IllegalArgumentException("Protected method: " + sig1);

            throw e;

        }

    }

 

public Object invokeSuper(Object obj, Object[] args) throws Throwable {
        try {
            this.init();
            MethodProxy.FastClassInfo fci = this.fastClassInfo;
            return fci.f2.invoke(fci.i2, obj, args);
        } catch (InvocationTargetException var4) {
            throw var4.getTargetException();
        }
    }
上面代码调用过程就是获取到代理类对应的fastclass,并执行了代理方法,init方法就是用于生成fastclass对象,如果已存在就不创建;
-------------------------------------------------------------------------------------
Cglib动态代理执行代理方法效率之所以比JDK的高是因为Cglib采用了FastClass机制,它的原理简单来说就是:为代理类和被代理类各生成一个Class,这个Class会为代理类或被代理类的方法分配一个index(int类型)。getIndex就是用于给index赋值的方法,该方法在init中会被调用,这个index当做一个入参,FastClass就可以直接定位到要调用的方法直接进行调用省去了反射的过程、
private static class FastClassInfo {

    FastClass f1;//被代理类FastClass

    FastClass f2;//代理类FastClass

    int i1; //被代理类的方法签名(index)

    int i2;//代理类的方法签名

  

    private FastClassInfo() {

    }

}

 

//根据方法签名获取index,在init方法中会被调用

 public int getIndex(Signature var1) {
      String var10000 = var1.toString();
      switch(var10000.hashCode()) {
      case -2077043409:
         if(var10000.equals("getPerson(Ljava/lang/String;)Lcom/demo/pojo/Person;")) {
            return 21;
         }
         break;
      case -2055565910:
         if(var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
            return 12;
         }
         break;
      case -1902447170:
         if(var10000.equals("getCglib()V")) {
            return 7;
         }
         break;
   //省略部分代码.....

   

 //根据index直接定位执行方法,在methodProxy的invoke或者invokesuper中调用
 public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
      eaaaed75 var10000 = (eaaaed75)var2;
      int var10001 = var1;
      try {
         switch(var10001) {
          case 7:
            var10000.setPerson();
            return null;
        。。。。。。
         case 19:
            var10000.CGLIB$setPerson$0();
            return null;
        //省略部分代码....
      } catch (Throwable var4) {
         throw new InvocationTargetException(var4);
      }
 
      throw new IllegalArgumentException("Cannot find matching method/constructor");
   }

 

 

//MethodProxy invoke/invokeSuper都调用了init()

private void init() {
        if(this.fastClassInfo == null) {
            Object var1 = this.initLock;
            synchronized(this.initLock) {
                if(this.fastClassInfo == null) {
                    MethodProxy.CreateInfo ci = this.createInfo;
                    MethodProxy.FastClassInfo fci = new MethodProxy.FastClassInfo();
                    fci.f1 = helper(ci, ci.c1);//如果缓存中就取出,没有就生成新的FastClass
                    fci.f2 = helper(ci, ci.c2);
                    fci.i1 = fci.f1.getIndex(this.sig1);//获取方法的index
                    fci.i2 = fci.f2.getIndex(this.sig2);
                    this.fastClassInfo = fci;
                    this.createInfo = null;
                }
            }
        }
 

 

总过程:生成一个enhancer的实例,设定被代理类和拦截器,调用enhancer的create方法,之后能得到代理类对象proxy,并完成一些列的初始化工作,代理类对象继承了CglibService类,代理对象含有MethodInterceptor拦截器、表示被代理的方法Method对象和表示被代理的方法的MethodProxy;以及两个方法CGLIB$ getCglib $0和getCglib()方法;当主函数中调用proxy的getCglib时,会先获取拦截器,此时的拦截器,就是通过enhancer设定拦截器即CglibInterceptor的实例;然后调用intercept方法,完成回调;在CglibInterceptor类中的intercept方法中,调用methodProxy.invokeSuper方法;内部执行是,初始化fastclass,然后通过fastclass机制,获取到方法对应的index值,根据调index值用fastclass的invoke方法,此时将会调用CGLIB$ getCglib $0,即调用super父类CglibService的getCglib方法;调用结束。如果methodProxy.invoke方法,根据调index值用fastclass的invoke方法,此时将会调用getCglib造成循环调用;

1.JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。

2.JDK和Cglib都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码,Cglib代理实现更复杂,生成代理类比JDK效率低。

3.JDK调用代理方法,是通过反射机制调用,Cglib是通过FastClass机制直接调用方法,Cglib执行效率更高。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值