This chapter covers the Spring Actionscript Framework's implementation of the Inversion of Control (IoC) principle.
The org.springextensions.actionscript.context and org.springextensions.actionscript.ioc.factory.xml packages provide the basis for the Spring Actionscript Framework's IoC container.
The FlexXMLApplicationContext Extension of <code>XMLApplicationContext</code> that supports flex framework specific classes like <code>ArrayCollection</code>. or XMLApplicationContext The <code>XMLApplicationContext</code> is the object factory used in ActionScript projects, in Flex projects you want to use the <code>FlexXMLApplicationContext</code> class. are the classes that any programmer starting out with Spring Actionscript will encounter as the first pieces of code from the framework that they will need to use. The classes are nearly identical, FlexXMLApplicationContext Extension of <code>XMLApplicationContext</code> that supports flex framework specific classes like <code>ArrayCollection</code>. only adds Flex specific support, such as for the ArrayCollection.
These classes take care of loading and parsing of a configuration file, after which they are able to instantiate, assemble and otherwise manage objects.
In this chapter we are going to describe how to set up a configuration file, create an application context and use it to instantiate objects.
The objects that are managed by the Spring Actionscript IoC container, and the dependencies between them, are reflected in the configuration metadata used by a container.
The FlexXMLApplicationContext Extension of <code>XMLApplicationContext</code> that supports flex framework specific classes like <code>ArrayCollection</code>. or XMLApplicationContext The <code>XMLApplicationContext</code> is the object factory used in ActionScript projects, in Flex projects you want to use the <code>FlexXMLApplicationContext</code> class. classes are the central IoC container objects in Spring Actionscript. Their responsibilities include instantiating or sourcing application objects, configuring such objects, and assembling the dependencies between these objects.
They inherit from XMLObjectFactory which allows you to express the objects that compose your application, and the doubtless rich interdependencies between such objects, in terms of XML. The XMLObjectFactory takes this XML configuration metadata and uses it to create a fully configured system or application.
So what does this mean in plain English?
An instance of FlexXMLApplicationContext Extension of <code>XMLApplicationContext</code> that supports flex framework specific classes like <code>ArrayCollection</code>. or XMLApplicationContext The <code>XMLApplicationContext</code> is the object factory used in ActionScript projects, in Flex projects you want to use the <code>FlexXMLApplicationContext</code> class. can read an XML file containing a description of the dependencies of your business objects and manage these dependencies. Do all your business object need a reference to your model? But you want to be certain that they all receive the same reference without having to depend on a singleton object?
This is where the IoC container comes in.
Spring Actionscript supports configurations defined in XML or MXML. When using XML-based configuration metadata, you write object definitions for those objects that you want the Spring Actionscript IoC container to manage, and then let the container do its stuff. Spring Actionscript configuration consists of at least one object definition that the container must manage, but typically there will be more than one object definition. These object definitions are configured as <object/> elements inside a top-level <objects/> element.
(See Composing MXML based configuration metadata for how to perform this task using MXML instead).
These object definitions correspond to the actual objects that make up your application, they describe how these objects need to be instantiated and configured.
Find below an example of the basic structure of XML-based configuration metadata.
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springactionscript.org/schema/objects"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springactionscript.org/schema/objects
http://www.springactionscript.org/schema/objects/spring-actionscript-objects-1.0.xsd">
<object id="..." class="...">
<!-- collaborators and configuration for this object go here -->
</object>
<object id="..." class="...">
<!-- collaborators and configuration for this object go here -->
</object>
<!-- more object definitions go here -->
</objects>Instantiating a Spring Actionscript IoC container is straightforward.
var applicationContext:XMLApplicationContext The <code>XMLApplicationContext</code> is the object factory used in ActionScript projects, in Flex projects you want to use the <code>FlexXMLApplicationContext</code> class. = new XMLApplicationContext The <code>XMLApplicationContext</code> is the object factory used in ActionScript projects, in Flex projects you want to use the <code>FlexXMLApplicationContext</code> class.(); applicationContext.addConfigLocation("application-context.xml"); applicationContext.addEventListener(Event.COMPLETE, handleComplete); applicationContext.load();
The application-xml file in the above listing resides either on a remote server or a local file. Depending on the application in question being a Flex/Flash or AIR application. Either way, the XML file is being loaded using a URLLoader object. This means that this operation is asynchronous i.e. The application can't know beforehand when this it is finished. Hence the addEventListener call: once container has fully loaded the XML file and has successfully parsed it, the complete event is fired and the handleComplete method will be called.
To avoid hard coding the URL to the configuration file in the application source it is recommended to pass this a flashvar into the Flex application. These flashvars can be defined in Flex Builder in the HTML template. This template can be found in the project directory root and is called html-template. In this directory is resides a file called index.template.html.
Below is an example of how a flashvar defining the application-context.xml location, this example shows all the code between the <body> tag of the template. The relevant pieces of code have been marked in bold.
<script language="JavaScript" type="text/javascript"> <!-- // Version check for the Flash Player that has the ability to start Player Product Install (6.0r65) var hasProductInstall = DetectFlashVer(6, 0, 65); // Version check based upon the values defined in globals var hasRequestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision); if ( hasProductInstall && !hasRequestedVersion ) { // DO NOT MODIFY THE FOLLOWING FOUR LINES // Location visited after installation is complete if installation is required var MMPlayerType = (isIE == true) ? "ActiveX" : "PlugIn"; var MMredirectURL = window.location; document.title = document.title.slice(0, 47) + " - Flash Player Installation"; var MMdoctitle = document.title; AC_FL_RunContent( "src", "playerProductInstall", "FlashVars", "MMredirectURL="+MMredirectURL+'&MMplayerType='+MMPlayerType+'&MMdoctitle='+MMdoctitle+"", "width", "${width}", "height", "${height}", "align", "middle", "id", "${application}", "quality", "high", "bgcolor", "${bgcolor}", "name", "${application}", "allowScriptAccess","sameDomain", "type", "application/x-shockwave-flash", "pluginspage", "http://www.adobe.com/go/getflashplayer" ); } else if (hasRequestedVersion) { // if we've detected an acceptable version // embed the Flash Content SWF when all tests are passed AC_FL_RunContent( "src", "${swf}", "FlashVars", "ContextURL=application-context.xml", "width", "${width}", "height", "${height}", "align", "middle", "id", "${application}", "quality", "high", "bgcolor", "${bgcolor}", "name", "${application}", "allowScriptAccess","sameDomain", "type", "application/x-shockwave-flash", "pluginspage", "http://www.adobe.com/go/getflashplayer" ); } else { // flash is too old or we can't detect the plugin var alternateContent = 'Alternate HTML content should be placed here. ' + 'This content requires the Adobe Flash Player. ' + '<a href=http://www.adobe.com/go/getflash/>Get Flash</a>'; document.write(alternateContent); // insert non-flash content } // --> </script> <noscript> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="${application}" width="${width}" height="${height}" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"> <param name="FlashVars" value="ContextURL=application-context.xml" /> <param name="movie" value="${swf}.swf" /> <param name="quality" value="high" /> <param name="bgcolor" value="${bgcolor}" /> <param name="allowScriptAccess" value="sameDomain" /> <embed src="${swf}.swf" quality="high" bgcolor="${bgcolor}" width="${width}" height="${height}" name="${application}" align="middle" play="true" loop="false" quality="high" flashvars="ContextURL=application-context.xml" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer"> </embed> </object> </noscript>
To access the flashvar parameters add an eventhandler for the preinitialize event in your application, like so:
addEventListener(FlexEvent.PREINITIALIZE,handlePreInit);
or in MXML:
<mx:Application preinitialize="handlePreInit(event)"/>
Then in the event handling method retrieve the flashvar parameter like this:
private function handlePreInit(event:FlexEvent):void {
_contextURL = parameters['ContextURL'];
}Then later on the context URL can be fed to the application context instance again:
var applicationContext:XMLApplicationContext TheXMLApplicationContextis the object factory used in ActionScript projects, in Flex projects you want to use theFlexXMLApplicationContextclass. = new XMLApplicationContext TheXMLApplicationContextis the object factory used in ActionScript projects, in Flex projects you want to use theFlexXMLApplicationContextclass.(); applicationContext.addConfigLocation(_contextURL); applicationContext.addEventListener(Event.COMPLETE, handleComplete); applicationContext.load();
It can often be useful to split up container definitions into multiple XML files. One way to then load an application context which is configured from all these XML fragments is to use the application context constructor which takes multiple resource locations. Also, after construction of the container, more locations can be added with the addConfigLocation () method.
Generally, the Spring Actionscript team prefers the above approach, since it keeps container configuration files unaware of the fact that they are being combined with others. An alternate approach is to use one or more occurrences of the <import/> element to load object definitions from another file (or files). Let's look at a sample:
<objects>
<import file="services.xml"/>
<import file="resources/messageSource.xml"/>
<import file="/resources/themeSource.xml"/>
<object id="object1" class="..."/>
<object id="object2" class="..."/>
</objects>The contents of the files being imported must be valid XML object definition files according to the Spring Actionscript schema, including the top level <objects/> element.
In the case where an external XML file is not desirable or practical Spring Actionscript also allows you to embed the XML metadata file in the application.
To do so embed the XML file like this:
[Bindable] [Embed(source="application-context.xml",mimeType ="application/octet-stream")] public var contextConfig:Class;
For more information about embedding files visit this link: http://livedocs.adobe.com/flex/3/html/help.html?content=embed_3.html
After that the way to add the configuration location is slightly different:
var applicationContext:XMLApplicationContext TheXMLApplicationContextis the object factory used in ActionScript projects, in Flex projects you want to use theFlexXMLApplicationContextclass. = new XMLApplicationContext TheXMLApplicationContextis the object factory used in ActionScript projects, in Flex projects you want to use theFlexXMLApplicationContextclass.(); applicationContext.addEmbeddedConfig(contextConfig); applicationContext.load();
Notice that we no longer need the Event.COMPLETE handler, since the configurations are embedded they will be loaded and parsed synchronously, so after invoking addEmbeddedConfig() once or more and calling load() Loads the resource asynchronously and returns an operation that invokers can listen to. the application context will be ready for use immediately.
Of course, if you mix embedded and external metadata you will need to keep the Event.COMPLETE handler and load() Loads the resource asynchronously and returns an operation that invokers can listen to. invocation for obvious reasons.
And that's all there is to it!
If your embedded configuration file also contains import declarations you will have to change the markup slightly to let Spring Actionscript know where to find them. But first add your import configurations like this:
[Bindable] [Embed(source="services.xml",mimeType ="application/octet-stream")] public var servicesContext:Class; [Bindable] [Embed(source="resources/messageSource.xml",mimeType ="application/octet-stream")] public var messageSourceContext:Class; [Bindable] [Embed(source="/resources/themeSource.xml",mimeType ="application/octet-stream")] public var themeSourceContext:Class;
Then inside your main configuration file, change the import markup like this:
<objects>
<import file="servicesContext" type="class"/>
<import file="messageSourceContext" type="class"/>
<import file="themeSourceContext" type="class"/>
<object id="object1" class="..."/>
<object id="object2" class="..."/>
</objects>And again, that's all there is to it!
Make sure to add the embedded Class instances as properties of your Application object, this is the place where Spring Actionscript will look for these property names. If it fails to find the specified names an Error will be thrown. Also, because this functionality is depended on the Flex framework, it is only available when using the FlexXMLApplicationContext class, in other cases the type='class' attribute will be ignored.
In some scenarios it might be useful to store certain properties of the config XML file externally so that you can easily change them without having to wade through the entire configuration file or if you want to re-use certain global values in different parts of the configuration, such as path data or URLs.
The application context allows you to specify external properties in separate Ant-like *.properties files.
You can then define property placeholders in your config files with the ${...} syntax. Here's an example. Note that the path to the *.properties file is relative to the path of the configuration file.
<objects> <property file="strings.properties" /> <object id="string1" class="String"> <constructor-arg value="${s1}"/> </object> <object id="string2" class="String"> <constructor-arg value="${s2}"/> </object> </objects>
And the strings.properties file contents would look like this:
s1=First string s2=Second string
Its also possible to combine property values, that way a property value can be injected with other values, for example:
s1=First String and {$s2}
s2=Second stringTo prevent the properties file from being cached by the web browser the XMLObjectFactory by default will suffix the URL with a random number. To turn this off for a specified property file use the prevent-cache attribute. For example: <property file="strings.properties" prevent-cache="false"/>.
By default the properties loader will throw an error if a properties file could not be loaded, to ignore the error and resume loading set the required attribute to false: <property file="strings.properties" required="false"/>
If you don't need an external file to store your properties in, yet you would like to define global properties to be used throughout your configuration, its also possible to define the property values directly on the <property/> tag:
<property name="s1" value="First string"/> <property name="s2" value="Second string"/>
And, of course, here it is also possible to combine property values:
<property name="s1" value="First string and {$s2}"/>
<property name="s2" value="Second string"/>The file attribute will take precedence over the name and value attributes, so when both are declared the name and value attributes will be ignored.
A Spring Actionscript IoC container manages one or more objects. These objects are created using the configuration metadata that has been supplied to the container (typically in the form of XML <objects/> definitions).
Within the container itself, these object definitions are represented as ObjectDefinition Describes an object that can be created by an <code>ObjectFactory</code>. objects, which contain (among other information) the following metadata:
| Feature | Explained in... |
|---|---|
| class | Instantiating objects |
| name | Naming objects |
| constructor arguments | Injecting dependencies |
| properties | Injecting dependencies |
| autowiring mode | Autowiring collaborators |
| lazy-initialization mode | Lazily-instantiated objects |
| initialization method | Initialization callbacks |
Every object has one or more ids (also called identifiers, or names; these terms refer to the same thing). These ids must be unique within the container the object is hosted in.
When using XML-based configuration metadata, you use the 'id' attribute to specify the object identifier(s). The 'id' attribute allows you to specify exactly one id, and as it is a real XML element ID attribute, the XML parser is able to do some extra validation when other elements reference the id; as such, it is the preferred way to specify an object id. However, the XML specification does limit the characters which are legal in XML IDs.
An object definition essentially is a recipe for creating one or more objects. The container looks at the recipe for a named object when asked, and uses the configuration metadata encapsulated by that object definition to create (or acquire) an actual object.
If you are using XML-based configuration metadata, you can specify the type (or class) of the object that is to be instantiated using the 'class' attribute of the <object/> element. This 'class' attribute (which internally eventually boils down to being a Class property on a ObjectDefinition Describes an object that can be created by an <code>ObjectFactory</code>. instance) is normally mandatory (see Section "" for the exception) and is used for one of two purposes. The class property specifies the class of the object to be constructed in the common case where the container itself directly creates the object by calling its constructor (somewhat equivalent to Actionscript code using the 'new' operator). In the less common case where the container invokes a static, factory method on a class to create the object, the class property specifies the actual class containing the static factory method that is to be invoked to create the object (the type of the object returned from the invocation of the static factory method may be the same class or another class entirely, it doesn't matter).
Object factories can form a hierarchy through the parent property of an IObjectFactory Defines the most basic object factory. implementation such as the AbstractObjectFactory This is the basic implementation of <code>IConfigurableObjectFactory</code>.. By assigning another IObjectFactory Defines the most basic object factory. instance to this parent property the getObject() Will retrieve an object by it's name/id If the definition is a singleton it will be retrieved from cache if possible. method will first see if the current object factory can create the requested object instance, if no appropriate ObjectDefinition Describes an object that can be created by an <code>ObjectFactory</code>. can be found it will request it from its parent factory.
Imagine a scenario with two application contexts. One is created by the main application and the other is created inside a module that is loaded at a later time.
We will refer to the first as application context and the latter as module context.
Now imagine the configuration of the application context to look like this:
<objects> <object class="com.myclasses.MyObject" id="myObject" scope="singleton"/> <object class="com.myclasses.MyOtherObject" id="myOtherObject" scope="prototype"/> </objects>
And the module context looking like this:
<objects> <object class="com.myclasses.moduleimplementations.MyOtherObject" id="myOtherObject" scope="prototype"/> </objects>
When the module context is created, we will set the application context as its parent:
var moduleContext:XMLApplicationContext = new XMLApplicationContext("module-context.xml");
moduleContext.parent = applicationContext;The result of this is that, when an object with id myOtherObject is requested from the application context, you will receive an instance of type com.myclasses.MyOtherObject. However, when you request the same object id from the module context, you will receive an instance of type com.myclasses.moduleimplementations.MyOtherObject.
Next, we change both configurations slightly, add some dependencies and show how to override those dependencies in a the module configuration.
Here's how the application context's configuration looks:
<objects> <object class="com.myclasses.MyObject" id="myObject" scope="singleton"/> <object class="com.myclasses.MyOtherObject" id="myOtherObject" scope="prototype"> <property name="dependency" ref="myDependency"/> </object> <object class="com.dependencies.MyDependency" id="myDependency"/> </objects>
Now requesting an object with id myOtherObject from the application context will yield you an instance of type com.myclasses.MyOtherObject with a dependency property value set to an instance of type com.dependencies.MyDependency.
After that we change the module context configuration to look like this:
<objects>
<object class="com.moduledependencies.MyDependency" id="myDependency"/>
</objects>When we subsequently request an object with id myOtherObject from the module context the result will be an instance of type com.myclasses.MyOtherObject with a dependency property value set to an instance of type com.moduledependencies.MyDependency.
Overriding references like this will only work on objects that are scoped as prototype, this is because its very probable that the object has already been cached by the parent context when requested, and injecting singletons created by the parent with dependencies created by the module context will suddenly put a dependency from the application context on the module context, which is undesirable.
The lookup of external property values follows the same logic, so it is possible to replace properties with values that are available in the parent context.
So if the application context holds an external property by the name of prop1 it is possible declare an object definition in the module context like this:
<objects>
<object class="com.moduleclasses.MyObjectWithAProperty" id="myObjectWithAProperty">
<property name="myProperty" value="{$prop1}"/>
</object>
</objects>
When creating an object using the constructor approach, all normal classes are usable by and compatible with Spring Actionscript. That is, the class being created does not need to implement any specific interfaces or be coded in a specific fashion. Just specifying the object class should be enough. However, depending on what type of IoC you are going to use for that specific object, you may need a default (empty) constructor.
When using XML-based configuration metadata you can specify your object class like so:
<object id="exampleObject" class="examples.ExampleObject"/> <object name="anotherExample" class="examples.ExampleObjectTwo"/>
The Actionscript equivalent of which would be:
var exampleObject:ExampleObject; var anotherExample:ExampleObjectTwo;
And instantiating one of them by the IoC container would look like this:
var exampleObject:ExampleObject = applicationContext.getObject("exampleObject") as ExampleObject;Which in regular Actionscript would look like this:
var exampleObject:ExampleObject = new ExampleObject();
The mechanism for supplying arguments to the constructor (if required), or setting properties of the object instance after it has been constructed, is described shortly.
When defining an object which is to be created using a static factory method, along with the class attribute which specifies the class containing the static factory method, another attribute named factory-method 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 example shows an object definition which specifies that the object is to be created by calling a factory-method. 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 createInstance() method must be a static method.
<object id="exampleObject"
class="examples.ExampleObjectLocator"
factory-method="getInstance"/>Of which the Actionscript equivalent would be:
var exampleObject:ExampleObject = ExampleObjectLocator.getInstance();
The previous section explained how to use a static factory method on a class, here's how to use a factory method on a different instance.
<object id="exampleFactory"
class="examples.ExampleObjectFactory"/>
<object id="exampleObject" class="examples.Example"
factory-object="exampleFactory"
factory-method="getInstance"/>And for this the Actionscript equivalent would be:
var exampleFactory:ExampleObjectFactory = new ExampleObjectFactory(); var exampleObject:ExampleObject = exampleFactory.getInstance();
Besides an external or embedded configuration defined in an XML file, Spring Actionscript also offers you the ability to configure your objects through MXML markup. The markup is very similar to the regular XML version, but with some slight differences, we will list them below.
MXML configuration is done by creating one or more MXML files containing objects or object definitions and loading them via the MXMLApplicationContext Application context that enables configuration to be defined in MXML. class. The difference here with XML configurations is that you can either define objects explicitly in MXML (e.g. <mx:RemoteObject/>) or implicitly via the <Object/> element. The <Object/> element is the same as using the <object/> in XML configuration.
In order to create object definitions in MXML, we let Flex know where to find the components. We do that by declaring its namespace as follows (in MyConfig.mxml for instance):
<?xml version="1.0"?> <Objects xmlns="http://www.springactionscript.org/mxml/config" xmlns:mx="http://www.adobe.com/2006/mxml">
Now to add object definitions you add these MXML components as children to the MXML config.
<Object id="remoteObject" clazz={mx.rpc.remoting.mxml.RemoteObject}>
<Property name="destination" value="ColdFusion"/>
<Property name="concurrency" value="multiple"/>
<Property name="makeObjectsBindable" value="false"/>
<Property name="showBusyCursor" value="true"/>
<Property name="source" value="com.serverside.remote.remoteGateway"/>
</Object>Notice you can define the class of the object with the clazz property which is of type Class. This way you will have compile-time checking of the classes you include in your application context. This is an advantage over regular XML based configuration where you need to make sure that all classes are included by hand.
To use this configuration, all we need to do is create an instance of the MXMLApplicationContext Application context that enables configuration to be defined in MXML. class, add the configurations to it and invoke its load method. This will (asynchronously) load and initialize the application context.
private var appContext:MXMLApplicationContext;
public function creationCompleteHandler(event:FlexEvent):void {
appContext = new MXMLApplicationContext();
appContext.addConfig(MyConfig);
appContext.addEventListener(Event.COMPLETE, appContext_completeHandler);
appContext.load();
}Notice that we pass in the class of the configuration file and not an instance.
We can also use property placeholders inside objects and object definitions defined in MXML. This has the advantage that we can load properties defined externally into the MXML configuration so we do not need to recompile the application when these properties need to be changed. A typical example of this is the configuration of service endpoints.
Below are some examples of property placeholders in MXML configuration.
<Objects
xmlns="http://www.springactionscript.org/mxml/config"
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:context="org.springextensions.actionscript.ioc.factory.config.*">
<mx:Script>
<![CDATA[
import mx.rpc.remoting.mxml.RemoteObject;
]]>
</mx:Script>
<context:PropertyPlaceholderConfigurer locations="{['properties.properties.txt', 'server.properties.txt']}"/>
<Object id="string1" clazz="{String}">
<ConstructorArg>$(property1)</ConstructorArg>
</Object>
<mx:Array id="propertiesArray">
<mx:String>$(property1)</mx:String>
<mx:String>$(property2)</mx:String>
<mx:String>$(property3)</mx:String>
</mx:Array>
<mx:RemoteObject endpoint="http://$(host):$(port)/$(context-root)/messagebroker/amf"/>
<mx:RemoteObject id="remoteObject1" endpoint="http://$(host):$(port)/$(context-root)/messagebroker/amf"/>
<mx:RemoteObject id="remoteObject2">
<mx:endpoint>http://$(host):$(port)/$(context-root)/messagebroker/amf</mx:endpoint>
</mx:RemoteObject>
<Object id="remoteObjectDefinitionWithPlaceHolders" clazz="{RemoteObject}">
<Property name="endpoint" value="http://$(host):$(port)/$(context-root)/messagebroker/amf"/>
</Object>
</Objects>An XMLApplicationContext The <code>XMLApplicationContext</code> is the object factory used in ActionScript projects, in Flex projects you want to use the <code>FlexXMLApplicationContext</code> class. (or FlexXMLApplicationContext Extension of <code>XMLApplicationContext</code> that supports flex framework specific classes like <code>ArrayCollection</code>.) is essentially nothing more than the interface for an advanced factory capable of maintaining a registry of different objects and their dependencies. The XMLApplicationContext The <code>XMLApplicationContext</code> is the object factory used in ActionScript projects, in Flex projects you want to use the <code>FlexXMLApplicationContext</code> class., which is also an implementation of the IObjectFactory Defines the most basic object factory. interface, enables you to read object definitions and access them using the getObject Will retrieve an object by it's name/id If the definition is a singleton it will be retrieved from cache if possible.() method. When using just the XMLApplicationContext you would create one and read in some object definitions in the XML format as follows:
var applicationContext:XMLApplicationContext TheXMLApplicationContextis the object factory used in ActionScript projects, in Flex projects you want to use theFlexXMLApplicationContextclass. = new XMLApplicationContext TheXMLApplicationContextis the object factory used in ActionScript projects, in Flex projects you want to use theFlexXMLApplicationContextclass.(); applicationContext.addConfigLocation("application-context.xml"); applicationContext.addEventListener(Event.COMPLETE, handleComplete); applicationContext.load();
And in the handleComplete method (or any other code which runs after this event has fired) you access your object like this:
public function handleComplete(event:FlexEvent):void {
var exampleObject:ExampleObject = applicationContext.getObject
Will retrieve an object by it's name/id If the definition is a singleton it will be retrieved from
cache if possible.("exampleObject") as ExampleObject;
}Basically that is all there is to it. Using getObject Will retrieve an object by it's name/id If the definition is a singleton it will be retrieved from cache if possible.(String) you can retrieve instances of your object; the client-side view of the XMLApplicationContext The <code>XMLApplicationContext</code> is the object factory used in ActionScript projects, in Flex projects you want to use the <code>FlexXMLApplicationContext</code> class. is simple. The XMLApplicationContext The <code>XMLApplicationContext</code> is the object factory used in ActionScript projects, in Flex projects you want to use the <code>FlexXMLApplicationContext</code> class. object has just a few other methods, but ideally your application code should never use them... Ideally, your application code should have no calls to the getObject Will retrieve an object by it's name/id If the definition is a singleton it will be retrieved from cache if possible.(String) method at all, and thus no dependency on Spring Actionscript APIs at all.
Your typical enterprise application is not made up of a single object. Even the simplest of applications will no doubt have at least a handful of objects that work together to present what the end-user sees as a coherent application. This next section explains how you go from defining a number of object definitions that stand-alone, each to themselves, to a fully realized application where objects work (or collaborate) together to achieve some goal (usually an application that does what the end-user wants).
The basic principle behind Dependency Injection (DI) is that objects define their dependencies (that is to say the other objects they work with) only through constructor arguments, arguments to a factory method, or properties which are set on the object instance after it has been constructed or returned from a factory method. Then, it is the job of the container to actually inject those dependencies when it creates the object. This is fundamentally the inverse, hence the name Inversion of Control (IoC), of the object itself being in control of instantiating or locating its dependencies on its own using direct construction of classes, or something like the Service Locator pattern.
It becomes evident upon usage that code gets much cleaner when the DI principle is applied, and reaching a higher grade of decoupling is much easier when objects do not look up their dependencies, but are provided with them (and additionally do not even know where the dependencies are located and of what concrete class they are). DI exists in two major variants, namely and .
Constructor-based DI is effected by invoking a constructor with a number of arguments, each representing a dependency. Find below an example of a class that could only be dependency injected using constructor injection. Notice that there is nothing special about this class.
public class SimpleMovieLister {
// the SimpleMovieLister has a dependency on a MovieFinder
private _movieFinder:MovieFinder;
// a constructor so that the Spring Actionscript container can 'inject' a MovieFinder
public SimpleMovieLister(movieFinder:MovieFinder) {
_movieFinder = movieFinder;
}
// business logic that actually 'uses' the injected MovieFinder is omitted...
}Setter-based DI is realized by calling setter methods or plainly setting properties on your objects after invoking a no-argument constructor or no-argument static factory method to instantiate your object. Find below an example of a class that can only be dependency injected using pure setter injection. Note that there is nothing special about this class... it is plain old Actionscript.
public class SimpleMovieLister {
// the SimpleMovieLister has a dependency on the MovieFinder
private _movieFinder:MovieFinder;
// a setter method so that the Spring container can 'inject' a MovieFinder
public function set movieFinder(value:MovieFinder):void {
if (value !== this._movieFinder){
this._movieFinder = movieFinder;
}
}
// business logic that actually 'uses' the injected MovieFinder is omitted...
}The XMLObjectFactory supports both of these variants for injecting dependencies into objects it manages. (It in fact also supports injecting setter-based dependencies after some dependencies have already been supplied via the constructor approach.) The configuration for the dependencies comes in the form of an ObjectDefinition Describes an object that can be created by an <code>ObjectFactory</code>., which is used together with IPropertyEditor A property editor converts strings to typed objects. implementations to know how to convert properties from one format to another. However, most users of Spring Actionscript will not be dealing with these classes directly (that is programmatically), but rather with an XML definition file which will be converted internally into instances of these classes, and used to load an entire Spring IoC container instance.
Object dependency resolution generally happens as follows:
The XMLObjectFactory is created and initialized with a configuration which describes all the objects. (Most Spring Actionscript users use an ApplicationContext implementation that supports XML format configuration files.)
Each object has dependencies expressed in the form of properties, constructor arguments, or arguments to the static-factory method when that is used instead of a normal constructor. These dependencies will be provided to the object, when the object is actually created.
Each property or constructor argument is either an actual definition of the value to set, or a reference to another object in the container.
Each property or constructor argument which is a value must be able to be converted from whatever format it was specified in, to the actual type of that property or constructor argument. By default Spring can convert a value supplied in string format to all built-in types, such as int, uint, String, Boolean, etc.
The Spring Actionscript container validates the configuration of each object as the container is created, including the validation that properties which are object references are actually referring to valid objects. However, the object properties themselves are not set until the object is actually created. For those objects that are singleton-scoped and set to be pre-instantiated (such as singleton objects in an ApplicationContext), creation happens at the time that the container is created, but otherwise this is only when the object is requested. When an object actually has to be created, this will potentially cause a graph of other objects to be created, as its dependencies and its dependencies' dependencies (and so on) are created and assigned.
You can generally trust Spring Actionscript to do the right thing. It will detect misconfiguration issues, such as references to non-existent objects and circular dependencies, at container load-time. It will actually set properties and resolve dependencies as late as possible, which is when the object is actually created. This means that a Spring Actionscript container which has loaded correctly can later generate an exception when you request an object if there is a problem creating that object or one of its dependencies. This could happen if the object throws an exception as a result of a missing or invalid property, for example. This potentially delayed visibility of some configuration issues is why ApplicationContext implementations by default pre-instantiate singleton objects. At the cost of some upfront time and memory to create these objects before they are actually needed, you find out about configuration issues when the ApplicationContext is created, not later. If you wish, you can still override this default behavior and set any of these singleton objects to lazy-initialize (that is not be pre-instantiated).
If no circular dependencies are involved (see sidebar for a discussion of circular dependencies), when one or more collaborating objects are being injected into a dependent object, each collaborating object is totally configured prior to being passed (via one of the DI flavors) to the dependent object. This means that if object A has a dependency on object B, the Spring Actionscript IoC container will totally configure object B prior to invoking the setter method on object A; you can read 'totally configure' to mean that the object will be instantiated (if not a pre-instantiated singleton), all of its dependencies will be set, and the relevant lifecycle methods (such as a configured init method) will all be invoked.
First, an example of using XML-based configuration metadata for setter-based DI. Find below a small part of a Spring Actionscript XML configuration file specifying some object definitions.
<object id="exampleObject" class="examples.ExampleObject"> <!-- setter injection using the nested <ref/> element --> <property name="objectOne"><ref>anotherExampleObject</ref></property> <!-- setter injection using the neater 'ref' attribute --> <property name="objectTwo" ref="yetAnotherObject"/> <property name="integerProperty" value="1"/> <property name="booleanProperty" value="true"/> </object> <object id="anotherExampleObject" class="examples.AnotherObject"/> <object id="yetAnotherObject" class="examples.YetAnotherObject"/>
public class ExampleObject {
private var _objectOne:AnotherObject;
private var _objectTwo:YetAnotherObject;
private var _i:int;
private var _bool:Boolean;
public function set objectOne(value:AnotherObject):void {
if (value !== _objectOne){
_objectOne = value;
}
}
public function set objectTwo(value:YetAnotherObject):void {
if (value !== _objectTwo)
_objectTwo = value;
}
}
public function set integerProperty(value:int):void {
if (value != _i){
_i = value;
}
}
public function set booleanProperty(value:Boolean):void {
if (value != _bool){
_bool = value;
}
}
}As you can see, setters have been declared to match against the properties specified in the XML file. Find below an example of using constructor-based DI.
<object id="exampleObject" class="examples.ExampleObject"> <!-- constructor injection using the nested <ref/> element --> <constructor-arg> <ref>anotherExampleObject</ref> </constructor-arg> <!-- constructor injection using the neater 'ref' attribute --> <constructor-arg ref="yetAnotherObject"/> <constructor-arg value="1"/> <constructor-arg value="true"/> </object> <object id="anotherExampleObject" class="examples.AnotherObject"/> <object id="yetAnotherObject" class="examples.YetAnotherObject"/>
public class ExampleObject {
private var _objectOne:AnotherObject;
private var _objectTwo:YetAnotherObject;
private var _i:int;
private var _bool:Boolean;
public ExampleObject(anotherObject:AnotherObject, yetAnotherObject:YetAnotherObject, i:int, b:Boolean) {
_objectOne = anotherobject;
_objectTwo = yetAnotherobject;
_i = i;
_bool = b;
}
}Notice, the constructor arguments specified in the object definition will be used to pass in as arguments to the constructor of the ExampleObject. Now consider a variant of this where instead of using a constructor, Spring Actionscript is told to call a static factory method to return an instance of the object:
<object id="exampleObject" class="examples.ExampleObjectFactory" factory-method="createInstance"> <constructor-arg ref="anotherExampleObject"/> <constructor-arg ref="yetAnotherObject"/> <constructor-arg value="1"/> </object> <object id="anotherExampleObject" class="examples.AnotherObject"/> <object id="yetAnotherObject" class="examples.YetAnotherObject"/>
public final class ExampleObjectFactory {
// a static factory method; the arguments to this method can be
// considered the dependencies of the object that is returned,
// regardless of how those arguments are actually used.
public static createInstance(anotherObject:AnotherObject, yetAnotherObject:YetAnotherObject, i:int):ExampleObject {
var eb:ExampleObject = new ExampleObject(...);
// some other operations...
return eb;
}
}Note that arguments to the static factory method are supplied via <constructor-arg/> elements, exactly the same as if a constructor had actually been used. Also, it is important to realize that the type of the class being returned by the factory method does not have to be of the same type as the class which contains the static factory method.
As mentioned in the previous section, object properties and constructor arguments can be defined as either references to other managed objects (collaborators), or values defined inline. Spring Actionscript's XML-based configuration metadata supports a number of sub-element types within its <property/> and <constructor-arg/> elements for just this purpose.
The <value/> element specifies a property or constructor argument as a human-readable string representation. As mentioned previously, IPropertyEditor A property editor converts strings to typed objects. implementations are used to convert these string values from a String to the actual type of the property or argument.
<object id="amfChannel" class="mx.messaging.channels.AMFChannel">
<constructor-arg>
<value>my-amf</value>
</constructor-arg>
<constructor-arg>
<value>http://{server.name}:{server.port}/flex2gateway/</value>
</constructor-arg>
<property name="pollingEnabled">
<value>false</value>
</property>
</object>The <property/> and <constructor-arg/> elements also support the use of the 'value' attribute, which can lead to much more succinct configuration. When using the 'value' attribute, the above object definition reads like so:
<object id="amfChannel" class="mx.messaging.channels.AMFChannel">
<constructor-arg value="my-amf"/>
<constructor-arg value="http://{server.name}:{server.port}/flex2gateway/"/>
<property name="pollingEnabled" value="false"/>
</object>The ref element is the final element allowed inside a <constructor-arg/> or <property/> definition element. It is used to set the value of the specified property to be a reference to another object managed by the container (a collaborator). As mentioned in a previous section, the referred-to object is considered to be a dependency of the object who's property is being set, and will be initialized on demand as needed (if it is a singleton object it may have already been initialized by the container) before the property is set. All references are ultimately just a reference to another object.
Specifying the target object by using the <ref/> tag is the most general form.
<ref>myTargetObject</ref>
An <object/> element inside the <property/> or <constructor-arg/> elements is used to define a so-called inner object. An inner object definition does not need to have any id defined, and it is best not to even specify any id value because the id value simply will be ignored by the container.
<object id="outer" class="..."> <!-- instead of using a reference to a target object, simply define the target object inline --> <property name="target"> <object class="com.example.Person"> <!-- this is the inner object --> <property name="name" value="Fiona Apple"/> <property name="age" value="25"/> </object> </property> </object>
Note that in the specific case of inner objects, the 'scope' flag and any 'id' attribute are effectively ignored. Inner objects are always anonymous and they are always scoped as prototypes. Please also note that it is not possible to inject inner objects into collaborating objects other than the enclosing object.
The <array/>,
<array-collection/>
, <dictionary/>
and <vector/> elements
allow properties and arguments of the Actionscript collection type
Array, ArrayCollection, Dictionary and Vector, respectively, to be
defined and set.
Be aware that the array-collection type can only be used in a Flex based application (using the FlexXMLApplicationContext Extension of <code>XMLApplicationContext</code> that supports flex framework specific classes like <code>ArrayCollection</code>.) object since it is part of the framework.
Also be careful only to use the Vector type in applications that are made for Flash player version 10 or higher.
<object id="moreComplexObject" class="example.ComplexObject">
<property name="adminEmails">
<dictionary>
<entry key="administrator" value="administrator@example.org"/>
<entry key="support" value="support@example.org"/>
<!-- or a more verbose way of defining an entry -->
<entry>
<key>development</key>
<value>development@example.org</value>
</entry>
</dictionary>
</property>
<property name="someList">
<array>
<value>a list element followed by a reference</value>
<value><ref object="myOtherObject" /></value>
</array>
</property>
<!-- Only use this in a Flex based application -->
<property name="someOtherList">
<array-collection>
<value>a list element followed by a reference</value>
<value><ref object="myOtherObject" /></value>
</array-collection>
</property>
<!-- Only use this in an application made for Flash player 10 and higher -->
<property name="vectorProperty">
<vector type="String">
<value>string1</value>
<value>string2</value>
<value>string3</value>
<value>string4</value>
</vector>
</property>
</object>The nested element style used this initial example tends to become quite verbose. Fortunately, there are attribute shortcuts for most elements, which you can read about in Shortcuts and other convenience options for XML-based configuration metadata.
Injecting the application context can be achieved by using the id 'this' as reference:
<method-invocation name="someMethod">
<arg ref="this"/>
</method-invocation>The configuration metadata shown so far is a tad verbose. That is why there are several options available for you to limit the amount of XML you have to write to configure your components. The first is a shortcut to define values and references to other objects as part of a <property/> definition. The second is slightly different format of specifying properties altogether.
The <property/>, <constructor-arg/>, and <entry/> elements all support a 'value' attribute which may be used instead of embedding a full <value/> element. Therefore, the following:
<property name="myProperty"> <value>hello</value> </property>
<constructor-arg> <value>hello</value> </constructor-arg>
<entry key="myKey"> <value>hello</value> </entry>
are equivalent to:
<property name="myProperty" value="hello"/>
<constructor-arg value="hello"/>
<entry key="myKey" value="hello"/>
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" />
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, with commas, whitespace and semicolons all valid delimiters, like so:
<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" />
The default behavior for IApplicationContext Central interface for the configuration of an application. implementations is to eagerly pre-instantiate all singleton objects at startup. Pre-instantiation means that an IApplicationContext Central interface for the configuration of an application. 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 Central interface for the configuration of an application., 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"/>When the above configuration is consumed by an IApplicationContext Central interface for the configuration of an application., the object named 'lazy' will not be eagerly pre-instantiated when the IApplicationContext Central interface for the configuration of an application. 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 Central interface for the configuration of an application. 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.
See below for a graphical overview of the program flow that happens after you call the getObject() Will retrieve an object by it's name/id If the definition is a singleton it will be retrieved from cache if possible. method on an application context instance.

