Print
Nuts Lifecycle

Simple lifecycle

Lifecycle in Nuts is simple. The <ctor>, <bean>, <method> tags can have the following attributes:

  • initializer. The method to use to initialize the component instance. This method is called before the instance is wired to any other component instance.
  • starter. The method to start up the component instance.
  • stopper. The method to stop the component instance.
  • disposer. The method to dispose of the component instance.

For example:

<ctor class="Vehicle" initializer="init" disposer="destroy" starter="start" stopper="stop">
  <args>
    <value val="Jaguar"/>
  <args>
</ctor>

Note:

Nuts lifecycle manages both singleton and prototype components. Lifecycle for instances of prototype components are managed exactly the same way as those of the singleton components.

Singleton or not, lifecycle management is not concerned at all.

Advanced Lifecycle

The simple declarative lifecycle support is normally enough. But if you do need more exotic life cycle support, the <lifecycle> tag can be used.

For example, my disposer is not a parameter-less method in the object itself. Rather, I need to call CarManager.destroyCar(car) to dispose of a car.

Using <lifecycle> together with <sequence>, we can declare arbitrary number of life cycle callback entries for a component.

The following configuration declares "starter", "stopper" and "disposer" life cycle for the target component:

<sequence id="component with exotic lifecycle">
  <bean var="target" class="Car" props="..."/>
  <lifecycle name="starter">
    <method class="CarManager" name="startCar" args="$target"/>
  </lifecycle>
  <lifecycle name="stopper">
    <method class="CarManager" name="stopCar" args="$target"/>
  </lifecycle>
  <lifecycle name="disposer">
    <method class="CarManager" name="destroyCar" args="$target"/>
  </lifecycle>
  <return val="$target"/>
</sequence>

This tells Nuts that "CarManager.startCar(car)" is called for starting the car. "CarManager.destroyCar(car)" is called to dispose of the car, etc.

This example only demonstrated using inner component as the lifecycle callback. It is sometimes more convenient though to refer to a variable. For example, we could define a "destroyer" component in the local scope, which is then referenced in the <lifecycle> tag.

<local>
  <method id="destroyer" .../>
</local>
<lifecycle name="disposer" component="$destroyer"/>

Reentrant or Not

By default, "starter" and "stopper" are re-entrant. That means, when "DefaultLifecycleManager.start()" and "DefaultLifecycleManager.stop()" are called repeatedly, the starter method and the stopper method are also called repeatedly.

In contrast, "disposer" is non-reentrant. which mean even if "DefaultLifecycleManager.dispose()" is called more than once, the "disposer" method is guaranteed to be executed once and only once.

When this default behavior is not desirable, the "reentrant" attribute can be used to explicitly tell Nuts whether reentrance is allowed. For example, the following configuration prevents Nuts from calling "stopCar" for more than once:

<lifecycle name="stopper" reentrant="false">
  <method class="CarManager" name="stopCar" args="$target"/>
</lifecycle>
Powered by Atlassian Confluence