我们正在寻找一种能够以高效的方式跟踪客户端POJO实例状态的解决方案。我们期望的是:每次在POJO上进行更改时,都使用setter进行此状态。我们创建了一个基于OGNL的观看/事件总线,当我们进行更改时,我们会将适当的OgnlChangeEvent
发送到我们的事件总线。
到目前为止,我们研究了AspectJ / cglib /对象图Diff解决方案,但它们都占用了太多的CPU时间。我们当前的解决方案基于Spring MethodInterceptor
,每次调用Getter方法时我们都会创建一个新的Proxy
实例。
此时我们开始关注代码生成解决方案,我们偶然发现了Byte Buddy。这个方向是正确的方法吗?我们是否可以生成一个新的Class
来扩展我们的客户端POJO状态并通知其OGNL前缀直到调用setter方法?
答案 0 :(得分:2)
Byte Buddy是一个代码生成工具,当然可以实现这样的解决方案。要创建拦截setter的类,可以编写如下代码:
new ByteBuddy()
.subclass(UserPojo.class)
.method(ElementMatchers.isSetter())
.intercept(MethodDelegation.to(MyInterceptor.class)
.andThen(SuperMethodCall.INSTANCE)
.make();
你会在哪里编写这样的拦截器:
public class MyInterceptor {
public static void intercept(Object value) {
// business logic comes here
}
}
这样,每次调用在原始代码之前触发的setter时,都可以添加一些代码。您还可以使用所有基本类型重载拦截方法,以避免对参数进行装箱。 Byte Buddy想出了为你做些什么。
然而,我对 performant 的意思感到困惑。上面的代码对我来说就像创建一个类一样:
class UserClass {
String value;
void setValue(String value) {
this.value = value;
}
}
class InstrumentedUserClass extends UserClass {
@Override
void setValue(String value) {
MyInterceptor.intercept(value);
super.setValue(value);
}
}
表现主要受intercept
方法中表现的影响。
最后,我不明白cglib如何不适合你,但是使用Spring - 它是在cglib之上构建 - 确实有效。我怀疑你应该调查你的拦截逻辑有一些问题。
答案 1 :(得分:1)
我认为性能并不依赖于您使用的字节码检测框架,而是取决于您在方法拦截器中执行的操作。最后你只知道你是否测量。
我对你的用例一无所知,但总的来说我会问自己:
您应该将基本数据收集与该数据的解释(信息)分开。通常解释需要更多时间。基本数据是无法从其他数据派生的数据。例如,生日是基本数据,而年龄是从生日得出的。
在方法拦截器中我会
后台工作人员可以例如解释方法名称以查明它是否是属性访问器。通常,您使用从BeanInfo或至少反射api获得的Introspector来执行此操作。