See below for a graphical overview of the program flow that happens when an object is being wired by the application context.

The Spring Actionscript container is able to autowire relationships between collaborating objects. This means that it is possible to automatically let Spring Actionscript resolve collaborators (other objects) for your object by inspecting the contents of the ObjectDefinition. The autowiring functionality has five modes. Autowiring is specified per object and can thus be enabled for some objects, while other objects will not be autowired. Using autowiring, it is possible to reduce or eliminate the need to specify properties or constructor arguments, thus saving a significant amount of typing. When using XML-based configuration metadata, the autowire mode for a object definition is specified by using the autowire attribute of the <object/> element. The following values are allowed:
| Mode | Explanation |
|---|---|
| no | No autowiring at all. Object references must be defined via a
ref element. This is the default, and changing
this is discouraged for larger deployments, since explicitly
specifying collaborators gives greater control and clarity. To
some extent, it is a form of documentation about the structure of
a system. |
| byName | Autowiring by property name. This option will inspect the
container and look for an object named exactly the same as the
property which needs to be autowired. For example, if you have an
object definition which is set to autowire by name, and it
contains a master property, Spring
Actionscript will look for an object definition named
master, and use it to set the property. |
| byType | Allows a property to be autowired if there is exactly one object of the property type in the container. If there is more than one, a fatal exception is thrown, and this indicates that you may not use byType autowiring for that object. If there are no matching objects, nothing happens; the property is not set. |
| constructor | This is analogous to byType, but applies to constructor arguments. If there isn't exactly one object of the constructor argument type in the container, a fatal error is raised. |
| autodetect | Chooses constructor or byType through introspection of the object class. If a default (parameterless) constructor is found, the byType mode will be applied. |
Note that explicit dependencies in <property/>
and <constructor-arg/>
settings always override autowiring. Please also note that it is not
currently possible to autowire so-called simple
properties such as primitives, Strings, and
Classes (and arrays of such simple properties).
(This is by-design and should be considered a
feature.) When using either the
byType or constructor
autowiring mode, it is possible to wire arrays. In such cases all
autowire candidates within the container that match the expected type
will be provided to satisfy the dependency.
It is important to understand the various advantages and disadvantages of autowiring. Some advantages of autowiring include:
Autowiring can significantly reduce the volume of configuration required. However, mechanisms such as the use of a object template (discussed elsewhere in this chapter) are also valuable in this regard.
Autowiring can cause configuration to keep itself up to date as your objects evolve. For example, if you need to add an additional dependency to a class, that dependency can be satisfied automatically without the need to modify configuration. Thus there may be a strong case for autowiring during development, without ruling out the option of switching to explicit wiring when the code base becomes more stable.
Some disadvantages of autowiring:
Autowiring is more magical than explicit wiring. Although, as noted in the above table, Spring Actionscript is careful to avoid guessing in case of ambiguity which might have unexpected results, the relationships between your Spring Actionscript-managed objects are no longer documented explicitly.
Wiring information may not be available to tools that may generate documentation from a Spring Actionscript container.
Another issue to consider when autowiring by type is that multiple object definitions within the container may match the type specified by the setter method or constructor argument to be autowired. For arrays, collections, or maps, this is not necessarily a problem. However for dependencies that expect a single value, this ambiguity will not be arbitrarily resolved. Instead, if no unique object definition is available, an Exception will be thrown. You do have several options when confronted with this scenario. First, you may abandon autowiring in favor of explicit wiring. Second, you may designate that certain object definitions are never to be considered as candidates by setting their 'autowire-candidate' attributes to 'false' as described in the next section. Third, you may designate a single object definition as the primary candidate by setting the 'primary' attribute of its <object/> element to 'true'.
When deciding whether to use autowiring, there is no wrong or right answer in all cases. A degree of consistency across a project is best though; for example, if autowiring is not used in general, it might be confusing to developers to use it just to wire one or two object definitions.
If a property is of type IApplicationContext or ApplicationDomain the application context instance or its ApplicationDomain will be injected when autowiring byType.
As you can see its possible to combine the different types of wiring, the types take this override precedence:
Wire properties explicitly defined in the
IObjectDefinition from the configuration
Wire properties by name or type as defined by the class annotations (metadata)
Wire properties by name or type as defined in the IObjectDefinition

