Object definitions act as the 'recipes' with which object instances are created and
configured. These are, naturally, a very important aspect of the entire Spring Actionscript
library. In these sections every property of the object definition is explained along with
examples of how to populate them using the various types of configuration. To learn more about
configurations, check the section 'Configuration
types'.
Determines the way an object will be autowired (configured). To learn more about
autowiring, check out the 'Autowiring'
section.
Determines if the object definition will be injected into child contexts. To learn more
about this, check out the 'Context children'
section.
The fully qualified classname of the object that the current object definition describes.
The Class of the object that the current object definition describes. This property will be set once the definition gets registered by an IObjectDefinitionsRegistry.
An array of arguments that will be passed to the constructor of the object when it gets instantiated by the application context.
Optional extra data that can be used by other processing logic. May also be an instance
of ICustomConfigurator
Describes an object that can perform custom configuration on an instance that cannot be expressed with an <code>IObjectDefinition</code>.
or an instance of
Vector.<ICustomConfigurator>. Learn more about this in the section
'Custom object definition
configurators'.
Spring Actionscript has 4 different validation modes to check if properties have been set on an object. The different dependency check modes are 'none', 'simple', 'object', and 'all'. The default mode is 'none', so there isn't any dependency check validation unless explicitly configured. All values being checked must have been set in the configuration file or by autowiring. If a class has any defaults or fields that don't need to be set, the dependency check modes won't be of any use.
| Mode | Explanation |
|---|---|
| none | No dependency checking. This is the default. |
| simple | Dependency check for primitives and collections. |
| object | Dependency check for objects (collaborators). |
| all | Dependency check for primitives, collections, and objects (collaborators). |
The 'simple' mode checks that all primitive and collection values have been set. The 'object' mode checks that all collaborators (objects) have been set. The 'all' mode checks for everything that the 'simple' and 'object' modes do.
For most situations, the fact that an object is a dependency of another is expressed by the fact that one object is set as a property of another. This is typically accomplished with the <ref/> element in XML-based configuration metadata. For the relatively infrequent situations where dependencies between objects are less direct, the 'depends-on' attribute may be used to explicitly force one or more objects to be initialized before the object using this element is initialized. Find below an example of using the 'depends-on' attribute to express a dependency on a single object.
<object id="objectOne" class="ExampleObject" depends-on="manager"/> <object id="manager" class="ManagerObject" />
Or in MXML configurations
<sas:Object id="objectOne" clazz="{ExampleObject}" dependsOn="{[manager]}"/> <sas:Object id="manager" clazz="{ManagerObject}" />
Or in metadata configurations
[Component(id="objectOne", dependsOn="manager")]If you need to express a dependency on multiple objects, you can supply a list of object names as the value of the 'depends-on' attribute, delimited by commas.
<object id="objectOne" class="ExampleObject" depends-on="manager,accountDao"> <property name="manager" ref="manager" /> </object> <object id="manager" class="ManagerObject" /> <object id="accountDao" class="x.y.as.AccountDao" />
In MXML configurations you simply pass in an Array of MXMLObjectDefinition <p>MXML representation of an <code>ObjectDefinition</code> object. This non-visual component must be declared as a child component of a <code>MXMLApplicationContext</code> component.</p> <p>Describes an object that can populate an IObjectDefinition instance with properties defined in MXML.</p> instances.
<sas:Object id="objectOne" class="ExampleObject" dependsOn="{[manager,accountDao]}"> <sas:Property name="manager" ref="{manager}" /> </sas:Object> <sas:Object id="manager" clazz="{ManagerObject}" /> <sas:Object id="accountDao" clazz="{AccountDao}" />
Or in metadata
[Component(id="objectOne", dependsOn="manager,accountDao")]Like the application context, also objects that are managed by the context may need to have a disposal method in which they are able to release any resources they are holding. There are two ways of letting the context know which methods need to be invoked on an object once the context itself is being disposed:
The IDisposable interface
The destroyMethod property on an object definition
The IDisposable interface is quite small, its signature look like this and is self-explanatory:
public interface IDisposable { function get isDisposed():Boolean; function dispose():void; }
If an object is encountered in the context that implements this interface its dispose() method will be invoked once the context itself is being disposed.
The IDisposable interface is part of the as3commons-lang library.
To avoid dependencies on any third-party interfaces the destroy (for the IDisposable interface this would be its dispose() method) method for an object can also be defined in its associated object definition like this:
<object class="..." destroy-method="release"/>
MXML configuration:
<sas:Object clazz="..." destroyMethod="release"/>
Metadata configuration:
[Component(id="objectOne",destroyMethod="release")]When defining an object which is to be created using a static factory method, along with the className property which specifies the class containing the static factory method, another property named factoryMethod is needed to specify the name of the factory method itself. Spring Actionscript expects to be able to call this method and get back a live object, which from that point on is treated as if it had been created normally via a constructor. One use for such an object definition is to call static factories in legacy code, but it can also be used to retrieve objects that have been instantiated in MXML and are later pulled into the IoC container to be configured.The following examples show an object definition which specifies that the object is to be created by calling a factoryMethod. Note that the definition does not specify the type (class) of the returned object, only the class containing the factory method. In this example, the getInstance() method must be a static method.
<object id="exampleObject" class="..." factory-method="getInstance"/>
MXML configuration:
<sas:Object id="exampleObject" clazz="..." factoryMethod="getInstance"/>
Metadata configuration:
[Component(id="exampleObject",factoryMethod="getInstance")]And for this the Actionscript equivalent would be:
var exampleObject:ExampleObject = ExampleObjectLocator.getInstance();
Using a factoryMethod property combined with the factoryObjectName property enables you to let a second object be responsible for instantiating the object using a static method.
<object id="exampleFactory" class="examples.ExampleObjectFactory"/> <object id="exampleObject" class="examples.Example" factory-object="exampleFactory" factory-method="getInstance"/>
MXML configuration:
<sas:Object id="exampleFactory" clazz="{ExampleObjectFactory}"/> <sas:Object id="exampleObject" clazz="{Example}" factoryObject="{exampleFactory}" factoryMethod="getInstance"/>
Metadata configuration:
[Component(id="exampleObject",factoryMethod="getInstance",factoryObjectName="exampleFactory")]Object definitions provide support for a generic initialization method to be specified. In the case of XML-based configuration metadata, this is done using the 'init-method' attribute. For example, the following definition:
<object id="exampleInitObject" class="examples.ExampleObject" init-method="init"/>
MXML configuration:
<sas:Object id="exampleInitObject" clazz="{ExampleObject}" initMethod="init"/>
Metadata configuration:
[Component(id="exampleInitObject",initMethod="init")]An object definition potentially contains a large amount of configuration information, including container specific information (for example initialization method, static factory method name, and so forth) and constructor arguments and property values. A child object definition is an object definition that inherits configuration data from a parent definition. It is then able to override some values, or add others, as needed. Using parent and child objects definitions can potentially save a lot of typing. Effectively, this is a form of templating.
When using XML-based configuration metadata a child object definition is indicated simply by using the 'parent' attribute, specifying the parent object as the value of this attribute.
<object id="inheritedTestObject" abstract="true" class="org.springactionscript.objects.TestObject"> <property name="name" value="parent"/> <property name="age" value="1"/> </object> <object id="inheritsWithDifferentClass" class="org.springactionscript.objects.DerivedTestObject" parent="inheritedTestObject" init-method="initialize"> <property name="name" value="override"/> <!-- the age property value of 1 will be inherited from parent --> </object>
A child object definition will use the object class from the parent definition if none is specified, but can also override it. In the latter case, the child object class must be compatible with the parent, that is it must accept the parent's property values.
A child object definition will inherit constructor argument values, property values and method overrides from the parent, with the option to add new values. If any init-method and/or static factory method settings are specified, they will override the corresponding parent settings.
The remaining settings will always be taken from the child definition: depends on, autowire mode, dependency check, singleton, scope, lazy init.
Note that in the example above, we have explicitly marked the parent object definition as abstract by using the abstract attribute. In the case that the parent definition does not specify a class, and so explicitly marking the parent object definition as abstract is required:
<object id="inheritedTestObject" abstract="true"> <property name="name" value="parent"/> <property name="age" value="1"/> </object> <object id="inheritsWithDifferentClass" class="org.springactionscript.objects.DerivedTestObject" parent="inheritedTestObject" init-method="initialize"> <property name="name" value="override"/> <!-- the age property value of 1 will be inherited from parent --> </object>
The parent object cannot get instantiated on its own since it is incomplete, and it is also explicitly marked as abstract. When a definition is defined to be abstract like this, it is usable only as a pure template object definition that will serve as a parent definition for child definitions. Trying to use such an abstract parent object on its own (by referring to it as a ref property of another object, or doing an explicit getObject() call with the parent object id), will result in an error. Similarly, the container's internal instantiateSingletons() method will completely ignore object definitions which are defined as abstract.
ApplicationContexts will by default pre-instantiate all singletons. Therefore it is important (at least for singleton objects) that if you have a (parent) object definition which you intend to use only as a template, and this definition specifies a class, you must make sure to set the 'abstract' attribute to 'true', otherwise the application context will actually (attempt to) pre-instantiate the abstract object.
MXML configuration:
<sas:Object id="inheritedTestObject" isAbstract="true"> <sas:Property name="name" value="parent"/> <sas:Property name="age" value="1"/> </sas:Object> <sas:Object id="inheritsWithDifferentClass" clazz="{DerivedTestObject}" parentName="inheritedTestObject" initMethod="initialize"> <sas:Property name="name" value="override"/> <!-- the age property value of 1 will be inherited from parent --> </sas:Object>
Metadata configuration:
[Component(id="inheritingObject",isAbstract="true")] [Component(id="inheritsWithDifferentClass",parentName="inheritedTestObject")]
True if this object can be used as a value used by the container when it autowires an
object by type. To learn more about autowiring, check out the 'Autowiring' section.
Another way of defining object configurations is by using the interfaces they might implement. Imagine several classes implementing the same interface, if only one interface is implemented then using an object definition with an 'abstract="true"' attribute and having all implementing object definitions refer to this definition with their 'parent' attribute would suffice, even a template would do.
However, when multiple interfaces are being implemented is when you hit the limitations of these configuration options.
In this case the <interface/> element might be able to help you out and in this section we will explain how. Let's make up two simple interfaces for this example:
public interface ISimpleInterface { function get myStringProperty():String; function set myStringProperty(value:String):void; }
public interface ISimpleInitializingInterface { function initialize():void; }
These interfaces can be configured in the XML configuration like this:
<interface class="com.mycompany.interfaces.ISimpleInterface"> <property name="myStringProperty" value="This is my test value!"/> </interface> <interface class="com.mycompany.interfaces.ISimpleInitializingInterface"> <method-invocation name=initialize"/> </interface>
Now, imagine creating a class that implements the aforementioned ISimpleInterface:
public class MySimpleClass implements ISimpleInterface {
//implementation omitted
}To configure this object in your XML markup all you need to do is declare the object:
<object id="mySimpleInstance" class="com.mycompany.classes.MySimpleClass"/>
Afterwards Spring Actionscript will take care of combining the configurations for the implemented interfaces with your object definition.This works for multiple interfaces as well, so another class that would implement both interfaces. Say, something like this:
public class MySimpleInitializingClass implements ISimpleInterface, ISimpleInitializingInterface {
//implementation omitted
}To receive a fully configured instance of this object, all you need to do again is simply declare the object like this:
<object id="mySimpleInitialzingInstance" class="com.mycompany.classes.MySimpleInitializingClass"/>
And in this case Spring Actionscript will have combined the configurations for the ISimpleInterface and ISimpleInitializingInterface and added it to the mySimpleInitialzingInstance configuration.
MXML configuration:
<sas:Interface clazz="{ISimpleInterface}"> <sas:Property name="myStringProperty" value="This is my test value!"/> </sas:Interface> <sas:Interface clazz="{ISimpleInitializingInterface}"> <sas:MethodInvocation name=initialize"/> </sas:Interface>
The metadata configuration is the most straightforward, all you do is annotate an interface in the same way you annotate a class and that's it.
[Component] public interface ISimpleInterface { [Property(value="This is my test value")] function get myStringProperty():String; function set myStringProperty(value:String):void; }
[Component]
public interface ISimpleInitializingInterface {
[Invoke]
function initialize():void;
}The default behavior for IApplicationContext implementations is to eagerly pre-instantiate all singleton objects at startup. Pre-instantiation means that an IApplicationContext will eagerly create and configure all of its singleton objects as part of its initialization process. Generally this is a good thing, because it means that any errors in the configuration or in the surrounding environment will be discovered immediately (as opposed to possibly hours down the line).
However, there are times when this behavior is not what is desired. If you do not want a singleton object to be pre-instantiated when using an IApplicationContext, you can selectively control this by marking an object definition as lazily-initialized. A lazily-initialized object indicates to the IoC container whether or not an object instance should be created at startup or when it is first requested.
When configuring objects via XML, this lazy loading is controlled by the 'lazy-init' attribute on the <object/> element; for example:
<object id="lazy" class="com.foo.ExpensiveToCreateObject" lazy-init="true"/> <object name="not.lazy" class="com.foo.AnotherObject"/>
MXML configuration:
<sas:Object id="lazy" clazz="{ExpensiveToCreateObject}" lazyInit="true"/>
<sas:Object name="not.lazy" clazz="{AnotherObject}"/>Metadata configuration:
[Component(id="lazy",lazyInit="true")]When the above configuration is consumed by an IApplicationContext , the object named 'lazy' will not be eagerly pre-instantiated when the IApplicationContext is starting up, whereas the 'not.lazy' object will be eagerly pre-instantiated.
One thing to understand about lazy-initialization is that even though an object definition may be marked up as being lazy-initialized, if the lazy-initialized object is the dependency of a singleton object that is not lazy-initialized, when the IApplicationContext is eagerly pre-instantiating the singleton, it will have to satisfy all of the singletons dependencies, one of which will be the lazy-initialized object! So don't be confused if the IoC container creates one of the objects that you have explicitly configured as lazy-initialized at startup; all that means is that the lazy-initialized object is being injected into a non-lazy-initialized singleton object elsewhere.
True if only one instance of this object needs to be created by the container, i.e.
every subsequent call to the getObject() method will
return the same instance. See the section 'scope' for
more information.
An object definition whose properties and method invocations will be inherited by the
current definition. Check out the 'isAbstract'
section for more information.
The name of an object Definition whose properties and method invocations will be
inherited by the current definition. Check out the 'isAbstract' section for more information.
True if this object needs to be used as the primary autowire candidate when the
container is autowiring by type. This means that if multiple objects are found of the same
type, the object marked as 'primary' will become the
autowire candidate. To learn more about autowiring, check out the 'Autowiring' section.
When you create an object definition what you are actually creating is a recipe for creating actual instances of the class defined by that object definition. The idea that an object definition is a recipe is important, because it means that, just like a class, you can potentially have many object instances created from a single recipe.
You can control not only the various dependencies and configuration values that are to be plugged into an object that is created from a particular object definition, but also the scope of the objects created from a particular object definition. This approach is very powerful and gives you the flexibility to choose the scope of the objects you create through configuration instead of having to 'bake in' the scope of an object at the Actionscript class level. Objects can be defined to be deployed in one of a number of scopes: out of the box, Spring Actionscript supports exactly two scopes.
The scopes supported out of the box are listed below:
| Scope | Description |
|---|---|
| singleton | Scopes a single object definition to a single object instance per Spring Actionscript IoC container. |
| prototype | Scopes a single object definition to any number of object instances. |
When an object is a singleton, only one shared instance of the object will be managed, and all requests for objects with an id matching that object definition will result in that one specific object instance being returned by the Spring Actionscript container.
To put it another way, when you define an object definition and it is scoped as a singleton, then the Spring Actionscript IoC container will create exactly one instance of the object defined by that object definition. This single instance will be stored in a cache of such singleton objects, and all subsequent requests and references for that named object will result in the cached object being returned.
Please be aware that Spring Actionscript's concept of a singleton object is quite different from the Singleton pattern as defined in the seminal Gang of Four (GoF) patterns book. The GoF Singleton hard codes the scope of an object such that one and only one instance of a particular class will ever be created. The scope of the Spring Actionscript singleton is best described as per container and per object. This means that if you define one object for a particular class in a single Spring Actionscript container, then the Spring Actionscript container will create one and only one instance of the class defined by that object definition. The singleton scope is the default scope in Spring Actionscript. To define an object as a singleton in XML, you would write configuration like so:
<object id="accountService" class="com.foo.DefaultAccountService"/> <!-- the following is equivalent, though redundant (singleton scope is the default) --> <object id="accountService" class="com.foo.DefaultAccountService" scope="singleton"/> <!-- the following is equivalent and preserved for backward compatibility --> <object id="accountService" class="com.foo.DefaultAccountService" singleton="true"/>
MXML configuration:
<sas:Object id="accountService" clazz="{DefaultAccountService}"/> <!-- the following is equivalent, though redundant (singleton scope is the default) --> <sas:Object id="accountService" clazz="{DefaultAccountService}" scope="singleton"/> <!-- the following is equivalent and preserved for backward compatibility --> <sas:Object id="accountService" clazz="{DefaultAccountService}" isSingleton="true"/>
Metadata configuration:
[Component(id="accountService")] [Component(id="accountService",scope="singleton")] [Component(id="accountService",isSingleton="true")]
The non-singleton, prototype scope of object deployment results in the creation of a new object instance every time a request for that specific object is made (that is, it is injected into another object or it is requested via a programmatic getObject() method call on the container). As a rule of thumb, you should use the prototype scope for all objecs that are stateful, while the singleton scope should be used for stateless objects.
To define an object as a prototype in XML, you would write configuration like so:
<!-- recommended markup --> <object id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/> <!-- the following is equivalent and preserved for backward compatibility --> <object id="accountService" class="com.foo.DefaultAccountService" singleton="false"/>
MXML configuration:
<!-- recommended markup -->
<sas:Object id="accountService" clazz="{DefaultAccountService}" scope="prototype"/>
<!-- the following is equivalent and preserved for backward compatibility -->
<sas:Object id="accountService" clazz="{DefaultAccountService}" isSingleton="false"/>Metadata configuration:
[Component(id="accountService",scope="prototype")] [Component(id="accountService",isSingleton="false")]
When using singleton-scoped objects that have dependencies on objects that are scoped as prototypes, please be aware that dependencies are resolved at instantiation time. This means that if you dependency inject a prototype-scoped object into a singleton-scoped object, a brand new prototype object will be instantiated and then dependency injected into the singleton object... but that is all. That exact same prototype instance will be the sole instance that is ever supplied to the singleton-scoped object, which is fine if that is what you want.
However, sometimes what you actually want is for the singleton-scoped object to be able to acquire a brand new instance of the prototype-scoped bean again and again and again at runtime. In that case it is no use just dependency injecting a prototype-scoped object into your singleton object, because as explained above, that only happens once when the Spring Actionscript container is instantiating the singleton object and resolving and injecting its dependencies.
Determines whether the autowire processor will examine the class for the existence of
[Inject] or [Autowire]
metadata. To learn more about autowiring, check out the 'Autowiring' section.
Determines whether the application context will send the created object through its list
of object postprocessors. To learn more about object postprocessors, check out the 'Object post-processors' section.