@CascadeDispose
The @CascadeDispose annotation is used to mark fields that contain values that must
be disposed when the component is disposed. This is a short-hand way of cleaning up arez components and other
resources that have been created or are owned by the component when the component is disposed.
If the referenced value already uses liveness-managed disposal via
disposeOnDeactivate = true and should only be kept alive
while the owner is alive, prefer @AutoObserve. @CascadeDispose is for
ownership; @AutoObserve is for liveness.
If the target is an @ArezComponent configured with
disposeOnDeactivate = true then the annotation processor
will emit the suppressable warning Arez:ConflictingDisposeModel. Disposal should be managed either by liveness
or explicitly, but not both.
if the @CascadeDispose annotation did not exist, the component author would be responsible
for cleaning up the resource manually in a method annotated with @PreDispose.
An example using manual mechanisms for disposing a sub-resource of a component:
@ArezComponent
public abstract class MyService
{
@CascadeDispose
final MySubService _subService = MySubService.create();
@PreDispose
void preDispose()
{
Disposable.dispose( _subService );
}
...
}
Sometimes when the component author added a new sub-component, the component author would forget to add the
required dispose call in the @PreDispose annotated method. This resulted in a resource
leak an inevitably some amount of time was spent detecting and fixing the problem.
Alternatively the author can annotate the field with the @CascadeDispose annotation
and the annotation processor generates the code required for disposing the sub-component. In practice this
resulted in less time chasing down resource leaks and slightly less code to maintain. The only disadvantage
was that the fields have to be made non-private so that the generated sub-class can access the field.
For field visibility, prefer package access. The annotation processor emits suppressable warnings for public fields
and for protected fields unless the field is inherited from a parent class in a different package.
For example:
@ArezComponent
public abstract class MyService
{
@CascadeDispose
final MySubService _subService = MySubService.create();
...
}