Spring Actionscript has one situation when used in conjunction with the Flex framework which differs from other Spring implementations. This is when visual components (often declared as MXML components) need to be autowired. In this case the container can't be responsible for the actual creation of the components, so it is deferred back to the Flex application.
Concretely, we want to retain the expressiveness of MXML declaration and combine it with the IoC capabilities of Spring Actionscript.
For example, given this (very simple) piece of MXML markup:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:custom="http://www.mydomain.com/flexcomponents" layout="vertical"> <custom:OrderView myDependency="{this.applicationModel}"/> </mx:Application>
In this case the application model instance is directly injected through concrete markup. In a lot of cases this is perfectly acceptable, but Spring Actionscript offers a little extra flexibility by being able to inject the model instance at runtime.
Spring Actionscript is able to perform these dependency injections by hooking an event listener into the Event.ADDED event and process the components right after they have been added to the stage.
There are several ways of configuration for this stituation, in the following sections we will look at them one by one.
Spring Actionscript will wait until the container has finished loading and parsing its configuration, after which it will loop through the entire current displaylist once to autowire the already created stage components.
If you'd like to learn more about the underlying architecture of stage wiring and how to extend it, check out the section 'The IStageProcessor interface'.
These examples all deal with stage components, yet it is also possible to add the described metadata to 'normal' objects, the functionality remains the same.
You can force the autowiring process to ignore the metadata on a given object by setting its skip-metadata attribute to true. This will yield a small performance boost.
The first possible way of letting the Spring Actionscript container know how to configure a stage component is by adding specific metadata to the component's sources. Obviously this is only possible when the developer actually has access to the source code. Thus, this solution does not apply to the situation in which you'd like to autowire existing components, such as the ones that are already part of the Flex framework.
To make use of the metadata processor that handles all of the functionality described in the following sections add this to the XML configuration:
<object id="autowiringStageProcessor" class="org.springextensions.actionscript.stage.DefaultAutowiringStageProcessor"/>
The simplest way to inject a property by type is by decorating its source like this:
public class ExampleComponent extends UIComponent {
[Autowired]
public var modelInstance:IModelLocator;
public function ExampleComponent() {
super();
}
}Once this component is added to the stage, the Spring Actionscript container will search in its container an object of type IModelLocator and assign it to the modelInstance property of the ExampleComponent.
Wiring by name is also possible, all that is needed is a little extra metadata:
public class ExampleComponent extends UIComponent {
[Autowired(mode='byName')]
public var modelInstance:IModelLocator;
public function ExampleComponent() {
super();
}
}Now the Spring Actionscript container will look for an object in its configuration with the id 'modelInstance' and assign this to the modelInstance property of the ExampleComponent.
There's another way of injecting by name, suited for the situation where the name of the property and the id in the configuration don't match. What if the IModelLocator instance described in the configuration has an id called 'modelLocator' and for some reason this can't be easily changed?
Easy, you can define the exact name in the metadata as follows:
public class ExampleComponent extends UIComponent {
[Autowired(name='ModelLocator')]
public var modelInstance:IModelLocator;
public function ExampleComponent() {
super();
}
}When using the Autowired metadata do not forget to add these compiler settings to your Flex project: -keep-as3-metadata += Autowired
Apparently Flexbuilder on OSX behaves slightly different and needs you to add the metadata one-by-one and quoted, like this: -keep-as3-metadata "Autowired"
To keep your views as decoupled as possible it might be preferred not to inject the modelInstance into it, but a certain property of the model. Since the data in the model is subject to change (usually it is populated with data retrieved from remote method invocations), it would also be good to bind your view to the model.
This can be achieved by using the following metadata:
public class ExampleProductListComponent extends UIComponent {
[Autowired(name='ModelLocator',property='products')]
public var products:ArrayCollection;
public function ExampleProductListComponent() {
super();
}
}This example assumes that the ModelLocator object has a property called 'products' of type ArrayCollection. A binding is established between these two objects, so when the products ArrayCollection in the model in updated, so will the view component.
The property value can also be a chain of objects, so this will work as well:
public class ExampleProductListComponent extends UIComponent {
[Autowired(name='ModelLocator',property='productManager.products')]
public var products:ArrayCollection;
public function ExampleProductListComponent() {
super();
}
}Since this functionality makes use of Flex binding it is therefore only available through the FlexXMLApplicationContext Extension of <code>XMLApplicationContext</code> that supports flex framework specific classes like <code>ArrayCollection</code>..
Its also possible to inject the value of an external property into a stage component. (If you want to know more about external properties read the section 'External property files').
To do this add metadata to your source like this:
public class ExampleComponent extends UIComponent {
[Autowired(externalProperty='currentURL')]
public var websiteURL:String;
public function ExampleComponent() {
super();
}
}Where the value of the propertyName metadata argument key matches the key in one of the loaded property files.
When a Class only uses [Autowire] annotations to define its dependencies it is a waste to have to add an object definition for these classes to the XML configuration. Therefore its also possible to directly let the application context instantiate the class:
var example:ExampleObject = applicationContext.createInstance(ExampleObject);
The createInstance() Creates an instance of the specified <code>Class</code>, wires the instance and returns it. method will instantiate the Class and pass it through the rest of the wiring pipeline, so also object post processing and metadata wiring.
The examples in which metadata is used to describe the desired injections can also entirely be handled by XML configuration. Here is how to configure the ExampleComponent to be autowired by type:
<object id="exampleComponent" class="classes.components.ExampleComponent" autowire="byType" singleton="false"/>Let us be clear immediately though, autowiring a stage component in this way is a bad idea. The Spring Actionscript container will, in this case, actually loop through every property of the ExampleComponent instance and try to find a matching wiring candidate in the container. This will very quickly become very slow, so please regard this example as a proof of concept but don't use it in any actual production code.
Autowiring by name is almost the same and the same warning as the wiring by type is applicable: don't do it.
<object id="exampleComponent" class="classes.components.ExampleComponent" autowire="byName" singleton="false"/>The most obvious way of configuring the ExampleComponent is by simply injecting the property explicitly like this:
<object id="exampleComponent" class="classes.components.ExampleComponent" singleton="false"> <property name="modelInstance" ref="ModelLocator"/> </object>
What makes configuring stage components by XML, arguably, a lot more powerful is that all the usual Spring Actionscript features are now also applicable. This means all the regular injection of data and objects, but also object postprocessors, initialization callbacks, init methods, etc.
Do take notice of the singleton="false" attribute on each of these configuration examples. Don't forget to add this value to each and every stage component definition entry. Spring Actionscript defaults an object definition to a singleton scope and instantiates every singleton in the configuration at startup. Failing to add the singleton="false" attribute will result in Spring Actionscript creating a whole bunch of stage component instances unnecessarily.
The Event.ADDED event is fired a lot during the lifetime of a Flex application. It is therefore paramount to make the event handler as efficient as possible and thus determine as quickly as possible if the component in question is eligible for configuration or not.
Again Spring Actionscript offers several ways to do this. First of all we introduce the IObjectSelector Objects implementing this interface are used to approve (or deny) the selection of an object for some action/purpose. interface. This interface is a modest one:
public interface IObjectSelector {
function approve(object:Object):Boolean;
}An object that implements this interface is responsible for determining whether a specific instance is eligible for autowiring. The how and why is up to the implementation. Spring Actionscript by default uses a FlexStageDefaultObjectSelector instance.
The FlexStageDefaultObjectSelector is a fairly simple implementation of the IObjectSelector Objects implementing this interface are used to approve (or deny) the selection of an object for some action/purpose. interface that, by default, rejects any component whose namespace starts with either 'flash.*' or 'mx.*', after that it checks if the specified object inherits from UIComponent, if not, the object is rejected as well. (This is to prevent embedded images in skins from clogging up the wiring pipeline).
Once a component is approved by the IObjectSelector Objects implementing this interface are used to approve (or deny) the selection of an object for some action/purpose. it will be ready for configuration, the exact wiring information will be determined by either reading the metadata or retrieving an object definition from the configuration.
Naturally, Spring Actionscript also offers you the possibility to easily implement and plug in your own IObjectSelector Objects implementing this interface are used to approve (or deny) the selection of an object for some action/purpose. implementations. Let's have a look at how this works.
By default the DefaultAutowiringStageProcessor <code>IStageProcessor</code> implementation that is created by default by the <code>FlexXMLApplicationContext</code> to perform autowiring and dependency injection on stage components. is fitted with a FlexStageDefaultObjectSelector to approve or reject stage components that have been added to the stage. To override this behaviour you can create your own IObjectSelector Objects implementing this interface are used to approve (or deny) the selection of an object for some action/purpose. implementation and add an object definition for it in the XML configuration. A custom implementation might look something like this in your configuration:
<object id="flexStageObjectSelector" class="com.classes.objectselectors.MyCustomObjectSelector"/>
To use this IObjectSelector Objects implementing this interface are used to approve (or deny) the selection of an object for some action/purpose. instance you must also override the default autowiring processor with a new instance and assign this object selector to it:
<object class="org.springextensions.actionscript.stage.DefaultAutowiringStageProcessor" id="defaultAutowiringStageProcessor">
<property name="selector" ref="flexStageObjectSelector"/>
</object>Be sure to use the 'defaultAutowiringStageProcessor' id for your autowire processor override, this name is determined by the defaultAutowiringStageProcessorName property of the FlexXMLApplicationContext Extension of <code>XMLApplicationContext</code> that supports flex framework specific classes like <code>ArrayCollection</code>..
Once a stage component is approved by an IObjectSelector Objects implementing this interface are used to approve (or deny) the selection of an object for some action/purpose. instance the DefaultAutowiringStageProcessor <code>IStageProcessor</code> implementation that is created by default by the <code>FlexXMLApplicationContext</code> to perform autowiring and dependency injection on stage components. will need an object definition to be able to pass it on to the wire() method of the object factory. This particular task is bestowed upon the IObjectDefinitionResolver interface. Like the IObjectSelector Objects implementing this interface are used to approve (or deny) the selection of an object for some action/purpose., this interface is a simple one:
public interface IObjectDefinitionResolver {
function resolveObjectDefinition(object:*):IObjectDefinition;
}An object that implements this interface is responsible for retrieving, or creating, an object definition for a given object instance. Spring Actionscript by default uses a DefaultObjectDefinitionResolver instance. This implementation uses different strategies to retrieve the appropriate IObjectDefinition Represents an object definition. for an object. First of all it uses the value of its objectIdProperty property to find the object definition by name. By default the value of this property is 'name'. This means that if a stage component is being examined whose name property has a value of 'MyStageComponent', the DefaultObjectDefinitionResolver will look for an object definition with an id of 'MyStageComponent'. If the object definition can't be found it will fall back on trying to find an object definition by type, but only if the lookupByType property on the DefaultObjectDefinitionResolver is set to true.
If both of these options fail the DefaultObjectDefinitionResolver will create a default, empty, object definition. This will happen in the case that a stage component has been decorated with autowiring metadata and has no further use for an object definition. Of course, the both can combined as well, but its open to discussion whether this is advisable.
Just like the IObjectSelector Objects implementing this interface are used to approve (or deny) the selection of an object for some action/purpose. its also possible to plug in your own IObjectDefinitionResolver implementation. What follows is how to do this.
By default the DefaultAutowiringStageProcessor <code>IStageProcessor</code> implementation that is created by default by the <code>FlexXMLApplicationContext</code> to perform autowiring and dependency injection on stage components. is fitted with a DefaultObjectDefinitionResolver to retrieve an appropriate IObjectDefinition Represents an object definition. instance for a given object. To override this behaviour you can create your own IObjectDefinitionResolver implementation and add an object definition for it in the XML configuration. So you can simply add your IObjectDefinitionResolver implementation as follows:
<object id="flexStageObjectDefinitionResolver" class="com.classes.definitionresolvers.MyCustomDefinitionResolver"/>
To use this IObjectDefinitionResolver instance you must also override the default autowiring processor with a new instance and assign this object selector to it:
<object class="org.springextensions.actionscript.stage.DefaultAutowiringStageProcessor" id="defaultAutowiringStageProcessor">
<property name="selector" ref="flexStageObjectSelector"/>
<property name="objectDefinitionResolver" ref="flexStageObjectDefinitionResolver"/>
</object>The Event.ADDED that is being used by the stage wiring system gets dispatched a LOT in the lifetime of a Flex application. It is therefore paramount to keep the selection and wiring process as optimized as possible. First of all it is recommended to use a custom IObjectSelector Objects implementing this interface are used to approve (or deny) the selection of an object for some action/purpose. as much as possible. The one created by default by the DefaultAutowiringStageProcessor <code>IStageProcessor</code> implementation that is created by default by the <code>FlexXMLApplicationContext</code> to perform autowiring and dependency injection on stage components., the FlexStageDefaultObjectSelector, uses this code for the selection process:
public function approve(object:Object):Boolean {
var className:String = getQualifiedClassName(object);
if (className.match("spark.*") || className.match("flash.*") || className.match("mx.*")) {
return false;
}
if (!(object is UIComponent)) {
return false;
}
try {
ObjectUtils.getClass(object);
return true;
}
catch(e:*) {
}
return false;
}
These are quite a few calls for every component being added to the stage. Now, imagine a situation where you know beforehand that only components that implement a specific marker interface need to be autowired. In that case you can implement a much simpler selection process. Let's say the marker interface is called IAutowiredComponent, then the implementation of the approve() method needs to be simply this:
public function approve(object:Object):Boolean {
return (object is IAutowiredComponent);
}
Next, if you also know that all the autowiring is defined by
metadata the DefaultObjectDefinitionResolver,
used by the DefaultAutowiringStageProcessor, can
be a little heavy on the processing side. This is its resolveObjectDefinition()
Resolve an <code>IObjectDefinition</code> for an object to be subsequently
wired.
implementation:
override public function resolveObjectDefinition(object:*):IObjectDefinition {
var objectDefinition:IObjectDefinition = null;
if (_objectIdProperty != null) {
objectDefinition = _getObjectDefinitionByName(object);
}
if (objectDefinition == null && _lookupByType) {
objectDefinition = _getObjectDefinitionByType(object);
}
if (objectDefinition == null) {
LOGGER.debug("Using default IObjectDefinition for {0}", object);
objectDefinition = super.resolveObjectDefinition(object);
}
return objectDefinition;
}
Those are quite a few unnecessary lookups that can be avoided, instead just assign the SimpleObjectDefinitionResolver to the DefaultAutowiringStageProcessor <code>IStageProcessor</code> implementation that is created by default by the <code>FlexXMLApplicationContext</code> to perform autowiring and dependency injection on stage components., this will immediately create an empty ObjectDefinition Describes an object that can be created by an <code>ObjectFactory</code>. for any object it receives, thus speeding things up quite a bit.
If you don't need stage wiring in your application altogether, it might be advised to remove the autowiring stage processor completely. You can do this by invoking the removeAutowiringStageProcessor() on the FlexXMLApplicationContext Extension of <code>XMLApplicationContext</code> that supports flex framework specific classes like <code>ArrayCollection</code>..
It is also possible to inject a stage component into a 'regular' object. To achieve this Spring Actionscript offers an IStageProcessor Describes an object that can process objects that have been added to the stage. implementation called GenericStageProcessor This <code>IStageProcessor</code> uses certain stage components to be assigned to a specified target object.. What this stageprocessor does is it will assign a component that was added to the stage to a previously configured object. This assignment can either be done by property assignement or method invocation.
To determine which object will 'receive' the selected components the GenericStageProcessor This <code>IStageProcessor</code> uses certain stage components to be assigned to a specified target object. has a property called targetObject The target instance that holds the property value defined by the targetField property.. This targetObject The target instance that holds the property value defined by the targetField property. is a reference to another object that is declared in the application context, so to configure the GenericStageProcessor This <code>IStageProcessor</code> uses certain stage components to be assigned to a specified target object. you will need to add this markup to your application context:
<object class="org.springextensions.actionscript.stage.GenericStageProcessor" id="stageProcessor"> <property name="targetObject" ref="stageComponentRegistry"/> </object>
Let's say this stageComponentRegistry object has a method called registerComponent that is used to gather a list of stage components. To have the GenericStageProcessor This <code>IStageProcessor</code> uses certain stage components to be assigned to a specified target object. invoke this method with each stage component it approves, add this bit of markup:
<object class="org.springextensions.actionscript.stage.GenericStageProcessor" id="stageProcessor">
<property name="targetObject" ref="stageComponentRegistry"/>
<property name="targetMethod" value="registerComponent"/>
</object>Right, that was easy so far. Now all we need to do is put the
mechanism in place that will determine which stage components will be
passed to the stageComponentRegistry instance. For this we need to
declare an IObjectSelector instance, in this
example we use one of the pre-existing implementations offered by
Spring Actionscript called ClassBasedObjectSelector. This IObjectSelector
Objects implementing this interface are used to approve (or deny)
the selection of an object for some action/purpose.
approves objects based on their classname and uses regular expressions
to evaluate these names. To add the ClassBasedObjectSelector
to your application add this markup:
<object class="org.springextensions.actionscript.ioc.wire.ClassBasedObjectSelector" id="registrySelector">
<property name="approveOnMatch" value="true"/>
<property name="classRegexpArray">
<value>
<array>
<value>com\.components*</value>
</array>
</value>
</property>
</object>Change the regular expression pattern to suit your own needs.
After this all we need to do is assign this selector to the GenericStageProcessor This <code>IStageProcessor</code> uses certain stage components to be assigned to a specified target object. like this:
<object class="org.springextensions.actionscript.stage.GenericStageProcessor" id="stageProcessor">
<property name="targetObject" ref="stageComponentRegistry"/>
<property name="targetMethod" value="registerComponent"/>
<property name="objectSelector" ref="registrySelector"/>
</object>And that's it, from now on every component that is added to the stage and has a class name that starts with com.components will be passed to the registerComponent method of the stageComponentRegistry object.
To make life a little easier by reducing the amount of markup for the GenericStageProcessor This <code>IStageProcessor</code> uses certain stage components to be assigned to a specified target object. Spring Actionscript also offers a custom namespace with some special markup for this class. See The Stage Processing schema for more details.
Spring Actionscript wouldn't be Spring Actionscript if it didn't allow you to implement your own brand of autowiring. Naturally the Spring Actionscript team is of the opinion that the offered autowiring functionality is about as broad as one can imagine, but should the need arise to step outside the confines of Spring Actionscript autowiring than this entirely possible.
In this particular case the IAutowireProcessor Interface that needs to be implemented by objects that can perform autowiring on arbitrary objects. is your friend. And as you are used to, its not a very complicated one, see for yourself:
public interface IAutowireProcessor {
function autoWire(object:Object, objectDefinition:IObjectDefinition, objectName:String=null):void;
function preprocessObjectDefinition(objectDefinition:IObjectDefinition):void;
}
The first method is the main autoWire() Performs autowiring on the specified object instance, the specified <code>IObjectDefinition</code> can optionally be used to retrieve autowiring information from. method that is invoked by the object container immediately after creation. (see 'A graphical overview of the wiring flow of an object' for more details.)
The second method is invoked by the container right before an object is actually created, so this would typically be a good moment to change any kind of constructor argument autowiring or perhaps change the autowiring strategy of the current IObjectDefinition Represents an object definition. based on some pre-configured logic.
As you can see in the default implementation used by the AbstractObjectFactory This is the basic implementation of <code>IConfigurableObjectFactory</code>., (fittingly titled DefaultAutowireProcessor <p>Default <code>IAutowireProcessor</code> implementation used by the <code>AbstractObjectFactory</code>.</p> ),it is also possible for your own IAutowireProcessor Interface that needs to be implemented by objects that can perform autowiring on arbitrary objects. implementation to include the IObjectFactoryAware Interface to be implemented by all objects that want to know what container they run in. interface. If your instance implements this particular interface it will automatically be injected by the object factory instance to which the IAutowireProcessor Interface that needs to be implemented by objects that can perform autowiring on arbitrary objects. is assigned.
Now, after you've created your own implementation, its time to hook it up to the object container, typically this would be done something like this:
var xmlApplicationContext:XMLApplicationContext = new XMLApplicationContext(); xmlApplicationContext.autowireProcessor = new MyCustomAutowireProcessor();
After that your own autowiring logic will be performed on any object created by the XMLApplicationContext The <code>XMLApplicationContext</code> is the object factory used in ActionScript projects, in Flex projects you want to use the <code>FlexXMLApplicationContext</code> class. instance.
Consequently, when you don't need the autowiring functionality at all in your application, it might be an idea to set the autowireProcessor property to null as this will yield a small performance benefit.
The underlying architecture for stage component wiring can be easily extended, the basics are very simple: An IStageProcessorRegistry Descibes an object that manages a collection of <code>IStageProcessor</code> instances. implementation (in most cases that would be the FlexXMLApplicationContext Extension of <code>XMLApplicationContext</code> that supports flex framework specific classes like <code>ArrayCollection</code>.) adds an event listener to the SystemManager and listens for an Event.ADDED event to be fired. After that an IObjectSelector Objects implementing this interface are used to approve (or deny) the selection of an object for some action/purpose. instance determines whether the DefaultAutowiringStageProcessor <code>IStageProcessor</code> implementation that is created by default by the <code>FlexXMLApplicationContext</code> to perform autowiring and dependency injection on stage components. should process the object or not.
Here's a quick overview of how the IStageProcessorRegistry, IObjectSelector and IStageProcessor interfaces work together:

