设计模式之动态代理

设计模式之动态代理,第1张

Cglib动态代理 方式一
public interface ITarget {
    public void iTest(String username);
}

public class IClazz implements ITarget {
    @Override
    public void iTest(String username) {
        System.out.println("this is username = " + username);
    }
}
public class ITargetProxy<T> implements MethodInterceptor {

    private T t;

    public ITargetProxy (T t){
        this.t = t;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("interface before");
        // 通过被代理类 IClazz 调用目标方法
        Object invoke = method.invoke(t, objects);
        System.out.println("interface after");
        return invoke;
    }
}
public class ITest {

    public static void main(String[] args) {
        String path = TargetProxy.class.getClassLoader().getResource("").getPath();
        System.getProperties().setProperty("cglib.debugLocation",path);
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, path);
        IClazz iClazz = new IClazz();
        ITargetProxy iTargetProxy = new ITargetProxy(iClazz);
        ITarget clazz = getClazz(ITarget.class,iTargetProxy);
        clazz.iTest("宋江");

    }

    public static  <T> T getClazz(Class<T> clazz,ITargetProxy iTargetProxy){
        //字节码增强的类
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(iTargetProxy);
        return (T)enhancer.create();
    }
}
方式二
public class TargetClazz {

    public String thanksHello(String msg){
        System.out.println("i am invoke");
        return msg;
    };
}
public class TargetProxyV2<T> implements MethodInterceptor {

// 表示被代理的目标类:必须是实例,不可以是类信息
 T t;

 public TargetProxyV2(T t){
     this.t = t;
 }

 public static void main(String[] args){

     // 用反编译工具打开生成的字节码类文件即可
     String path = TargetProxyV2.class.getClassLoader().getResource("").getPath();
     System.getProperties().setProperty("cglib.debugLocation",path);
     System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, path);

	// 创建被代理目标类的实例
     TargetProxyV2 proxy = new TargetProxyV2(new TargetClazz());
     TargetClazz clazz = (TargetClazz)proxy.getClazz(TargetClazz.class);
     clazz.thanksHello("hahahah");
 }

 public <T> T getClazz(Class<T> clazz){
     //字节码增强的类
     Enhancer enhancer = new Enhancer();
     enhancer.setSuperclass(clazz);
     enhancer.setCallback(this);
     return (T)enhancer.create();
 }

 /**
   *
   * @param o 表示代理类 TargetClazz$$EnhancerByCGLIB$$cb3b2d89
   * @param method 目标方法
   * @param objects 目标方法对应的参数
   * @param methodProxy 目标方法的代理方法
   * @return
   * @throws Throwable
  */
 @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("before");
        Object invoke = method.invoke(t, objects);//正常
        // 调用被代理类中的 CGLIB$thanksHello//        Object invoke = methodProxy.invokeSuper(t, objects);//异常 方法
// 调用被代理类中的 thanksHello 方法
        //        Object invoke = methodProxy.invoke(t, objects);//正常
System
        ..outprintln("after");return
        ; invoke}
    public
方式三
class TargetProxy <Timplements> MethodInterceptor public {

    static void main (String[]) args// 用反编译工具打开生成的字节码类文件即可{

        String
        = path TargetProxy .class.getClassLoader().getResource("").getPath();System
        .getProperties().setProperty("cglib.debugLocation",)path;System
        .setProperty(DebuggingClassWriter.,DEBUG_LOCATION_PROPERTY) path;TargetProxy

        = proxy new TargetProxy ();TargetClazz
        = clazz ( TargetClazz).proxygetClazz(TargetClazz.class);.
        clazzthanksHello("hahahah");}
    public

    < TT> getClazz (Class<T)> clazz//字节码增强的类{
        Enhancer
        = enhancer new Enhancer ();.
        enhancersetSuperclass()clazz;.
        enhancersetCallback(this);return
        ( T).enhancercreate();}
    @Override
    
    public
    Object intercept (Object, oMethod , methodObject [], objectsMethodProxy ) methodProxythrows Throwable System {
        ..outprintln("before");//        Object invoke = method.invoke(o, objects); //异常
// 调用代理类中 CGLIB$thanksHelloObject 方法
        =
        . invoke invokeSuper methodProxy(,)o; objects//正常// 调用代理类中 thanksHello 方法//        Object invoke = methodProxy.invoke(o, objects);//异常
        System
.
        .printlnout("after");return;
        } invoke}
    TargetClazz
EnhancerByCGLIB

备注:通过 “method.invoke” 调用会生成代理类:

// 目标类的代理类$$TargetClazz$$cb3b2d89

通过 “methodProxy.invoke” 调用生成代理类:

