在这里,我需要创建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);
}
}
最佳答案
您所描述的听起来像是混音模式。您不能简单地明确实现委托吗?就像是:
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
});