在Java中,如何构造一个“代理包装器”? 围绕一个在更改属性时调用方法的对象?

发布于 2024-07-12 13:10:36 字数 921 浏览 8 评论 0原文

我正在寻找类似于 代理模式动态代理类,只是我不想在方法调用之前拦截它们在真实对象上调用,但我想拦截正在更改的属性。 我希望代理能够表示具有不同属性集的多个对象。 Action Script 3 中的 Proxy 类 会没事的。

这就是我一般想要实现的目标:

我有一个线程运行一个对象,该对象管理由程序中的其他线程移交的值列表(数字、字符串、对象),因此该类可以负责创建常规值磁盘上的持久快照,用于对应用程序进行检查点。 该持久化对象管理一个“脏”标志,该标志表示值列表自上一个检查点以来是否已更改,并且需要在忙于将列表写入磁盘时锁定该列表。

持久化器和其他组件通过通用名称来标识特定项目,以便从崩溃中恢复时,其他组件可以首先检查持久化器是否已保存其最新副本,并从中断处继续工作。

在正常操作期间,为了使用他们移交给持久化器的对象,我希望他们接收对代理对象的引用,该代理对象看起来就像原始对象一样,但是每当他们更改其上的某些值时,持久化器就会注意到并采取相应的行动,例如在实际设置实际值之前将项目或列表标记为脏。


编辑:或者,Java 中是否有通用设置器(如 PHP 5),即如果属性不存在则调用的方法? 或者是否有一种类型的对象可以在运行时添加属性?

I'm looking for something similar to the Proxy pattern or the Dynamic Proxy Classes, only that I don't want to intercept method calls before they are invoked on the real object, but rather I'd like to intercept properties that are being changed. I'd like the proxy to be able to represent multiple objects with different sets of properties. Something like the Proxy class in Action Script 3 would be fine.

Here's what I want to achieve in general:

I have a thread running with an object that manages a list of values (numbers, strings, objects) which were handed over by other threads in the program, so the class can take care of creating regular persistent snapshots on disk for the purpose of checkpointing the application. This persistor object manages a "dirty" flag that signifies whether the list of values has changed since the last checkpoint and needs to lock the list while it's busy writing it to disk.

The persistor and the other components identify a particular item via a common name, so that when recovering from a crash, the other components can first check if the persistor has their latest copy saved and continue working where they left off.

During normal operation, in order to work with the objects they handed over to the persistor, I want them to receive a reference to a proxy object that looks as if it were the original one, but whenever they change some value on it, the persistor notices and acts accordingly, for example by marking the item or the list as dirty before actually setting the real value.


Edit: Alternatively, are there generic setters (like in PHP 5) in Java, that is, a method that gets called if a property doesn't exist? Or is there a type of object that I can add properties to at runtime?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

公布 2024-07-19 13:10:36

如果“属性”指的是 JavaBean 属性,即表示 getter 和/或 setter 方法,那么您可以使用动态代理来拦截 set 方法。

如果你指的是实例变量,那么就没有办法——在 Java 级别上不行。 也许可以通过字节码级别的操作来完成一些事情。

实际上,最简单的方法可能是使用 AspectJ 并定义一个 set() 切入点(这将拦截字节码级别的字段访问)。

If with "properties" you mean JavaBean properties, i.e. represented bay a getter and/or a setter method, then you can use a dynamic proxy to intercept the set method.

If you mean instance variables, then no can do - not on the Java level. Perhaps something could be done by manipulations on the byte code level though.

Actually, the easiest way to do it is probably by using AspectJ and defining a set() pointcut (which will intercept the field access on the byte code level).

白况 2024-07-19 13:10:36

您正在寻找的设计模式是:差异执行。 我相信。

差异执行是如何工作的?

我回答的一个问题与此有关。