EnhancerByCGLIB
// 目标类代理类 对应的 FastClass代理类$$TargetClazz$$cb3b2d89
EnhancerByCGLIB
FastClassByCGLIB$$11$$cb3b2d89$$// 目标类 对应的 FastClass代理类$$TargetClazzee3115
FastClassByCGLIB
92$$TargetClazz$$EnhancerByCGLIB$$cb3b2d89$$finalbd8292
代理类

代理类 String,其父类为被代理类。重要方法如下:

0 ( CGLIB$thanksHello$String)// 调用父类方法,也即目标方法 paramStringreturn {
	super
    . thanksHello();paramString}public
  final
  
String thanksHello ( String)if paramString( {
    this .==nullCGLIB$CALLBACK_0 ) BIND_CALLBACKS(
      CGLIB$this);return( 
    this .!=nullCGLIB$CALLBACK_0 ) ?( String )this..interceptCGLIB$CALLBACK_0(this,0Method CGLIB$thanksHello$,$newObject 	
    	[ ]}, { paramString 0Proxy CGLIB$thanksHello$)$:super . thanksHello();paramString}CGLIB$thanksHellothanksHello
  invoke

以上代理类方法 thanksHello & invokeSuper 其实就是 MethodProxy 代理的方法。其中,CGLIB$thanksHellopublic调用的是static代理方法,MethodProxy调用的是create代理方法。

MethodProxy
( Class , Class,String c1, String c2, String desc) //c1 是被代理类(目标类) c2 代理类 desc表示被代理方法的返回值类型 name1表示被代理方法名thanksHello  name2表示代理类中的CGLIB$thanksHelloMethodProxy方法 name1= new name2MethodProxy {
	(
	) proxy ; . =newSignature(
	proxy,sig1 ) ; //被代理方法签名(目标类方法签名),也就是代表 void thanksHello().name1= descnewSignature(
	proxy,sig2 ) ; //代理类方法签名,也就是 void CGLIB$thanksHello.()=name2new descCreateInfo(,
	proxy)createInfo ; //CreateInfo中表示的是被代理类和代理类中的信息 return;c1} c2privatevoidinit
	( proxy)
