A Trigger is a callback which allows a subscriber to be notified when a
property value changes.
If the user wishes to be able to remove a Trigger at some time after it
has been added, then either 1) the user has to keep the instance of the
Trigger that was added and use it when calling the remove method or 2) the
Trigger must implement the equals method and the Trigger used during the call
to the remove method must be equal to the original Trigger added.
Each non-persistent Trigger is wrapped in a
java.lang.ref.WeakReference, so that is can be garbage-collected. But this
means that the user had better keep a reference to the Trigger, otherwise it
will be removed (garbage collected) without the user knowing.
Persistent Triggers (those that refer to objects in their
#executemethod that will never be garbage-collected) are not wrapped in a
WeakReference.
What does all this mean, well, objects that might be garbage collected
that create a Trigger must keep a reference to the Trigger (otherwise the
Trigger will be garbage-collected out from under the object). A common usage
pattern is to implement the Trigger interface using an anonymous class -
anonymous classes are non-static classes when created in an instance object.
But, remember, the anonymous class instance holds a reference to the outer
instance object but not the other way around; the instance object does not
have an implicit reference to the anonymous class instance - the reference
must be explicit. And, if the anonymous Trigger is created with the
isPersistent method returning true, then, surprise, the outer instance object
will never be garbage collected!!!
Note that it is up to the creator of a set of triggers to make sure that
they are ordered correctly. This is done by either having order independent
Triggers (they all have the same phase) or by assigning phases to the
Triggers where primaries execute before secondary which execute before
tertiary.
If a finer level of execution order granularity is needed, then the
implementation should be changed so that the
#phase method returns
just some integer and it's up to the users to coordinate their values.