但是,我可以建议您改用回调吗? 您将必须阅读有关此内容的内容,但总体思路是您可以实现在“有趣的事情”发生时激活的接口(通常称为侦听器)。 比如改变数据结构。

强制链接:

Wiki 差异执行

Wiki Callback

好吧,这是我看到的答案。 差分执行的时间为 O(N)。 这确实很合理,但如果这对你不起作用,回调会。 回调基本上是通过将方法按参数传递给正在更改数组的类来工作的。 此方法将获取更改的值和项目的位置,通过参数将其传递回“存储类”并适当地更改值。 所以,是的,您必须通过方法调用来支持每个更改。

我现在意识到这不是你想要的。 看来您想要的是一种可以为数组中的每个变量提供某种侦听器的方法,该侦听器将在该项目更改时被调用。 然后,侦听器将更改“备份”中相应的数组以反映此更改。

我本身想不出一种方法来做到这一点。 当然,您可以使用接口创建自己的侦听器和事件。 这基本上与回调的想法相同,尽管看起来更好。

然后是反射...Java 具有反射,我确信您可以使用它编写一些东西来做到这一点。 然而,反射速度是出了名的慢。 更不用说编码的痛苦(在我看来)。

希望有帮助...

The design pattern you are looking for is: Differential Execution. I do believe.

How does differential execution work?

Is a question I answered that deals with this.

However, may I suggest that you use a callback instead? You will have to read about this, but the general idea is that you can implement interfaces (often called listeners) that active upon "something interesting" happening. Such as having a data structure be changed.

Obligitory links:

Wiki Differential execution

Wiki Callback

Alright, here is the answer as I see it. Differential Execution is O(N) time. This is really reasonable, but if that doesn't work for ya Callbacks will. Callbacks basically work by passing a method by parameter to your class that is changing the array. This method will take the value changed and the location of the item, pass it back by parameter to the "storage class" and change the value approipriately. So, yes, you have to back each change with a method call.

I realize now this is not what you want. What it appears that you want is a way that you can supply some kind of listener on each variable in an array that would be called when that item is changed. The listener would then change the corresponding array in your "backup" to refect this change.

Natively I can't think of a way to do this. You can, of course, create your own listeners and events, using an interface. This is basically the same idea as the callbacks, though nicer to look at.

Then there is reflection... Java has reflection, and I am positive you can write something using it to do this. However, reflection is notoriously slow. Not to mention a pain to code (in my opinion).

Hope that helps...

烈酒灼喉 2024-07-19 13:10:36

我不想在实际对象上调用方法调用之前拦截它们,但是
相反,我想拦截正在更改的属性

所以事实上,您想要监视的对象不是方便的 bean,而是 C 结构的复兴。 我想到的唯一方法是使用 JVMTI 中的字段访问调用

I don't want to intercept method calls before they are invoked on the real object, but
rather I'd like to intercept properties that are being changed

So in fact, the objects you want to monitor are no convenient beans but a resurgence of C structs. The only way that comes to my mind to do that is with the Field Access call in JVMTI.

源来凯始玺欢你 2024-07-19 13:10:36

我自己也想做同样的事情。 我的解决方案是使用 Javassist 来使用动态代理包装器。 我将生成一个实现与目标对象的类相同的接口的类,将代理类包装在原始类周围,并将代理上的所有方法调用委托给原始类,除了也会触发 PropertyChangeEvent 的 setter 之外。

无论如何,我在我的博客上发布了完整的解释和代码:
http://clockwork-fig.blogspot.com /2010/11/javabean-property-change-listener-with.html

I wanted to do the same thing myself. My solution was to use dynamic proxy wrappers using Javassist. I would generate a class that implements the same interface as the class of my target object, wrap my proxy class around original class, and delegate all method calls on proxy to the original, except setters which would also fire the PropertyChangeEvent.

Anyway I posted the full explanation and the code on my blog here:
http://clockwork-fig.blogspot.com/2010/11/javabean-property-change-listener-with.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文