我正在尝试编写类似于工作单元的东西来跟踪更改,尽管它非常特定于某些生成的代码。
我有以下 ByteBuddy 代码
private Class<? extends Group> getTrackedClass(GroupChangeTrackingProxy trackingProxy) {
return new ByteBuddy()
.subclass(Group.class)
.method(ElementMatchers.isSetter())
.intercept(InvocationHandlerAdapter.of(new GroupChangeTrackingProxy()))
.make()
.load(CustomerPlatformGroupsRepositoryImpl.class.getClassLoader())
.getLoaded();
}
public class GroupChangeTrackingProxy implements InvocationHandler {
private final Logger log = LogManager.getLogger(GroupChangeTrackingProxy.class);
private final GroupModifications target = new GroupModifications();
private final AtomicBoolean tracking = new AtomicBoolean(false);
public GroupModifications getTarget() {
return target;
}
public void setTrack(boolean bool) {
this.tracking.setPlain(bool);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
if (tracking.get()) {
var match = ReflectionUtils.findMethod(GroupModifications.class, method.getName());
if (match != null) {
ReflectionUtils.invokeMethod(match, target, args);
log.debug(
"tracking: '{}.{}({})'",
() -> proxy.getClass().getSimpleName(),
method::getName,
() -> args);
}
}
// RECURSIVE!!!!
ReflectionUtils.invokeMethod(method, proxy, args);
return null; // should be void methods anyways
}
}
我们必须将返回的信息复制到我们跟踪的代理中,然后开始跟踪
private Group track(Group value) {
var tracker = new GroupChangeTrackingProxy();
var clazz = getTrackedClass(tracker);
var tracked = createInstanceOf(clazz);
this.copier.copy(value, tracked);
tracker.setTrack(true);
return tracked;
}
这个实现的问题是它最终是一个递归调用。我可以避免使用 spring
ReflectionUtils
和 InvocationHandler
,但我找不到从 Byte Buddy 获取方法名称的方法。
如何在没有递归问题的情况下做到这一点?
我在这个问题中找到了答案。
本质上就是这些注释
public void invoke(
@This Object proxy, @SuperMethod Method method, @AllArguments Object[] args)
然后更改 bytebuddy 的设置方式
.intercept(MethodDelegation.to(new GroupChangeTrackingProxy()))