【问题标题】:How to implement a delegation using cglib?如何使用 cglib 实现委托?
【发布时间】:2014-08-13 03:04:01
【问题描述】:

这里我需要创建BImpl 的实例,但BImpl 需要通过接口A 访问功能。为此,该类实现了这个接口A。如何在运行时连接BImpl 的这些接口方法的委托?这个想法是BImpl 可以使用A 的方法。

在我的情况下,A 是已知的,AImpl 实例是在运行时创建的。

public static void main(String[] args) {
  B b = (B) Enhancer.create(BImpl.class, new MyInterceptor());
  System.out.println(b.cellValue());
}

interface A {
  String value();
}

class AImpl implements A {

  @Override
  public String value() {
    return "MyA";
  }
}

interface B {
  String cellValue();
}

abstract class BImpl implements B, A {
  @Override
  public String cellValue() {
    return value() + "MyBCell";
  }
}

class MyInterceptor implements MethodInterceptor {

  @Override
  public Object intercept(Object obj, Method method, Object[] args,
                          MethodProxy proxy) throws Throwable {
    System.out.println(method.getName());
    if ("value".equals(method.getName()))
      return method.invoke(obj, args);
    else
      return proxy.invokeSuper(obj, args);
    }
  }

【问题讨论】:

    标签: java java-bytecode-asm cglib


    【解决方案1】:

    你所描述的听起来像一个 mixin 模式。你不能简单地明确地实现一个委托吗?比如:

    class BImpl implements B, A {
    
      private A a;
    
      public BImpl(A a) {
        this.a = a;
      }
    
      @Override
      public String cellValue() {
        return value() + "MyBCell";
      }
    
      @Override
      public String value() {
        return a.value();
      }
    }
    

    这应该是可能的,因为你说你在编译期间知道A

    否则,如果您确实需要在运行时执行此操作,那么您的方法可能是 cglib 的正确方法。但是,您需要在调用时为 obj 提供不同的实例:

    return method.invoke(obj, args);
    

    否则你再次调用被拦截的方法,发现自己在循环中点击MyMethodInterceptor会陷入死循环。你也可以safe yourself the branch and use a CallbkackFilter instead

    如果你没有绑定 cglib,你也可以查看我的库 Byte Buddy,这会让这一切更具表现力:

    new ByteBuddy()
      .subclass(BImpl.class)
      .method(isAnnotatedBy(A.class))
      .intercept(Forwarding.to("a", A.class))
      .make();
    

    生成的类现在有一个字段a,您可以将其设置为任何A 的实例,A 接口方法的方法调用现在委托给该实例。您可以通过例如使用 Java 反射来设置此字段。否则,您可以使用static 字段

    Forwarding.to(new A() {
      // A methods
    }); 
    

    【讨论】:

      猜你喜欢
      • 2019-10-07
      • 2013-12-05
      • 2013-06-30
      • 2011-08-21
      • 1970-01-01
      • 1970-01-01
      • 2019-10-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多