This pattern can naturally be used to perform other kinds of operations on stage components.
To automatically register any IStageProcessor Describes an object that can process objects that have been added to the stage. instances declared in the configuration, a FlexXMLApplicationContext Extension of <code>XMLApplicationContext</code> that supports flex framework specific classes like <code>ArrayCollection</code>. instance creates a StageProcessorFactoryPostprocessor <p><code>IObjectFactoryPostProcessor</code> implementation that retrieves all the <code>IStageProcessor</code> from the <code>IConfigurableListableObjectFactory</code> instance and registers them by invoking the <code>registerStageProcessor()</code> method on the <code>IStageProcessorRegistry</code> instance.</p> for itself.
As you can see the DefaultAutowiringStageProcessor <code>IStageProcessor</code> implementation that is created by default by the <code>FlexXMLApplicationContext</code> to perform autowiring and dependency injection on stage components. is an implementation of the IStageProcessor Describes an object that can process objects that have been added to the stage. interface, this interface is, as usual, fairly simple:
public interface IStageProcessor {
function get selector():IObjectSelector;
function set selector(value:IObjectSelector):void;
function process(object:Object):Object;
}The IObjectSelector
Objects implementing this interface are used to approve (or deny)
the selection of an object for some action/purpose.
instance can be shared among IStageProcessor
Describes an object that can process objects that have been added to the stage.
instances, so that way only one IObjectSelector's
approval can invoke multiple IStageProcessor
Describes an object that can process objects that have been added to the stage.
process()
Invokes the <code>createInstance()</code> method on the <code>securityManagerFactory</code> instance with
the specified <code>object</code>.
methods. So, if you want the same IObjectSelector
Objects implementing this interface are used to approve (or deny)
the selection of an object for some action/purpose.
to also trigger your custom IStageProcessor
Describes an object that can process objects that have been added to the stage.,
add their configurations like this:
<object class="org.springextensions.actionscript.ioc.wire.ClassBasedObjectSelector" id="globalSelector">
<property name="approveOnMatch" value="true"/>
<property name="classRegexpArray">
<value>
<array>
<value>com\.components*</value>
</array>
</value>
</property>
</object>
<object class="org.springextensions.actionscript.stage.DefaultAutowiringStageProcessor" id="defaultAutowiringStageProcessor">
<property name="selector" ref="globalSelector"/>
<property name="objectDefinitionResolver" ref="flexStageObjectDefinitionResolver"/>
</object>
<object class="com.classesMyCustomStageProcessor" id="myCustomStageProcessor">
<property name="selector" ref="globalSelector"/>
</object>
Although probably you will need different approval strategies for each IStageProcessor Describes an object that can process objects that have been added to the stage. instance, in that case declare separate IObjectSelector Objects implementing this interface are used to approve (or deny) the selection of an object for some action/purpose. instances per IStageProcessor Describes an object that can process objects that have been added to the stage..
For another example of an IStageProcessor Describes an object that can process objects that have been added to the stage. implementation, see the section 'Injecting stage components into other objects'.
A good example of an IStageProcessor Describes an object that can process objects that have been added to the stage. implementation is the LocalizationStageProcessor <code>IStageProcessor</code> that can assign resource values based on the value of specified property on a stage component., found in the org.springextensions.actionscript.localization package. This class enables you to assign resource values to stage components at runtime based on the value of the component's id. To use this class add this bit of markup to your configuration:
<object id="resourceManager" class="mx.resources.ResourceManager" factory-method="getInstance"/> <object id="localizationProcessor" class="org.springextensions.actionscript.localization.LocalizationStageProcessor"> <property name="resourceManager" ref="resourceManager"/> <property name="bundleName" value="mySampleResources"/><!-- change this to the name of your bundle --> </object>
The LocalizationStageProcessor <code>IStageProcessor</code> that can assign resource values based on the value of specified property on a stage component. uses a PropertyValueBasedObjectSelector <code>IObjectSelector</code> that only approves objects that have a specified property whose value is not empty. instance by default, this selector approves only components whose id property is set. When the LocalizationStageProcessor <code>IStageProcessor</code> that can assign resource values based on the value of specified property on a stage component. receives a component it will use its id as a base name to look up resource strings and assign these to arbitrary properties on the component. For instance, if a button is added to the stage with an id called 'myButton' and you want the label property on the button to be set to 'Click me' add a resource string like this:
myButton_label=Click me
If you want the tooltip property to be set to 'Click this button for fun!', then add a resource string like this:
myButton_toolTip=Click this button for fun!
By default the LocalizationStageProcessor <code>IStageProcessor</code> that can assign resource values based on the value of specified property on a stage component. looks for resource strings for the following property names: text,label,toolTip,prompt,dataProvider,title,headerText.
To add to this list, or replace it with your own array of names, use the LocalizationStageProcessor <code>IStageProcessor</code> that can assign resource values based on the value of specified property on a stage component.'s resourceSuffixes <p>An <code>Array</code> of suffixes that correspond to property names on the stage component.</p> <p>For example, a button with id 'myButton':<br/> <Button id="myButton"/><br/> Can have its label property assigned automatically if a resourceName exists with this name:<br/> myButton_label=Click this button</p> property.
There is a sample project that demonstrates the LocalizationStageProcessor <code>IStageProcessor</code> that can assign resource values based on the value of specified property on a stage component. class, you can take a look by following this SVN link.
To learn more about flex resource management, follow this link.
The stage processing pattern can also be used to add role and rights based security to an application. For this particular task Spring Actionscript offers the org.springextensions.actionscript.security package. Part of this package is the SimpleSecurityStageProcessor <p>An <code>IStageProcessor</code> implementation that uses an <code>ISecurityManagerFactory</code> instance to create <code>ISecurityManager</code> instances for the stage components passed to its <code>process()</code> method.</p> <p>This <code>IStageProcessor</code> creates a <code>PropertyValueBasedObjectSelector</code> by default.</p> which is able to create a SimpleStageSecurityManager An <code>ISecurityManager</code> that restricts the access to a list of <code>UIComponents</code>, the way this restriction works is determined by an instance of the <code>AccessStrategy</code> enum. for specified components after they have been added to the stage.
To add the SimpleSecurityStageProcessor <p>An <code>IStageProcessor</code> implementation that uses an <code>ISecurityManagerFactory</code> instance to create <code>ISecurityManager</code> instances for the stage components passed to its <code>process()</code> method.</p> <p>This <code>IStageProcessor</code> creates a <code>PropertyValueBasedObjectSelector</code> by default.</p> to your configuration add this bit of markup:
<object id="securityProcessor" class="org.springextensions.actionscript.security.SimpleSecurityStageProcessor"/>
Now just adding this stage processor to your application context isn't going to achieve much. Somehow the data needed to create what kind of SimpleStageSecurityManager An <code>ISecurityManager</code> that restricts the access to a list of <code>UIComponents</code>, the way this restriction works is determined by an instance of the <code>AccessStrategy</code> enum. for which stage component needs to be fed to the stage processor.
The SimpleSecurityStageProcessor <p>An <code>IStageProcessor</code> implementation that uses an <code>ISecurityManagerFactory</code> instance to create <code>ISecurityManager</code> instances for the stage components passed to its <code>process()</code> method.</p> <p>This <code>IStageProcessor</code> creates a <code>PropertyValueBasedObjectSelector</code> by default.</p> creates a SimpleSecurityManagerFactory <code>ISecurityManagerFactory</code> that holds the roles and rights data for a specified list of <code>UIComponents</code> in a dictionary with a <code>UIComponent</code> id as its key and an <code>IMembershipOwner</code> as its value. instance for itself by default, this ISecurityManagerFactory Describes an object that can manage a list of membership data and based on that can create <code>ISecurityManager</code> instances for arbitrary objects. implementation uses a Dictionary of MembershipAccessData Subclass of <code>SimpleMembershipOwner</code> that also holds an instance of <code>AccessStrategy</code> to determine the type of access restriction to be used on a <code>UIComponent</code> instance. to hold the membership information for stage components. The key of the Dictionary is the id of the stage component to which the MembershipAccessData Subclass of <code>SimpleMembershipOwner</code> that also holds an instance of <code>AccessStrategy</code> to determine the type of access restriction to be used on a <code>UIComponent</code> instance. is applicable. The MembershipAccessData Subclass of <code>SimpleMembershipOwner</code> that also holds an instance of <code>AccessStrategy</code> to determine the type of access restriction to be used on a <code>UIComponent</code> instance. determines which roles and rights are applicable and what strategy is to be used to restrict access to the component.
For example, to assign the right called 'canClickButton' to a Button instance with the id 'myButton' and to have the button be invisible when access is restricted, create a MembershipAccessData Subclass of <code>SimpleMembershipOwner</code> that also holds an instance of <code>AccessStrategy</code> to determine the type of access restriction to be used on a <code>UIComponent</code> instance. instance like this:
var md:MembershipAccessData = new MembershipAccessData();
md.rights.push("canClickButton");
md.accessStrategy = AccessStrategy.VISIBLE;
To have this membership data be used by the stage processor, assign it like this:
var sp:SimpleSecurityStageProcessor = _applicationContext.getObject("securityProcessor") as SimpleSecurityStageProcessor;
(sp.securityManagerFactory as SimpleSecurityManagerFactory).membershipData["myButton"] = md;
This will cause the SimpleSecurityStageProcessor <p>An <code>IStageProcessor</code> implementation that uses an <code>ISecurityManagerFactory</code> instance to create <code>ISecurityManager</code> instances for the stage components passed to its <code>process()</code> method.</p> <p>This <code>IStageProcessor</code> creates a <code>PropertyValueBasedObjectSelector</code> by default.</p> to create a SimpleSecurityManager instance for the button instance with id 'myButton' after it has been added to the stage.
Finally, the SimpleSecurityManagerFactory <code>ISecurityManagerFactory</code> that holds the roles and rights data for a specified list of <code>UIComponents</code> in a dictionary with a <code>UIComponent</code> id as its key and an <code>IMembershipOwner</code> as its value. needs an IMembershipOwner Describes an object that hold a list of role and right names. instance to evaluate against. Typically this would be a user object representing the currently logged in user. The IMembershipOwner Describes an object that hold a list of role and right names. interface is a modest one and only exposes two properties: rights and roles:
public interface IMembershipOwner extends IEventDispatcher {
function get roles():Array;
[Bindable(event="rolesChanged")]
function set roles(value:Array):void;
function get rights():Array;
[Bindable(event="rightsChanged")]
function set rights(value:Array):void;
}You can either have your user object implement this interface or simple inherit from the Spring Actionscript SimpleMembershipOwner Basic implementation of the <code>IMembershipOwner</code> interface. class.
Lastly, it is necessary to assign the user object to the ISecurityManagerFactory Describes an object that can manage a list of membership data and based on that can create <code>ISecurityManager</code> instances for arbitrary objects. that the stage processor exposes. This enables the ISecurityManagers <p>Describes an object that can restrict the access to a list of objects based on a list of role and right names contained in a given <code>IMembershipOwner</code> instance.</p> <p>This interface extends the <code>IMembershipOwner</code> that way the roles and rights that are applicable to the objects that are being managed can be stored in the <code>ISecurityManager</code>.</p> to determine whether they will grant access to their stage components for the currently logged in user, based on the roles and rights that this user owns.
You can perform this assignment like so:
var sp:SimpleSecurityStageProcessor = _applicationContext.getObject("securityProcessor") as SimpleSecurityStageProcessor;
sp.securityManagerFactory.membershipOwner = currentUser; //Where the currentUser variable is an implementation of IMembershipOwner or a subclass of SimpleMembershipOwner.
And that's it! If the currentUser also owns the right called 'canClickButton' the button with id 'myButton' will become visible after the sp.securityManagerFactory.membershipOwner = currentUser assignment has been performed.
To simulate the user logging out simply set the membershipOwner <p><code>IMembershipOwner</code> instance that will be monitored and whose changes will be used to let the <code>ISecurityManagers</code> evaluate access to the objects they manage.</p> <p>Typically an <code>ISecurityManagerFactory</code> will call the <code>checkMembership()</code> method on each <code>ISecurityManager</code> it created when this property changes.</p> property to null.
There is a sample project that demonstrates the SimpleSecurityStageProcessor <p>An <code>IStageProcessor</code> implementation that uses an <code>ISecurityManagerFactory</code> instance to create <code>ISecurityManager</code> instances for the stage components passed to its <code>process()</code> method.</p> <p>This <code>IStageProcessor</code> creates a <code>PropertyValueBasedObjectSelector</code> by default.</p> class, you can take a look by following this SVN link.
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"/>
public class ExampleObject {
public init():void {
// do some initialization work
}
}...is exactly the same as...
<object id="exampleInitObject" class="examples.ExampleObject">
<method-invocation name="init"/>
</object>But a whole lot shorter...
A class which implements the IApplicationContextAware Interface to be implemented by any object that wishes to be notified of the IApplicationContext that it runs in. interface is provided with a reference to the FlexXMLApplicationContext Extension of <code>XMLApplicationContext</code> that supports flex framework specific classes like <code>ArrayCollection</code>. or XMLApplicationContext The <code>XMLApplicationContext</code> is the object factory used in ActionScript projects, in Flex projects you want to use the <code>FlexXMLApplicationContext</code> class. that created it, when it is created by that ApplicationContext.
public interface IApplicationContextAware Interface to be implemented by any object that wishes to be notified of the IApplicationContext that it runs in. { function set applicationContext(value:IApplicationContext Interface to be implemented by any object that wishes to be notified of the IApplicationContext that it runs in.):void; }
This allows objects to manipulate the FlexXMLApplicationContext Extension of <code>XMLApplicationContext</code> that supports flex framework specific classes like <code>ArrayCollection</code>. or XMLApplicationContext The <code>XMLApplicationContext</code> is the object factory used in ActionScript projects, in Flex projects you want to use the <code>FlexXMLApplicationContext</code> class. that created them programmatically, through the IApplicationContextAware Interface to be implemented by any object that wishes to be notified of the IApplicationContext that it runs in. interface, or by casting the reference to a known subclass of this which exposes additional functionality. Primarily this would consist of programmatic retrieval of other objects. While there are cases when this capability is useful, it should generally be avoided, since it couples the code to Spring Actionscript and does not follow the Inversion of Control style, where collaborators are provided to objects as properties.
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 working with an IApplicationContext Central interface for the configuration of an application. programmatically, child object definitions are represented by the ChildObjectDefinition class. Most users will never work with them on this level, instead configuring object definitions declaratively. 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 Will retrieve an object by it's name/id If the definition is a singleton it will be retrieved from cache if possible.() call with the parent object id), will result in an error. Similarly, the container's internal preInstantiateSingletons Instantiates all definitions that are defined as singleton and are not lazy.() 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.
Spring Actionscript offers a second way of defining a template which is almost identical to the above way. There is a specific element called <template/> that offers the same kind of functionality but also has a way of adding parameters to the template's definition. Let's take a look at the following XML metadata:
<template id="remoteObject">
<object class="mx.rpc.remoting.mxml.RemoteObject">
<property name="destination" value="ColdFusion"/>
<property name="endpoint" value="/flex2gateway/"/>
<property name="concurrency" value="multiple"/>
<property name="makeObjectsBindable" value="${makeBindable}"/>
<property name="showBusyCursor" value="${showCursor}"/>
<property name="source" value="com.path.to.remoteobjects.${serviceClass}"/>
<property name="channelSet">
<ref>channelset</ref>
</property>
</object>
</template>This shows the definition of a RemoteObject template which can be re-used for creating different instances of a RemoteObject with different parameters. In the XML metadata you can see a number of placeholders recognizable by the fact that they are enclosed by braces and prefixed with a dollar-sign like this: ${placeholder}. These placeholders will be replaced by the values of the parameters that are sent to the template when instantiating an object.
Here is an example of an object definition that makes use of the template described above:
<object id="concreteService" template="remoteObject"> <param name="makeBindable" value="false"/> <param name="showCursor" value="true"/> <param name="serviceClass" value="gatewayname"/> </object>
The class that takes care of this functionality is the TemplatePreprocessor The <code>TemplatePreprocessor</code> is used to apply all templates to the xml context., this class is automatically created by the XMLObjectDefinitionsParser Xml parser for object definitions. in its preProcessXML() Pre process the xml data before parsing. method.
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" init-method="initialize"/>
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.
The class that takes care of this functionality is the InterfacePreprocessor A <code>IXMLObjectDefinitionsPreprocessor</code> instance that retrieves all <interface/> elements, looks up the <object/> definitions that have classes that implement these interfaces and copies the configuration nodes from the interfaces to the appropriate <object/> elements., this class is automatically created by the XMLObjectDefinitionsParser Xml parser for object definitions. in its preProcessXML() Pre process the xml data before parsing. method.
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"/>
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() Will retrieve an object by it's name/id If the definition is a singleton it will be retrieved from cache if possible. 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"/>
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.
The Spring Actionscript Framework provides a callback interface to change the behavior of your object in the container; this is the IInitializingObject Objects that should execute behavior after their properties have been set, should implement this interface. interface. Implementing this interface will result in the container calling the afterPropertiesSet() Invoked by an object factory after all properties of an object have been set. method immediately after the object has been created and configured, but before its initialization method is called (defined by the init-method attribute).
Internally, the Spring Actionscript Framework uses IObjectPostProcessor Classes that implement the <code>IObjectPostProcessor</code> interface are <em>special</em>, and so they are treated differently by the container. implementations to process any callback interfaces it can find and call the appropriate methods. If you need custom features or other lifecycle behavior Spring Actionscript doesn't offer out-of-the-box, you can implement an IObjectPostProcessor Classes that implement the <code>IObjectPostProcessor</code> interface are <em>special</em>, and so they are treated differently by the container. yourself. More information about this can be found in the section entitled .
Implementing the org.springextensions.actionscript.ioc.factory.IInitializingObject Objects that should execute behavior after their properties have been set, should implement this interface. interface allows an object to perform initialization work after all necessary properties on the object have been set by the container. The IInitializingObject Objects that should execute behavior after their properties have been set, should implement this interface. interface specifies exactly one method:
function afterPropertiesSet():void;
Generally, the use of the IInitializingObject Objects that should execute behavior after their properties have been set, should implement this interface. interface can be avoided and is actually discouraged since it unnecessarily couples the code to Spring Actionscript. As an alternative, objects 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"/>
public class ExampleObject {
public function init():void {
// do some initialization work
}
}...is exactly the same as...
<object id="exampleInitObject" class="examples.AnotherExampleObject"/>
public class AnotherExampleObject implements IInitializingObject {
public function afterPropertiesSet():void {
// do some initialization work
}
}... but does not couple the code to Spring Actionscript.
The IoC component of the Spring Actionscript Framework has been designed for extension. There is typically no need for an application developer to subclass the ApplicationContext class. The Spring Actionscript IoC container can be infinitely extended by plugging in implementations of special integration interfaces.
Spring Actionscript can be extended through the IObjectPostProcessor Classes that implement the <code>IObjectPostProcessor</code> interface are <em>special</em>, and so they are treated differently by the container., IObjectFactoryPostProcessor <p>Allows for custom modification of an application context's objects definitions, adapting the objects property values of the context's underlying object factory. and IFactoryObject <p>Interface to be implemented by objects that are factories for other objects. interfaces.
First we look at some existing examples of these interfaces and after that there is a small tutorial on how to build your own implementation.
The following are a few implementations of these interfaces that Spring Actionscript supports 'out of the box' to help you out in daily development life.
Specifically for the FlexXMLApplicationContext Extension of <code>XMLApplicationContext</code> that supports flex framework specific classes like <code>ArrayCollection</code>. there is the ability to refer to the properties of the Application class directly from the container's metadata. These properties can be used as regular property placeholders in an application context or a properties file. e.g. ${application.url}.
The following properties are supported:
application.frameRate
application.historyManagementEnabled
application.pageTitle
application.resetHistory
application.scriptRecursionLimit
application.scriptTimeLimit
application.url
application.url.protocol
application.url.host
application.url.port
application.usePreloader
application.viewSourceURL
In order to use it in your application, include it as an object in your application context:
<object class="org.springextensions.actionscript.ioc.factory.config.flex.ApplicationPropertiesResolver"/>
The logging target this factory creates will automatically be added to the log manager class.
<object id="traceTarget" class="org.springextensions.actionscript.ioc.factory.config.LoggingTargetFactoryObject"> <property name="loggingTargetClass" value="mx.logging.targets.TraceTarget"/> <property name="includeCategory" value="true"/> <property name="includeDate" value="true"/> <property name="includeLevel" value="true"/> <property name="includeTime" value="true"/> <property name="level" value="2"/> <property name="filters"> <array> <value>com.domain.model.*</value> <value>com.domain.view.*</value> </array> </property> </object>
This is an IObjectPostProcessor Classes that implement the <code>IObjectPostProcessor</code> interface are <em>special</em>, and so they are treated differently by the container. implementation that enforces required properties to be injected. A property is marked as required by adding [Required] metadata to the property definition:
[Required] public var myProperty:Type;
If the property has been defined as required but a suitable injection candidate cannot be found by the container it will throw an IllegalArgumentError exception.
In order to use it in your application, include it as an object in your application context:
<object class="org.springextensions.actionscript.ioc.factory.config.RequiredMetadataObjectPostProcessor"/>
The ObjectFactoryAwarePostProcessor Post processes object by setting the object container as a property on the object if it implements <code>IObjectContainerAware</code>. will check if the object that has just been created by the container implements the IObjectContainerAware Interface to be implemented by all objects that want to know what container they run in. interface. If this is found to be true it will inject the container as a property on the specified object.
In order to use it in your application, include it as an object in your application context:
<object class="org.springextensions.actionscript.ioc.factory.config.ObjectFactoryAwarePostProcessor"/>
Sometimes it is necessary to use the value of another object's field to be injected into a new object. Spring Actionscript offers the FieldRetrievingFactoryObject <p><code>FieldRetrievingFactoryObject</code> is an <code>IFactoryObject</code> implementation which retrieves a static or non-static field value. the this specific task. Configuration for this object is fairly straightforward, here is an example of its usage:
<object id="trafficEventManager" class="com.myclasses.TrafficEventManager"> <constructor-arg> <object class="org.springextensions.actionscript.ioc.factory.config.FieldRetrievingFactoryObject"> <property name="targetObject" ref="modelLocator" /> <property name="targetField" value="trafficEventTypes" /> </object> </constructor-arg> </object>
The TrafficEventManager instance requires an ArrayCollection of event types to be passed to its constructor. In this example we assume this list of event types is defined in the modelLocator instance by its trafficEventTypes property. With the above example this value is now injected into the TrafficEventManager's constructor.
The FieldRetrievingFactoryObject <p><code>FieldRetrievingFactoryObject</code> is an <code>IFactoryObject</code> implementation which retrieves a static or non-static field value. supports both instance and static properties.
Here's how the FieldRetrievingFactoryObject <p><code>FieldRetrievingFactoryObject</code> is an <code>IFactoryObject</code> implementation which retrieves a static or non-static field value. can be used to retrieve a static field:
<object class="org.springextensions.actionscript.ioc.factory.config.FieldRetrievingFactoryObject"> <property name="staticField" value="CURRENT_VERSION"/> <property name="targetClass" value="mx.core.FlexVersion/> </object>
Not just properties can be retrieved from other objects, also the result of method invocations on these objects can be used to inject into other objects. The MethodInvokingFactoryObject <p><code>MethodInvokingFactoryObject</code> is an <code>IFactoryObject</code> implementation which retrieves the result of a method invocation on a specified object or class which may then be used to set a property value or constructor argument for another object.</p> <p>Configuration example of how to retrieve an <code>IResourceManager</code> instance:</p> <pre> <object class="org.springextensions.actionscript.ioc.factory.config.MethodInvokingFactoryObject"> <property name="targetClass" value="mx.resources.ResourceManager" /> <property name="targetMethod" value="getInstance" /> </object> </pre> deals with these kinds of situations. Here is an example:
<object class="org.springextensions.actionscript.ioc.factory.config.MethodInvokingFactoryObject" id="resourceManager">
<property name="targetClass" value="mx.resources.ResourceManager"/>
<property name="targetMethod" value="getInstance"/>
</object>This will call the static getInstance() method on the mx.resources.ResourceManager class. It is also possible to call a method on an instance, here's how:
<object class="org.springextensions.actionscript.ioc.factory.config.MethodInvokingFactoryObject" id="resourceValue">
<property name="targetObject" value="resourceManager"/>
<property name="targetMethod" value="getString"/>
<property name="arguments">
<array>
<value>bundleName</value>
<value>resourceName</value>
</array>
</property>
</object>This will retrieve the previously instantiated resourceManager from the first example and invokes the getString() method on it using the specified array of arguments.
The first extension point that we will look at is the IObjectPostProcessor Classes that implement the <code>IObjectPostProcessor</code> interface are <em>special</em>, and so they are treated differently by the container. interface. This interface defines a number of callback methods that you as an application developer can implement in order to provide your own (or override the containers default) instantiation logic, dependency-resolution logic, and so forth. If you want to do some custom logic after the Spring Actionscript container has finished instantiating, configuring and otherwise initializing an object, you can plug in one or more IObjectPostProcessor Classes that implement the <code>IObjectPostProcessor</code> interface are <em>special</em>, and so they are treated differently by the container. implementations.
IObjectPostProcessors operate on object instances; that is to say, the Spring Actionscript IoC container will have instantiated an object instance for you, and then IObjectPostProcessors get a chance to do their stuff. If you want to change the actual object definition (that is the recipe that defines the object), then you rather need to use a IObjectFactoryPostProcessor (described below in the section entitled .
The org.springextensions.actionscript.ioc.factory.config.IObjectPostProcessor Classes that implement the <code>IObjectPostProcessor</code> interface are <em>special</em>, and so they are treated differently by the container. interface consists of exactly two callback methods. When such a class is registered as a post-processor with the container, for each object instance that is created by the container, the post-processor will get a callback from the container both before any container initialization methods (such as afterPropertiesSet and any declared init method) are called, and also afterwards. The post-processor is free to do what it wishes with the object instance, including ignoring the callback completely. An object post-processor will typically check for callback interfaces, or do something such as wrap an object with a proxy.
An ApplicationContext will automatically detect any objects which are defined in the configuration metadata which is supplied to it that implement the IObjectPostProcessor Classes that implement the <code>IObjectPostProcessor</code> interface are <em>special</em>, and so they are treated differently by the container. interface, and register them as post-processors, to be then called appropriately by the container on object creation. Nothing else needs to be done other than deploying the post-processors in a similar fashion to any other object.
You can force the object factory to ignore its list of IObjectPostProcessors Classes that implement the <code>IObjectPostProcessor</code> interface are <em>special</em>, and so they are treated differently by the container. for a given ObjectDefinition Describes an object that can be created by an <code>ObjectFactory</code>. by setting its skip-postprocessors attribute to true. This will yield a small performance boost.
Let's see how we can build our own processor. Suppose we have an IProductManager interface that looks like this:
public interface IProductManager {
function get items():ArrayCollection;
function set items(value:ArrayCollection):void;
}At runtime the actual items will be loaded by a server call and stored in the application model. Since we won't know exactly when the items will be loaded we can't use the FieldRetrievingFactoryObject <p><code>FieldRetrievingFactoryObject</code> is an <code>IFactoryObject</code> implementation which retrieves a static or non-static field value. to simply assign the model's items to the items property of the IProductManager instance. What we'd like to do is actually bind the productmanager's items to the model items.
Let's see if we can build something that performs this task. We will implement the IObjectPostProcessor Classes that implement the <code>IObjectPostProcessor</code> interface are <em>special</em>, and so they are treated differently by the container. interfaces like this:
public class PropertyBindingPostProcessor implements IObjectPostProcessor {
public function PropertyBindingPostProcessor() {
super();
}
private var _host:Object;
public set host(value:Object):void {
_host = host;
}
private var _chain:Object;
public set chain(value:Object):void {
_chain = value;
}
public function postProcessBeforeInitialization(object:*, objectName:String):* {
Assert.notNull(_host,"host property cannot be null");
Assert.notNull(_chain,"chain property cannot be null");
if (object is IProductManager)
{
BindingUtils.bindProperty(object,'items',host,chain);
}
}
public function postProcessAfterInitialization(object:*, objectName:String):* {
return null;
}
}Now all we need to do is add this bit of configuration and the post processor is ready to do its work:
<object id="propertyBindingPostProcessor" class="com.myclasses.postprocessors.PropertyBindingPostProcessor"> <property name="host" ref="modelInstance"/> <property name="chain" value="items"/> </object>
That's it basically it! Now its certainly possible to come up with a much more generic solution than this, but it does show its fairly easy to create your own post processors for specific tasks.
The org.springextensions.actionscript.ioc.factory.IFactoryObject <p>Interface to be implemented by objects that are factories for other objects. interface is to be implemented by objects that are themselves factories.
The IFactoryObject <p>Interface to be implemented by objects that are factories for other objects. interface is a point of pluggability into the Spring Actionscript IoC containers instantiation logic. If you have some complex initialization code that is better expressed in Actionscript as opposed to a (potentially) verbose amount of XML, you can create your own IFactoryObject <p>Interface to be implemented by objects that are factories for other objects., write the complex initialization inside that class, and then plug your custom IFactoryObject <p>Interface to be implemented by objects that are factories for other objects. into the container.
Now when you request an instance of such an
IFactoryObject from the container, it doesn't
actually return an IFactoryObject
<p>Interface to be implemented by objects that are factories for other
objects. instance, instead, it calls the
getObject()
Will retrieve an object by it's name/id If the definition is a singleton it will be retrieved from
cache if possible.
method on the object and returns the result of this method.
The IFactoryObject <p>Interface to be implemented by objects that are factories for other objects. interface provides three methods:
getObject():*; has to return an instance of the object this factory creates. The instance can possibly be shared (depending on whether this factory returns singletons or prototypes).
isSingleton():Boolean; has to return true if this IFactoryObject returns singletons, false otherwise
getObjectType():Class; has to return either the object type returned by the getObject() method or null if the type isn't known in advance
Let's say we need to instantiate an object of class IncrediblyComplicatedObject. The initialization of this object involves some kind of logic that is beyond the scope of Spring Actionscript and way too complicated to be expressed in XML. We are of course able to write our own code to perform this. We can now build an IFactoryObject <p>Interface to be implemented by objects that are factories for other objects. that implements this task:
public class IncrediblyComplicatedObjectFactory implements IFactoryObject {
public function getObject():* {
var instance:IncrediblyComplicatedObject = new IncrediblyComplicatedObject();
//creation logic ommitted
return instance;
}
public function getObjectType():Class {
return IncrediblyComplicatedObject;
}
public function get isSingleton():Boolean {
return false;
}
}The isSingleton() Determines if the definition with the given name is a singleton. method returns false, this means that every time this IFactoryObject <p>Interface to be implemented by objects that are factories for other objects. is requested from the container, it creates a new instance of IncrediblyComplicatedObject. When set to true it will create an instance once, and return this on every subsequent call. (At least, if the interface is properly implemented :) ).
In order to use an IFactoryObject <p>Interface to be implemented by objects that are factories for other objects. in your application, include it as an object in your application context:
<object class="com.myclasses.factories.IncrediblyComplicatedObjectFactory" id="incrediblyComplicatedObject"/>
After that, requesting an instance of IncrediblyComplicatedObject is the same as requesting any other ordinary object from the container:
var complicated:IncrediblyComplicatedObject = applicationContext.getObject("incrediblyComplicatedObject") as IncrediblyComplicatedObject;Finally, there is sometimes a need to ask a container for an actual IFactoryObject <p>Interface to be implemented by objects that are factories for other objects. instance itself, not the object it produces. This may be achieved by prepending the object id with '&' (sans quotes) when calling the getObject Will retrieve an object by it's name/id If the definition is a singleton it will be retrieved from cache if possible. method of the ObjectFactory (including ApplicationContext). So for a given IFactoryObject <p>Interface to be implemented by objects that are factories for other objects. with an id of myObject, invoking getObject("myObject") on the container will return the product of the IFactoryObject <p>Interface to be implemented by objects that are factories for other objects., but invoking getObject("&myObject") will return the IFactoryObject <p>Interface to be implemented by objects that are factories for other objects. instance itself.
The next extension point that we will look at is the org.springextensions.actionscript.ioc.factory.config.IObjectFactoryPostProcessor <p>Allows for custom modification of an application context's objects definitions, adapting the objects property values of the context's underlying object factory.. The semantics of this interface are similar to the IObjectPostProcessor Classes that implement the <code>IObjectPostProcessor</code> interface are <em>special</em>, and so they are treated differently by the container., with one major difference: IObjectFactoryPostProcessors <p>Allows for custom modification of an application context's objects definitions, adapting the objects property values of the context's underlying object factory. operate on the object configuration metadata; that is, the Spring Actionscript IoC container will allow IObjectFactoryPostProcessors <p>Allows for custom modification of an application context's objects definitions, adapting the objects property values of the context's underlying object factory. to read the configuration metadata and potentially change it before the container has actually instantiated any other objects.
The interface is fairly simple as you can see:
public interface IObjectFactoryPostProcessor {
function postProcessObjectFactory(objectFactory:IConfigurableListableObjectFactory):void;
}In order to use an IObjectFactoryPostProcessor <p>Allows for custom modification of an application context's objects definitions, adapting the objects property values of the context's underlying object factory. in your application, include the implementation as an object in your application context:
<object class="com.myclasses.postprocessors.MyObjectFactoryPostProcessor" id="objectFactoryPostProcessor"/>
Now after the application context has finished loading its configuration file, and before it starts instantiating any objects every IObjectFactoryPostProcessor <p>Allows for custom modification of an application context's objects definitions, adapting the objects property values of the context's underlying object factory. that was found in the configuration will be invoked by calling its postProcessObjectFactory() Modify the application context's internal object factory after its standard initialization. method and passing the current IConfigurableListableObjectFactory This interface combines IConfigurableObjectFactory and IListableObjectFactory instance as the argument. The IObjectFactoryPostProcessor <p>Allows for custom modification of an application context's objects definitions, adapting the objects property values of the context's underlying object factory. can then use the IConfigurableObjectFactory Defines the methods for configuring object factories., IListableObjectFactory Provides an object factory with list type methods of accessing definitions. and IConfigurableListableObjectFactory This interface combines IConfigurableObjectFactory and IListableObjectFactory interfaces to perform whatever postprocessing logic is necessary.
Just as in the case of IObjectPostProcessors, you typically don't want to have IObjectFactoryPostProcessors marked as being lazily-initialized. If they are marked as such, then the Spring Actionscript container will never instantiate them, and thus they won't get a chance to apply their custom logic.