if
( == null)synchronized {
( )fastClassInfo if (== {
	null )initLockCreateInfo {
		= ;fastClassInfo // f1代表目标类 f2代理代理类 FastClassInfo= {
			new ci FastClassInfo createInfo(
)

			; fci . = helper(,.
			fci)f1 ; // 生成目标类的 FastClass代理类,也就是TargetClazz$$FastClassByCGLIB$bd8292// 生成目标类代理类 对应的 FastClass代理类,也就是目标类代理类(TargetClazz$$EnhancerByCGLIB$$cb3b2d89)的FastClass代理类 TargetClazz$$EnhancerByCGLIB$$cb3b2d89$$FastClassByCGLIB$ee3115ci. ci=c1helper(,
			.
			fci)f2 ; // 根据方法签名1从 TargetClazz$$FastClassByCGLIB$bd8292 获取 目标类方法void thanksHello()的下标.ci= ci.c2.getIndex
			(
			fci)i1 ; fci// 根据方法签名2从 TargetClazz$$EnhancerByCGLIB$$cb3b2d89$$FastClassByCGLIB$ee3115 获取 目标类方法vvoid CGLIB$thanksHello.()的下标f1=..sig1getIndex(
			)
			fci;i2 = fci;f2=null;sig2}}
			fastClassInfo } fci}
			createInfo public Objectinvoke
		(
	Object
,
Object
[ ] )throwsThrowable objinit (); argsFastClassInfo = ; {
	return..invoke
	( fci . fastClassInfo,
	, fci)f1;// 通过下标调用对应的方法}fci
  • 根据方法签名获取目标方法的下标。
  • i1public objint argsgetIndex(Signature )
    FastClass

    FastClass中涉及的代理类,其功能主要包括:

    • 直接通过目标方法的下标执行具体的方法。(优于反射方式)
    TargetClazz$$FastClassByCGLIB$bd8292  public Objectinvoke( paramSignatureint
    
      ,

    Object

    , Object []) paramIntthrows InvocationTargetException paramObjecttry switch() paramArrayOfObjectcase 0 : {
        / {
          / 0paramIntreturn {
            ( (TargetClazz)) 如果下标为.,则调用
              thanksHello ((String)paramObject[0]);case1paramArrayOfObject:returnnewBoolean(
            ( (TargetClazz
              ) ) .equals([0]paramObject));caseparamArrayOfObject2:return((TargetClazz
            ) ).
              toString ();caseparamObject3:returnnewInteger(
            ( (TargetClazz
              ) ) .hashCode());paramObject}}catch(Throwable)throw
          new 
        InvocationTargetException ( null) throwable; {
          } throw newIllegalArgumentException("Cannot find matching method/constructor")
        ; 
        } TargetClazz$$EnhancerByCGLIB$$cb3b2d89$$FastClassByCGLIB$ee3115 publicObjectinvoke(int
      ,
    

    Object

    , Object []) paramIntthrows InvocationTargetException paramObjecttry switch() paramArrayOfObjectcase 0 : {
        return {
          new BooleanparamInt( {
            ( (TargetClazz
              EnhancerByCGLIB ) ).equals([$$0$$cb3b2d89]paramObject));caseparamArrayOfObject1:return((TargetClazz
            EnhancerByCGLIB ))
              . toString()$$;$$cb3b2d89caseparamObject2:returnnewInteger(
            ( (TargetClazz
              EnhancerByCGLIB ) ).hashCode()$$)$$cb3b2d89;paramObjectcase3:return((TargetClazz
            EnhancerByCGLIB ))
              . clone()$$;$$cb3b2d89caseparamObject4:return((TargetClazz
            EnhancerByCGLIB ))
              . newInstance(($$Callback$$cb3b2d89[paramObject])[0]);case5paramArrayOfObject:return((TargetClazz
            EnhancerByCGLIB ))
              . newInstance(($$Class$$cb3b2d89[paramObject])[0],(Object[paramArrayOfObject])[1 ],(Callback[paramArrayOfObject])[2 ]);case6paramArrayOfObject:return((TargetClazz
            EnhancerByCGLIB ))
              . newInstance(($$Callback$$cb3b2d89)paramObject[0]);case7paramArrayOfObject:TargetClazzEnhancerByCGLIB.STATICHOOK1
            ( );
              return$$null$$cb3b2d89;CGLIB$case8:return
              ( (TargetClazz
            EnhancerByCGLIB ))
              . 0(($$String$$cb3b2d89)paramObject[0CGLIB$thanksHello$]);case9paramArrayOfObject:returnnewBoolean(
            ( (TargetClazz
              EnhancerByCGLIB ) ).1([$$0$$cb3b2d89]paramObject))CGLIB$equals$;caseparamArrayOfObject10:return((TargetClazz
            EnhancerByCGLIB ))
              . 2()$$;$$cb3b2d89caseparamObject11:CGLIB$toString$returnnewInteger(
            ( (TargetClazz
              EnhancerByCGLIB ) ).3()$$)$$cb3b2d89;paramObjectcase12CGLIB$hashCode$:return((TargetClazz
            EnhancerByCGLIB ))
              . 4()$$;$$cb3b2d89caseparamObject13:CGLIB$clone$returnTargetClazzEnhancerByCGLIB.
            findMethodProxy ((
              Signature )$$[$$cb3b2d890CGLIB$]);case14paramArrayOfObject:return((TargetClazz
            EnhancerByCGLIB ))
              . thanksHello(($$String$$cb3b2d89)paramObject[0]);case15paramArrayOfObject:((TargetClazzEnhancerByCGLIB
            ) ).
              setCallback(($$($$cb3b2d89NumberparamObject)[0]).intValue(paramArrayOfObject),(Callback)[1]) ;returnnullparamArrayOfObject;case16:(
              ( TargetClazzEnhancerByCGLIB
            ) ).
              setCallbacks(($$Callback$$cb3b2d89[paramObject])[0]);returnnullparamArrayOfObject;case17:TargetClazz
              EnhancerByCGLIB .SET_STATIC_CALLBACKS
            ( (Callback
              [$$]$$cb3b2d89)CGLIB$[0]);returnnullparamArrayOfObject;case18:TargetClazz
              EnhancerByCGLIB .SET_THREAD_CALLBACKS
            ( (Callback
              [$$]$$cb3b2d89)CGLIB$[0]);returnnullparamArrayOfObject;case19:return
              ( (TargetClazz
            EnhancerByCGLIB ))
              . getCallback(($$($$cb3b2d89NumberparamObject)[0]).intValue(paramArrayOfObject));case20:return((TargetClazz
            EnhancerByCGLIB ))
              . getCallbacks()$$;$$cb3b2d89}paramObject}catch(Throwable)throw
          new 
        InvocationTargetException ( null) throwable; {
          } throw newIllegalArgumentException("Cannot find matching method/constructor")
        ; 
        } FastClass FastClassFastClass
      
    

    使用 的原因是其实现方式不是通过反射实现的,而是通过下标 快速在 生成目标类的 代理类 | 代理类的 代理类中找到执行的目标方法。

    备注:内容来源 https://www.bilibili.com/video/BV1fF411q7QQ?p=4&spm_id_from=pageDriver

    欢迎分享,转载请注明来源:内存溢出

    原文地址:https://www.54852.com/langs/877881.html

    (0)
    打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
    上一篇 2022-05-13
    下一篇2022-05-13

    发表评论

    登录后才能评论

    评论列表(0条)

      保存