当前位置: 首页 > 知识库问答 >
问题:

ByteBuddy拦截setter和调用方法,参数取决于调用setter方法的对象

华化
2023-03-14

我想截取在一个类的所有实例上调用的每个setter方法,然后在另一个类对象上调用一个方法,参数对应于第一个类的每个实例的一些字段值。为此,我想使用ByteBuddy API,但我也想为指定类的所有实例只创建一个子类

例如,我编写了以下代码:

public final class AttributesIntercepted<T> {

    private static EnumMap<ResourceType, Class> attributesClasses = new EnumMap<>(ResourceType.class);

    private Target target;
    private T attributes;
    private Resource resource;

    private AttributesIntercepted(T attributes, Target target, Resource resource) {
        this.attributes = attributes;
        this.target = target;
        this.resource = resource;
    }

    private T makeInstance() {
        T instance = null;
        try {
            Class subClass;
            if (!attributesClasses.containsKey(resource.getType())) {
                subClass = new ByteBuddy()
                        .subclass(attributes.getClass())
                        .method(ElementMatchers.isSetter())
                        .intercept(SuperMethodCall.INSTANCE.andThen(
                                MethodCall.invoke(target.getClass().getMethod("updateResource", Resource.class))
                                        .on(target)
                                        .with(resource)
                        )).make()
                        .load(attributes.getClass().getClassLoader())
                        .getLoaded();
                attributesClasses.put(resource.getType(), subClass);
            } else {
                subClass = attributesClasses.get(resource.getType());
            }

            // create the new instance of this subclass
            instance = (T) (subClass.getDeclaredConstructor(attributes.getClass()).newInstance(attributes));
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
System.out.println(e.toString());
        }

        return instance;
    }

    public static<T> T create(T attributes, Target target, Resource resource) {
        return (T) (new AttributesIntercepted(attributes, target, resource).makeInstance());
    }
}

我将为每个资源类型创建的每个子类保存在映射中,以便为每个资源类型只创建一个子类。这里的问题是,对于创建的子类的所有实例,传递给在目标对象上调用的方法“updateResource”的参数“resource”的值将始终相同。似乎传递给目标对象的参数是在创建子类时计算的,而不是在调用setter时计算的

如果我只是在注释中添加将子类保存在html" target="_blank">map中的代码,它是有效的,但是,正如我所说,我只想为每种资源类型创建一个子类......

谢谢你的帮助

共有1个答案

漆雕奇逸
2023-03-14

你应该使用Byte Buddy的类型缓存,避免使用你自己的解决方案,这将帮助你避免一些常见问题。

至于拦截:在DSL中使用defineField为这些值定义字段。然后,不要在(目标)上执行,而是在字段(…)上执行 带字段(…) 。创建类之后,现在需要为创建的任何特定实例设置这些字段,这样就可以在所有情况下重用该类。

 类似资料:
  • 让我有一个这样的界面: 还有这样一个实现类: 现在我想使用bytebuddy创建一个拦截器/代理,它捕捉对setter的调用,存储更改后的值,并调用real方法。 最后,我想向拦截器/代理“询问”被调用的setter和更改的值。 我尝试了很多考虑也教程,但到目前为止,我发现没有工作的解决方案。也许有人可以帮助我。 这是拦截器: 以下是我当前的“测试”代码: 编辑:

  • 我不明白我做错了什么。我想使用JAXB解封一个xml,但是我注意到没有调用setter方法。我使用Java1.5。Attribute.java类中的Getters和Setters正常工作,但在Configuration.javaclass-Setter方法不调用。你能告诉我我错在哪里吗? 我的XML如下所示:

  • 问题内容: 我有这个代码 有什么方法可以在没有子类化或修改类且没有工厂的情况下拦截呼叫? 编辑:抱歉忘了提到这是在Android平台上。 问题答案: 您是否考虑过面向方面的编程,甚至还考虑过AspectJ?有关AspectJ / Android的信息,请参见此处和此处。

  • 给定一个,使用一个公共方法,第二个,使用一个私有方法。有没有可能用bytebuddy生成一个子类,该子类将调用私有方法,从实现的?这基本上会模拟JVM反射生成的MethodAccessor,它正是这样做的。 目前,我正在尝试使用以下方法调用: ,但它抱怨

  • 问题内容: 我需要使用反射调用类的setter方法,并且代码如下: 的是一个以及设置器方法如下: 运行此代码时,将引发A ,但是将setter方法参数类型更改为from时,将执行正常。有没有一种方法可以将setter方法的参数保持为超级类型,并且在从类中获取方法时仍无需手动指定参数的类型即可使用反射? 问题答案: 与其他答案相反,有一个非常简单的解决方案。请参阅。它为您提供了一种执行任意反射代码的

  • 问题内容: 我正在用python实现RESTful Web服务,并想通过拦截函数调用并记录其执行时间等方式来添加一些QOS记录功能。 基本上,我想到了所有其他服务都可以从中继承的类,该类会自动覆盖默认方法的实现,并将其包装在logger函数中。实现此目标的最佳方法是什么? 问题答案: 像这样吗 这暗示着在您的方法中添加装饰器(如果您愿意,也可以基于此创建一个显式装饰器): 当您现在尝试类似的方法: