在这里,我需要创建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);
}
}
答案 0 :(得分:3)
您所描述的内容听起来像 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反射来设置此字段。否则,您可以使用{/ 1}}字段
static