diff --git a/doc/reference/src/objects.xml b/doc/reference/src/objects.xml index 9eec15a9..185b54c2 100644 --- a/doc/reference/src/objects.xml +++ b/doc/reference/src/objects.xml @@ -27,42 +27,31 @@ Introduction - This chapter covers the Spring Framework's implementation of the + This chapter covers the Spring Framework implementation of the Inversion of Control (IoC) See the section entitled principle - The Spring.Core assembly provides the basis for - the Spring.NET Inversion of Control container. The The Spring.Core assembly is the basis for + Spring.NET's IoC container. The IObjectFactory interface provides an advanced configuration mechanism capable of managing - objects of any nature. The IApplicationContext - interface builds on top of the IObjectFactory (it is a - sub-interface) and adds other functionality such as easier integration - with Spring.NET's Aspect Oriented Programming (AOP) features, message - resource handling (for use in internationalization), event propagation and - application layer-specific context such as + is a sub-interface of IObjectFactory. It adds easier + integration with Spring.NET's Aspect Oriented Programming (AOP) features, + message resource handling (for use in internationalization), event + propagation and application layer-specific context such as WebApplicationContext for use in web applications. In short, the IObjectFactory provides the - configuration framework and basic functionality, while the - IApplicationContext adds more enterprise-centric - functionality to it. The IApplicationContext is a - complete superset of the IObjectFactory, and any - description of IObjectFactory capabilities and behavior - should be considered to apply to IApplicationContexts - as well. - - This chapter is divided into two parts, with the first part covering the basic principles - that apply to both the IObjectFactory and - IApplicationContext, with the second part covering those features - that apply only to the IApplicationContext - interface. + configuration framework and basic functionality, and the + IApplicationContext adds more enterprise-specific + functionality. The IApplicationContext is a complete + superset of the IObjectFactory and is used exclusively + in this chapter when describing Spring's IoC container. If you are new to Spring.NET or IoC containers in general, you may want to consider starting with , which @@ -75,84 +64,84 @@ - Basics - containers and objects + The Spring IoC container - - The container + The interface IApplicationContext represents + the Spring IoC container and is responsible for instantiating, + configuring, and assembling many of the objects in your application. The + container gets its instructions on what objects to instantiate, configure, + and assemble by reading configuration metadata. The configuration metadata + is represented in XML. The configuration metadata allows you to express + the objects that compose your application and the rich interdependencies + between such objects. - The IObjectFactory is the actual representation - of the Spring IoC container that is responsible for instantiating, - configuring, and managing a number of objects. + + Note that other ways to specify the metadata, such as attributes + and .NET code, are planned for future releases, the core IoC container + does not assume any specific metadata format. The Java version of Spring + already supports such functionality. + - The IObjectFactory interface is the central IoC - container interface in Spring. Its responsibilities include - instantiating or sourcing application objects, configuring such objects, - and assembling the dependencies between these objects. + Spring provides implementations of the + IApplicationContext interface for use in standalone + and web applications. In standalone applications it is common to create an + instance of an XmlApplicationContext either + programmatically or declaratively in your applications App.config file. In + web applications Spring provides a WebApplicationContext implementation + which is configured by adding a custom HTTP module and HTTP handler to + your Web.config file. See the section on Web Configuration for more + details. - There are a number of implementations of the - IObjectFactory interface that come supplied straight - out-of-the-box with Spring. The most commonly used - IObjectFactory implementation is the - XmlObjectFactory class. This implementation 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. - Interaction with the IObjectFactory interface is - discussed in . Additional - features offered by another implementation of - IObjectFactory, the - IApplicationContext, are discussed in section . + The following diagram is a high-level view of how Spring works. Your + application classes are combined with configuration metadata so that after + the ApplicationContext is created and initialized, you have a fully + configured and executable system or application. - - - - - + + + + + - - Configuration metadata + + Configuration metadata - As can be seen in the above image, the Spring IoC container - consumes some form of configuration metadata; this configuration - metadata is nothing more than how you (as an application developer) - inform the Spring container as to how to “instantiate, configure, and - assemble [the objects in your application]”. This configuration - metadata is typically supplied in a simple and intuitive XML format. - When using XML-based configuration metadata, you write object - definitions for those object that you want the Spring IoC container to - manage, and then let the container do it's stuff. + As the preceding diagram shows, the Spring IoC container consumes + a form of configuration metadata; this + configuration metadata represents how you as an application developer + tell the Spring container to instantiate, configure, and assemble the + objects in your application. Configuration metadata is supplied in a + simple and intuitive XML format - - XML-based metadata is by far the most commonly used form of - configuration metadata. It is not however the only form of - configuration metadata that is allowed. The Spring IoC container - itself is totally decoupled from the format in which this - configuration metadata is actually written. Attribute based metadata - will be part of an upcoming release and it is already part of the - Spring Java framework. - + + XML-based metadata is by far the most commonly used form of + configuration metadata. It is not however the only form of + configuration metadata that is allowed. The Spring IoC container + itself is totally decoupled from the format in which this + configuration metadata is actually written. Attribute based and code + based metadata will be part of an upcoming release and it is already + part of the Spring Java framework. + - Spring configuration consists of at least one object definition - that the container must manage, but typically there will be more than - one object definition. When using XML-based configuration metadata, - these object are configured as <object/> elements inside a - top-level <objects/> element. + Spring configuration consists of at least one and typically more + than one object definition that the container must manage. XML- based + configuration represents beans as <object/> elements inside a + top-level <objects/> element. - These object definitions correspond to the actual objects that - make up your application. Typically you will have object definitions - for your service layer objects, your data access objects (DAOs), - presentation objects such as ASP.NET page instances, infrastructure - objects such as NHibernate SessionFactories, and so forth. Typically - one does not configure fine-grained domain objects in the container, - because it is usually the responsibility of DAOs and business logic to - create/load domain objects. + These object definitions correspond to the actual objects that + make up your application. Typically you define service layer objects, + data access objects (DAOs), presentation objects such as ASP.NET page + instances, infrastructure objects such as NHibernate + SessionFactories, and so forth. Typically one does + not configure fine-grained domain objects in the container, because it + is usually the responsibility of DAOs and business logic to create/load + domain objects. - Find below an example of the basic structure of XML-based - configuration metadata. + The following example shows the basic structure of XML-based + configuration metadata: - <objects xmlns="http://www.springframework.net"> + <objects xmlns="http://www.springframework.net"> <object id="..." type="..."> <!-- collaborators and configuration for this object go here --> @@ -165,119 +154,15 @@ <!-- more object definitions go here --> </objects> - - - - Instantiating a container - - Instantiating a Spring IoC container is straightforward. - - IApplicationContext context = new XmlApplicationContext( - "file://services.xml", - "assembly://MyAssembly/MyDataAccess/data-access.xml"); - -// an IApplicationContext is also an IObjectFactory (via inheritance) -IObjectFactory factory = context; - - You can also create an container by using a custom configuration - section in the standard .NET application (or web) configuration file. - Once the container has been created you may never need to explicitly - interact with it again in your code, for example when configuring - ASP.NET pages. - - You may be wondering what the assembly URL is all about. The above - example uses Spring.NET's IResource - abstraction. The IResource interface provides a - simple and uniform interface to a wide array of IO resources that can - represent themselves as System.IO.Stream. An example - for a file based resource, not using the URL syntax but an - implementation of the IResource interface for file is shown - below.[C#] -IResource input = new FileSystemResource ("objects.xml"); -IObjectFactory factory = new XmlObjectFactory(input); - - These resources are most frequently files or URLs but can also be - resources that have been embedded inside a .NET assembly. A simple URI - syntax is used to describe the location of the resource, which follows - the standard conventions for files, i.e. - file://object.xml and other well known protocols such - as http. - - The following snippet shows the use of the URI syntax for - referring to a resource that has been embedded inside a .NET assembly, - assembly://<AssemblyName>/<NameSpace>/<ResourceName>. - The IResource abstraction is explained further in - . - - - To create an embedded resource using Visual Studio you must set - the Build Action of the .xml configuration file to Embedded Resource - in the file property editor. Also, you will need to explicitly rebuild - the project containing the configuration file if it is the only change - you make between successive builds. If using NAnt to build, add a - <resources> section to the csc task. For example usage, look at - the Spring.Core.Tests.build file included the distribution. - - - The preferred way to create an - IApplicationContext or - IObjectFactory is to use a custom configuration - section in the standard .NET application configuration file (one of - App.config or Web.config). A - custom configuration section that creates the same - IApplicationContext as the previous example is - <spring> - <context type="Spring.Context.Support.XmlApplicationContext, Spring.Core"> - <resource uri="file://services.xml"/> - <resource uri="assembly://MyAssembly/MyDataAccess/data-access.xml"/> - </context> -</spring> The context type (specified as the value of - the type attribute of the context - element) is wholly optional, and defaults to the - Spring.Context.Support.XmlApplicationContext class, - so the following XML snippet is functionally equivalent to the first. - <spring> - <context> - <resource uri="file://services.xml"/> - <resource uri="assembly://MyAssembly/MyDataAccess/data-access.xml"/> - </context> -</spring> - - To acquire a reference to an - IApplicationContext using a custom configuration - section, one simply uses the following code; IApplicationContext ctx = ContextRegistry.GetContext(); - The ContextRegistry is used to both instantiate the - application context and to perform service locator style access to other - objects. (See for more - information). The glue that makes this possible is an implementation of - the Base Class Library (BCL) provided - IConfigurationSectionHandler interface, namely the - Spring.Context.Support.ContextHandler class. The - handler class needs to be registered in the - configSections section of the .NET configuration file - as shown below. <configSections> - <sectionGroup name="spring"> - <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/> - </sectionGroup> -</configSections> This declaration now enables the use - of a custom context section starting at the spring - root element. - - In some usage scenarios, user code will not have to explicitly - instantiate an appropriate implementation of the - IObjectFactory interface, since Spring.NET code will - do it. For example, the ASP.NET web layer provides support code to load - a Spring.NET IApplicationContext automatically as - part of the normal startup process of an ASP.NET web application. - Similar support for WinForms applications is being investigated. - - While programmatic manipulation of - IObjectFactory instances will be described later, the - following sections will concentrate on describing the configuration of - objects managed by IObjectFactory instances. + The id attribute is a string that you use to + identify the individual object definition. The type attribute defines + the type of the object and uses the fully qualified type name, including + the assembly name. The value of the id attribute + refers to collaborating objects. The XML for referring to collaborating + objects is not shown in this example; Dependencies for more information. + Spring.NET comes with an XSD schema to make the validation of the XML object definitions a whole lot easier. The XSD document is @@ -289,15 +174,196 @@ IObjectFactory factory = new XmlObjectFactory(input); providing validation (and Intellisense support in the case of Visual Studio). You may wish to refer to for more information regarding such integration. + - Your XML object definitions can also be defined within the - standard .NET application configuration file by registering the - Spring.Context.Support.DefaultSectionHandler class as - the configuration section handler for inline object definitions. This - allows you to completely configure one or more - IApplicationContext instances within a single - standard .NET application configuration file as shown in the following - example. <configuration> + + Instantiating a container + + Instantiating a Spring IoC container is straightforward. The + location path or paths suppied to an IApplicationContext constructor are + actually resource strings that allow the container to load configuration + metadata from a variety of external resources such as the local file + system, embedded assembly resources, and so on. + + IApplicationContext context = new XmlApplicationContext("services.xml", "data-access.xml"); + + + The following example shows the service layer objects + (services.xml) configuration file. + + <objects xmlns="http://www.springframework.net"> + + <object id="PetStore" type="PetStore.Services.PetStoreService, PetStore"> + <property name="AccountDao" ref="AccountDao"/> + <property name="ItemDao" ref="ItemDao"/> + <!-- additional collaborators and configuration for this object go here --> + </object> + + <!-- more bean definitions for services go here --> + +</objects>The following example shows the data access + objects (daos.xml) configuration file: + + <objects xmlns="http://www.springframework.net"> + + <object id="AccountDao" type="Petstore.Dao.HibernateAccountDao, PetStore"> + <!-- additional collaborators and configuration for this bean go here --> + </object> + + <object id="ItemDao" type="Petstore.Dao.HibernateItemDao, PetStore"> + <!-- additional collaborators and configuration for this bean go here --> + </object> + + <!-- more bean definitions for data access objects go here --> +</objects> + + In this example, the service layer consists of the class + PetStoreService, and two data access objects of + the type HibernateAccountDao and + HibernateItemDao are based on the NHibernate + Object/Relational mapping framework. The property name element refers to + the name of the class's property, and the ref element refers to the name + of another object definition. This linkage between id and ref elements + expresses the dependency between collaborating objects. For details of + configuring an object's dependencies, see Dependencies. + + + Loading configuration metadata from non-default resource + locations + + In the previous example the configuration resources are assumed + to be located in the bin\Debug directory. You can use Spring's + IResource + abstraction to load resources from other locations. + + The following example shows how to create an IoC container + referring to resources located in the root directory of the filesystem + an as an embedded assembly resource. + + IApplicationContext context = new XmlApplicationContext( + "file:///services.xml", + "assembly://MyAssembly/MyDataAccess/data-access.xml"); +The above example uses Spring.NET's IResource + abstraction. The IResource interface provides a + simple and uniform interface to a wide array of IO resources that can + represent themselves as System.IO.Stream. + + + After you learn about Spring's IoC container, you may want to + know more about Spring's IResource + abstraction to load metadata from other locations as desribed below + and alsoin the chapter + + + These resources are most frequently files or URLs but can also + be resources that have been embedded inside a .NET assembly. A simple + URI syntax is used to describe the location of the resource, which + follows the standard conventions for files, i.e. + file:///services.xml and other well known protocols + such as http. + + The following snippet shows the use of the URI syntax for + referring to a resource that has been embedded inside a .NET assembly, + assembly://<AssemblyName>/<NameSpace>/<ResourceName>. + The IResource abstraction is explained further in + . + + + To create an embedded resource using Visual Studio you must + set the Build Action of the .xml configuration file to Embedded + Resource in the file property editor. Also, you will need to + explicitly rebuild the project containing the configuration file if + it is the only change you make between successive builds. If using + NAnt to build, add a <resources> section to the csc task. For + example usage, look at the Spring.Core.Tests.build file included the + distribution. + + + + + Declarative configuration of the container in + App.config/Web.config + + You can also create a container by using a custom configuration + section in the standard .NET application configuration file (one of + App.config or Web.config). A + custom configuration section that creates the same + IApplicationContext as the previous example is + <spring> + <context> + <resource uri="file://services.xml"/> + <resource uri="assembly://MyAssembly/MyDataAccess/data-access.xml"/> + </context> +</spring> The context type (specified as the value of + the type attribute of the + context element) is optional. In a standalone + application the context type defaults to the + Spring.Context.Support.XmlApplicationContext class + and in a Web application defaults to WebApplicationContext. An example + of explicitly configuring the context type The following example shows + explicit use of the context type attribute: <spring> + <context type="Spring.Context.Support.XmlApplicationContext, Spring.Core"> + <resource uri="file:///services.xml"/> + <resource uri="assembly://MyAssembly/MyDataAccess/data-access.xml"/> + </context> +</spring> + + To acquire a reference to an + IApplicationContext using a custom configuration + section, one simply uses the following code; IApplicationContext ctx = ContextRegistry.GetContext(); + The ContextRegistry is used to both instantiate the + application context and to perform service locator style access to + other objects. (See for more + information). The glue that makes this possible is an implementation + of the Base Class Library (BCL) provided + IConfigurationSectionHandler interface, namely the + Spring.Context.Support.ContextHandler class. The + handler class needs to be registered in the + configSections section of the .NET configuration + file as shown below. <configSections> + <sectionGroup name="spring"> + <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/> + </sectionGroup> +</configSections> This declaration now enables the use + of a custom context section starting at the spring + root element. + + In some usage scenarios, user code will not have to explicitly + instantiate an appropriate implementation + IApplicationContext interface, since Spring.NET + code will do it for you. For example, the ASP.NET web layer provides + support code to load a Spring.NET + WebApplicationContext automatically as part of the + normal startup process of an ASP.NET web application. As such, once + the container has been created for you, it is often the case that you + will never need to explicitly interact with it again in your code, for + example when configuring ASP.NET pages. + + Spring.NET comes with an XSD schema to make the validation of + the XML object definitions a whole lot easier. The XSD document is + thoroughly documented so feel free to take a peek inside (see ). The XSD is currently used in the + implementation code to validate the XML document. The XSD schema + serves a dual purpose in that it also facilitates the editing of XML + object definitions inside an XSD aware editor (typically Visual + Studio) by providing validation (and Intellisense support in the case + of Visual Studio). You may wish to refer to + for more information regarding such integration. + + Your XML object definitions can also be defined within the + standard .NET application configuration file by registering the + Spring.Context.Support.DefaultSectionHandler class + as the configuration section handler for inline object definitions. + This allows you to completely configure one or more + IApplicationContext instances within a single + standard .NET application configuration file as shown in the following + example. <configuration> <configSections> <sectionGroup name="spring"> @@ -320,35 +386,31 @@ IObjectFactory factory = new XmlObjectFactory(input); </configuration> - Other options available to structure the configuration files are - described in and - . + Other options available to structure the configuration files are + described in and + . - The IApplicationContext can be configured to - register other resource handlers, custom parsers to integrate - user-contributed XML schema into the object definitions section, type - converters, and define type aliases. These features are discussed in - section + The IApplicationContext can be configured to + register other resource handlers, custom parsers to integrate + user-contributed XML schema into the object definitions section, type + converters, and define type aliases. These features are discussed in + section + Composing XML-based configuration metadata - It is often 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. With an - object factory, an object definition reader can be used multiple times - to read definitions from each file in turn. + It can be useful to split up object definitions into multiple + XML files. Often each individual XML configuration file represents a + logical layer or module in your architecture. One way to then load an + application context that is configured from all these XML fragments is + to use the application context constructor. This constructor takes + multiple IResource locations, as was shown in + the previous section. - Generally, the Spring.NET team prefers the above approach, - assembling individual files because it keeps container configuration - files unaware of the fact that they are being combined with others. - However, an alternate approach is to compose one XML object definition - file using one or more occurrences of the import - element to load definitions from other files. Any - import elements must be placed before - object elements in the file doing the importing. - Let's look at a sample: + 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 xmlns="http://www.springframework.net"> @@ -362,7 +424,7 @@ IObjectFactory factory = new XmlObjectFactory(input); </objects> In this example, external object definitions are being loaded - from 3 files, services.xml, + from three files, services.xml, messageSource.xml, and themeSource.xml. All location paths are considered relative to the definition file doing the importing, so @@ -374,53 +436,93 @@ IObjectFactory factory = new XmlObjectFactory(input); importing file. As you can see, a leading slash is actually ignored, but given that these are considered relative paths, it is probably better form not to use the slash at all. The contents of the files - being imported must be fully valid XML object definition files - according to the XSD, including the top level - objects element. + being imported, including the top level + <objects/> element, must be valid XML bean + definitions according to the Spring Schema. + + Using the container + + An IApplicationContext is the interface for an + advanced factory capable of maintaining a registry of different objects + and their dependencies. Using the method + GetObject(string) or the indexer + [string] you can retrieve instances of your + objects. + + The IApplicationContext enables you to read + object definitions and access them as follows: + + // create and configure beans +IApplicationContext context = new XmlApplicationContext("services.xml", "daos.xml"); + +// retrieve configured instance +PetStoreService service = (PetStoreService) context.GetObject("PetStoreService"); + +// use configured instance +IList userList = service.GetUserNames(); + + + You use the method GetObject to retrieve + instances of your objects. The IApplicationContext interface has a few + other methods for retrieving objects, but ideally your application code + should never use them. Indeed, your application code should have no + calls to the GetObject method at all, and thus no dependency on Spring + APIs at all. For example, Spring's integration with web frameworks + provides for dependency injection for various web framework classes such + as ASP.NET pages and user controls. + + + The syntactical inconvenience of the cast will be addressed in a + future release of Spring.NET that is based on a generic API. Note, + that even when using a generic API, looking up an object by name in no + way guarantees that the return type will be that of the generic + type. + + + The Objects - A Spring 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 <object/> - definitions). + A Spring IoC container manages one or more objects. These objects + are created using the configuration metadata that you supply to the + container. Within the container itself, these object definitions are - represented as IObjectDefinition objects, which contain (among other - information) the following metadata: + represented as IObjectDefinition objects, which + contain (among other information) the following metadata: - A type name: typically this is the - actual implementation class of the object being defined.. + A type name: typically the actual + implementation class of the object being defined.. Object behavioral configuration elements, which state how - the object should behave in the Spring.NET IoC container (i.e. - prototype or singleton, lifecycle callbacks, and so forth) + the object should behave in the container (i.e. prototype or + singleton, lifecycle callbacks, and so forth) - references to other objects which are needed for the object + References to other objects which are needed for the object to do its work: these references are also called collaborators or dependencies. - other configuration settings to set in the newly created + Other configuration settings to set in the newly created object. An example would be the number of threads to use in an object that manages a worker thread pool, or the size limit of the pool. - The concepts listed above directly translate to a set of elements - the object definition consists of. These elements are listed below, - along with a link to further documentation about each of them. + The preceeding concepts translate directly to a set of properties + that eacdh object definition consists of. The following table lists some + of these properties, with links to documentation
Object definition explanation @@ -508,84 +610,88 @@ IObjectFactory factory = new XmlObjectFactory(input); Naming objects - 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. An object will almost always have only one id, but if an - object has more than one id, the extra ones can essentially be - considered aliases. + Every object has one or more identifiers. These identifiers must + be unique within the container that hosts the objects. An object + usually has only one identifier, but if it requires more than one, the + extra ones can be considered aliases. + + + A convention that has evolved is to use the standard C# + convention for Property names when naming objects. That is, object + names start with a uppercase letter, and are camel-cased from then + on. Examples of such names would be (without quotes) + 'AccountManager', 'AccountService', 'UserDao', 'LoginController', + and so forth. + + Naming object consistently makes your configuration easier to + read and understand, and if you are using Spring AOP it helps a lot + when applying advice to a set of objects related by name. + When using XML-based configuration metadata, you use the - 'id' or 'name'attributes to + 'id' and/or 'name'attributes 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 + attribute allows you to specify exactly one id, and because 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. This is usually not a constraint, but if you have a need to use one of these special XML characters, or want to introduce other aliases to the object, you - may also or instead specify one or more object ids, + can specify them in the 'name' attribute , separated by a comma (,), semicolon - (;), or whitespace in the 'name' - attribute. + (;), or whitespace. - Please note that you are not required to supply a name for a - object. If no name is supplied explicitly, the container will generate - a unique name for that object. The motivations for not supplying a - name for a object will be discussed later (one use case is inner - objects). + + You are not required to supply a name for a object. If no name + is supplied explicitly, the container will generate a unique name + for that object. The motivations for not supplying a name for a + object are to use autowiring and inline-objects which will be + discussed later. + - Aliasing objects + Aliasing an object outside the object definition In an object definition itself, you may supply more than one - name for the object, by using a combination of the id and name - attributes as discussed in . - This approach to aliasing objects has some limitations when you - would like to assemble the main application configuration file from - multiple files. This usage pattern is common when each configuration - file represents a logical layer or component within the application. - In this case you may want to refer to a common object dependency - using a name that is specific to each file. If the common object - dependency is defined in the main application configuration file - itself, then one can use the name element as an alias mechanism. - However, if the main application configuration file should not be - responsible for defining the common object dependency, since it - logically 'belongs' to one of the other layers or components, you - can not use the name attribute to achieve this goal. + name for the object, by using a combination of up to one name + specified by the id attribute, and any number of + other names in the name attribute. These names + are equivalent aliases to the same object, and are useful for some + situations, such as allowing each component in an application to + refer to a common dependency by using a object name that is specific + to that component itself. - In this case, you can define an alias using an explicit - alias element contained in the main application - configuration file. + Specifying all aliases where the object is actually defined is + not always adequate, however. It is sometimes desirable to introduce + an alias for an object that is defined elsewhere. This is commonly + the case in large systems where configuration is split amongst each + subsystem, each subsystem having its own set of object defintions. + In XML-based configuration metadata, you can use of the + <alias/> element to accomplish this. - <alias name="fromName" - alias="toName"/> + <alias name="fromName" alias="toName"/> - This allows an object named fromName to be - referred to as toName across all application - configuration files. + In this case, an object in the same container which is named + 'fromName', may also after the use of this alias + definition, be referred to as 'toName'. - As a concrete example, consider the case where the - configuration file 'a.xml' (representing component A) defines a - connection object called componentA-connection. In another file, - 'b.xml' (representing component B) would like to refer to the - connection as componentB-connection. And the main application, - MyApp, defines its own XML fragment to assembles the final - application configuration from all three fragments and would like to - refer to the connection as myApp-connection. This scenario can be - easily handled by adding to the MyApp XML fragment the following - standalone aliases: + For example, the configuration metadata for subsystem A may + refer to a DbProvider via the name 'SubsystemA-DbProvider. The + configuration metadata for subsystem B may refer to a DbProvider via + the name 'SubsystemB-DbProvider'. When composing the main + application that uses both these subsystems the main application + refers to the DbProvider via the name 'MyApp-DbProvider'. To have + all three names refer to the same object you add to the MyApp + configuration metadata the following aliases definitions: - <alias - name="componentA-connection" - alias="componentB-connection"/> - - <alias name="componentA-connection" - alias="myApp-connection"/> + <alias name="SubsystemA-DbProvider" alias="SubsystemB-DbProvider"/> +<alias name="SubsystemA-DbProvider" alias="MyApp-DbProvider"/> Now each component and the main app can refer to the - connection via a name that is unique and guaranteed not to clash + connection through a name that is unique and guaranteed not to clash with any other definition (effectively there is a namespace), yet they refer to the same object. @@ -593,7 +699,7 @@ IObjectFactory factory = new XmlObjectFactory(input); - Object creation + Instantiating objects An object definition essentially is a recipe for creating one or more objects. The container looks at the recipe for a named object when @@ -604,43 +710,52 @@ IObjectFactory factory = new XmlObjectFactory(input); the type of object that is to be instantiated using the 'type' attribute of the <object/> element. This - 'type' attribute (which internally eventually boils - down to being a Type property on a - IObjectDefinition instance) is normally mandatory - (see XXX “Instantiation using an instance factory method” and XXX - “Object definition inheritance” for the two exceptions) and is used for - one of two purposes. The type property specifies the type of of the - object to be constructed in the common case where the container itself - directly creates the object by calling its constructor reflectively - (somewhat equivalent to C# 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 type 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 type or another type entirely, it doesn't matter). + 'type' attribute (which internally is a + Type property on a + IObjectDefinition instance) is normally mandatory. + (For exceptions see the section called Instantiation + using an instance factory method and Object definition inheritance.) + You use the Type property in one of two ways: + + + + To specify the type of of the object to be constructed in the + common case where the container itself directly creates the object + by calling its constructor reflectively, somewhat equivalent to C# + 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, specify 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 type or another type entirely. + + - Object creation via constructor invocation + Instantiatoin using a constructor - When creating an object using the constructor approach, all + When you createn an object using the constructor approach, all normal classes are usable by and compatible with Spring. That is, the type being created does not need to implement any specific interfaces or be coded in a specific fashion. Just specifying the object type should be enough. However, depending on what type of IoC you are going to use for that specific object, you may need to create a default - constructor (i.e. a constructor that has no parameters) in the source - code definition of your class. + constructor. - The XmlObjectFactory implementation of the - IObjectFactory interface can consume object - definitions that have been defined in XML, for example... - <object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary"/> + With XML-based configuration metadata you can specify your + object class as follows: <object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary"/> 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. + been constructed, is described in This XML fragment describes an object definition that will be identified by the exampleObject name, instances @@ -693,19 +808,19 @@ IObjectFactory factory = new XmlObjectFactory(input); Object creation via a static factory method When defining an object which is to be created using a static - factory method, along with the type attribute which specifies the type - containing the static factory method, another attribute named - factory-method is needed to specify the name of the factory method - itself. Spring.NET expects to be able to call this method (with an - optional list of arguments as described later) 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. + factory method, you use the type attribute to specify the type + containing the static factory method and an attribute named + factory-method to specify the name of the factory method itself. You + should be able to call this method (with an optional list of arguments + as described later) and return 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. - Following is an example of 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 type containing the factory method. In this example, + The following example shows an object definition that specifies + the object is to be created by calling a factory-method. The + definition does not specify the type of the returned object, only the + type containing the factory method. In this example, CreateInstance must be a static method. <object id="exampleObject" type="Examples.ExampleObjectFactory, ExamplesLibrary" @@ -713,21 +828,23 @@ IObjectFactory factory = new XmlObjectFactory(input); The mechanism for supplying (optional) arguments to the factory method, or setting properties of the object instance after it has been - returned from the factory, will be described shortly. + returned from the factory, is described in Object creation via an instance factory method - In a fashion similar to instantiation using a static factory - method, instantiation using an instance factory method is where a - non-static method of an existing object from the container is invoked - to create the new object. To use this mechanism, the - 'type' attribute must be left empty, and the - 'factory-object' attribute must specify the name of - an object in the current (or parent/ancestor) container that contains - the instance method that is to be invoked to create the object. The - name of the factory method itself should still be set via the + Similar to instantiation through a static factory + method, instantiation with an instance factory method involves + the invocation of a non-static method on an existing object from the + container to create a new object. To use this mechanism, leave the + 'type' attribute empty, and in the + 'factory-object' attribute specify the name of an + object in the current (or parent/ancestor) container that contains the + instance method that is to be invoked to create the object. Set the + name of the factory method itself with the 'factory-method' attribute.<!-- the factory object, which contains an instance method called 'CreateInstance' --> <object id="exampleFactory" type="..."> @@ -739,16 +856,19 @@ IObjectFactory factory = new XmlObjectFactory(input); factory-method="CreateInstance" factory-object="exampleFactory"/> - Although the mechanisms for setting object properties are still - to be discussed, one implication of this approach is that the factory - object itself can be managed and configured via Dependency Injection, - by the container. - When the Spring documentation makes mention of a 'factory - object', this will be a reference to an object that is configured - in the Spring container that will create objects via an instance - or static factory method. When the documentation mentions a - IFactoryObject (notice the capitalization) this - is a reference to a Spring-specific + Although the mechanisms for setting object + properties are still to be discussed, one implication of this + approach is that the factory object itself can be managed and + configured through Dependency Injection (DI). + In Spring documentation, 'factory + object', refers to an object that is configured in the + Spring container that will create objects via an instance + or static + factory method. By contrast, IFactoryObject + (notice the capitalization) refers to a Spring-specific IFactoryObject . @@ -890,78 +1010,65 @@ public class TestGenericObjectFactory TestGenericObject<List<int>,int> - - - Using the container - - An IApplicationContext is essentially nothing - more than the interface for an advanced factory capable of maintaining a - registry of different objects and their dependencies. The - IApplicationContext enables you to read object - definitions and access them. You create one and read in some object - definition in the XML format as follows: - - IApplicationContext context = new XmlApplicationContext("file://objects.xml"); - - - Basically that is all there is to it. Using - GetObject(string) or the indexer - [string], you can retrieve instances of your object; - the client-side view of the IApplicationContext is - simple. The IApplicationContext interface has just a - few other methods related to finding objects in the contianer, but - ideally your application code should never use them... indeed, your - application code should have no calls to the - GetObject(string) method at all, and thus no - dependency on Spring APIs at all. - Dependencies - 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). + A typical enterprise application does not consist of a single + object. Even the simplest application has a few 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 to a fully realized application where objects collaborate + to achieve a goal. Injecting dependencies - 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. + Dependency injection (DI) is a process whereby objects define + their dependencies, that is, the other objects they work with, only + through constructor arguments and properties that are set on the object + instance after it is constructed. (Factory methods may be considered a + special case of providing constructor arguments for the purposes of this + description). The container injects these dependencies when it creates + the bean. This process is fundamentally the inverse to the case when the + bean itself is controlling the instantiation of its dependencies on its + own by using direct construction of classes, or the Service Locator + pattern. The inverting of this responsibility is why the name Inversion + of Control (IoC) is used to describe the container's actions. - 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 Constructor Injection and Setter - Injection. + Code is cleaner when using DI and decoupling is more effective + when objects are provided with their dependencies. The object does not + look up its dependencies, and does not know the location or class of the + dependencies. Long sections of initialization code that you used to hide + in a #region tag simply go away, and are placed by container + configuration metadata. One can also consider this clean up an + application of the principal of Separation of Concerns. Before using DI, + you class was responsible for business logic AND its configuration, it + was concerns with doing more than one thing. DI removes the + responsibility of configuration from the class, leaving it only with a + single purpose, as the location of business logic. Furthermore, since + you class does not know the location of its dependencies these classes + also become easier to test, in particular when the dependencies are + interfaces or abstract base classes allowing for stub or mock + implementation to be used in unit tests. + + Dependency injection exists in two major variants, + Constructor-based dependency injection and Setter-based dependency + injection. - Constructor Injection + Constructor-based dependency injection - Constructor-based DI is effected by invoking a constructor with - a number of arguments, each representing a dependency. Additionally, - calling a static factory method with specific arguments to construct - the object, can be considered almost equivalent, and the rest of this - text will consider arguments to a constructor and arguments to a - static factory method similarly. 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. + Constructor-based DI is accomplished by the container invoking a + constructor with a number of arguments, each representing a + dependency. Calling a static factory method with specific arguments to + construct the object is nearly equivalent, and this discussion treats + arguments to a constructor and to a static factory method similarly. + The following example shows a class that can only be + dependency-injected by using constructor injection. Notice that there + is nothing special about this class (no container specific interfaces, + base classes or attributes) public class SimpleMovieLister { @@ -979,15 +1086,14 @@ public class TestGenericObjectFactory } - Constructor Argument Resolution + Constructor argument resolution Constructor argument resolution matching occurs using the - argument's type. If there is no potential for ambiguity in the - constructor arguments of a object definition, then the order in - which the constructor arguments are defined in a object definition - is the order in which those arguments will be supplied to the - appropriate constructor when it is being instantiated. Consider the - following class: + argument's type. If ambiguity exists in the constructor arguments of + a object definition, then the order in which the constructor + arguments are defined in a object definition is the order in which + those arguments will be supplied to the appropriate constructor when + it is being instantiated. Consider the following class: namespace X.Y { @@ -1000,11 +1106,11 @@ public class TestGenericObjectFactory } } - There is no potential for ambiguity here (assuming of course - that Bar and Baz classes are not related in an inheritance - hierarchy). Thus the following configuration will work just fine, - and you do not need to specify the constructor argument indexes and - / or types explicitly. + No ambiguity exists, assuming of course that Bar and Baz + classes are not related by inheritance. Thus the following + configuration will work just fine, and you do not need to specify + the constructor argument indexes and / or types explicitly in the + contructor-arg element. <object name="Foo" type="X.Y.Foo, Example"> <constructor-arg> @@ -1017,7 +1123,9 @@ public class TestGenericObjectFactory When another object is referenced, the type is known, and matching can occur (as was the case with the preceding example). - When a simple type is used, such as + + + When a simple type is used, such as <value>true<value>, Spring cannot determine the type of the value, and so cannot match by type without help. Consider the following class: @@ -1041,12 +1149,13 @@ namespace SimpleApp } - Constructor Argument Type Matching + Constructor argument type matching - The above scenario can use type - matching with simple types by explicitly specifying the type of - the constructor argument using the type - attribute. For example: <object name="exampleObject" type="SimpleApp.ExampleObject, SimpleApp"> + In the preceding scenario, the container + can use type matching with simple types by + explicitly specifying the type of the constructor argument using + the 'type' attribute. For example: + <object name="exampleObject" type="SimpleApp.ExampleObject, SimpleApp"> <constructor-arg type="int" value="7500000"/> <constructor-arg type="string" value="42"/> </object> @@ -1185,25 +1294,24 @@ namespace SimpleApp - Constructor Argument Index + Constructor argument Index - Constructor arguments can have their index specified - explicitly by use of the index attribute. For + You can specify explicitly the index of constructor + arguments by using the index attribute. For example: <object name="exampleObject" type="SimpleApp.ExampleObject, SimpleApp"> <constructor-arg index="0" value="7500000"/> <constructor-arg index="1" value="42"/> -</object>As well as solving the ambiguity problem of - multiple simple values, specifying an index also solves the - problem of ambiguity where a constructor may have two arguments of - the same type. Note that the index is 0 - based. +</object>In addition to resolving the ambiguity of + multiple simple values, specifying an index also resolves + ambiguity where a constructor has two arguments of the same type. + Note that the index is 0 based. - Constructor Arguments by Name + Constructor arguments by name - Constructor arguments can also be specified by name by using - the name attribute of the + You can specify constructor argumetn by name using + name attribute of the <constructor-arg> element. <object name="exampleObject" type="SimpleApp.ExampleObject, SimpleApp"> @@ -1215,13 +1323,13 @@ namespace SimpleApp - Setter Injection + Setter-based dependency injection - Setter-based DI is realized by calling setter methods on your - objects after invoking a no-argument constructor or no-argument static - factory method to instantiate your object. + Setter-based DI is accomplished by the container invoking setter + 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 + The following eample shows a class that can only be dependency injected using pure setter injection. public class MovieLister @@ -1240,63 +1348,64 @@ namespace SimpleApp } - Constructor- or Setter-based DI? + Constructor-based or setter-based DI? The Spring team generally advocates the usage of setter injection, since a large number of constructor arguments can get unwieldy, especially when some properties are optional. The presence - of setter methods also makes objects of that class amenable to being - re-configured (or re-injected) at some later time (for management - purposes). + of setter properties also makes objects of that class amenable to + reconfigured or reinjection later. Managment through WMI is a + compelling use case. - Constructor-injection is favored by some purists though and - with good reason. Supplying all of an object's dependencies means - that that object is never returned to client (calling) code in a - less than totally initialized state. The flip side is that the - object becomes less amenable to re-configuration (or - re-injection). + Some purists favor constructor-based injection. Supplying all + object dependencies means that the object is always returned to + client (calling) code in a totally initialized state. The + disadvantage is that the object becomes less amenable to + reconfiguration and re-injection. - There is no hard and fast rule here. Use whatever type of DI - makes the most sense for a particular class; sometimes, when dealing - with third party classes to which you do not have the source, the - choice will already have been made for you - a legacy class may not - expose any setter methods, and so constructor injection will be the - only type of DI available to you. + Use the DI that makes the most sense for a particular class. + Sometimes, when dealing with third-party classes to which you do not + have the source, the choice is made for you. A legacy class may not + expose any setter methods, and so constructor injection is the only + available DI. Since you can mix both, Constructor- and Setter-based DI, it is a good rule of thumb to use constructor arguments for mandatory dependencies and setters for optional dependencies. - The IObjectFactory 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 the + The IAppliationContext supports constructor- + and setter-based DI for the objects it manages. It also supports + setter-based DI after some dependencies have already been supplied via + the constructor approach.. + + The configuration for the dependencies comes in the form of the IObjectDefinition class, which is used together with TypeConverters to know how to convert properties from one format to another. However, most users of Spring.NET will not be dealing with these classes directly (that is programatically), 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. + an entire Spring IoC container instance. Refer to for more information regarding + type conversion, and how you can design your classes to be convertible + by Spring.NET. - Object dependency resolution generally happens as follows: - + The container resolves object dependeices as: - The IObjectFactory is created and - initialized with a configuration which describes all the - objects. Most Spring.NET users use an - IObjectFactory or - IApplicationContext variant that supports XML - format configuration files. + The IApplicationContext is created and + initialized with a configuration that describes all the objects. + Most Spring.NET users use an IObjectFactory + or IApplicationContext variant 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, + static-factory method if you are using that instead of a normal + constructor. These dependencies apre provided to the object, when the object is actually created. @@ -1313,49 +1422,40 @@ namespace SimpleApp that property or constructor argument. By default Spring.NET can convert a value supplied in string format to all built-in types, such as int, long, - string, bool, etc. - Spring.NET uses TypeConverter definitions to - be able to convert string values to other, arbitrary types. - Refer to for more - information regarding type conversion, and how you can design - your classes to be convertible by Spring.NET. + string, bool, etc. The Spring 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 object. - However, the object properties themselves are not set until the object - is actually created. For those object that defined as singletons and - set to be pre-instantiated (such as singleton object in an - IApplicationContext), 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. + as the container is created, including the validation of whether + object reference properties refer to valid object. However, the object + properties themselves are not set until the object is actually + created. Objects that are defined as singletons and set to be + pre-instantiated, are created when the container is created. + Otherwise, the object is created only when it is requested. Creation + of an object potentially causes a graph of objects to be created as + the objects dependencies and its dependencies' dependencies (and so + on) are created and assigned. Circular Dependencies If you are using predominantly constructor injection it is - possible to write and configure your classes and objects such that - an unresolvable circular dependency scenario is created. + possible to create unresolvable circular dependency scenario. - Consider the scenario where you have class A, which requires - an instance of class B to be provided via constructor injection, and - class B, which requires an instance of class A to be provided via - constructor injection. If you configure object for classes A and B - to be injected into each other, the Spring IoC container will detect - this circular reference at runtime, and throw a + For example: Class A, which requires an instance of class B to + be provided via constructor injection, and class B, which requires + an instance of class A to be provided via constructor injection. If + you configure objects for classes A and B to be injected into each + other, the Spring IoC container detects this circular reference at + runtime, and throw a ObjectCurrentlyInCreationException. One possible solution to this issue is to edit the source code of some of your classes to be configured via setters instead of via - constructors. Another solution is not to use constructor injection - and stick to setter injection only. In other words, while it should - generally be avoided in all but the rarest of circumstances, it is - possible to configure circular dependencies with setter + constructors. Alternatively, avoid constructor injection and stick + to setter injection only. In other words, although it is not + recommended, you can configure circular dependencies with setter injection. Unlike the typical case (with no circular dependencies), a @@ -1365,45 +1465,42 @@ namespace SimpleApp You can generally trust Spring.NET to do the right thing. It - will detect configuration issues, such as references to non-existent + detects configuration problems, such as references to non-existent object definitions 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 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 IApplicationContext by - default pre-instantiates 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 - IApplicationContext is created, not later. If you - wish, you can still override this default behavior and set any of - these singleton objects to lazy-load (not be preinstantiated) + Spring sets properties and resolves dependencies as late as possible, + which is when the object is actually created. This means that a Spring + 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. For example, the object throws an + exception as a result of a missing or invalid property. This + potentially delayed visibility of some configuration issues is why + IApplicationContext 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 discover + configuration issues when the IApplicationContext + is created, not later. If you wish, you can still override this + default behavior and set any of these singleton objects will + lazy-initialize, rather than 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 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 or the IIntializingObject callback method) - will all be invoked. + If no circular dependencies exist, when one or more + collaborating objects are being injected into a dependent object, each + collaborating object is totally configured prior + to being passed into the dependent object. This means that if object A + has a dependency on object B, the Spring IoC container completely + configures object B prior to invoking the setter method on object A. + In other words, the object is instantiated (if not a pre-instantiated + singleton), its dependencies are set, and the relevant lifecycle + methods (such as a configured init method or the + IIntializingObject callback method) will all be + invoked. - Some examples + Examples of Dependency Injection First, an example of using XML-based configuration metadata for - setter-based DI. Find below a smallpart of a Spring XML configuration - file specifying some object definitions. <object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary"> + setter-based DI. A small part of a Spring XML configuration file + specifying some object definitions:<object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary"> <!-- setter injection using the ref attribute --> <property name="objectOne" ref="anotherExampleObject"/> @@ -1436,9 +1533,10 @@ public class ExampleObject } } - 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" type="Examples.ExampleObject, ExamplesLibrary"> + In the preceding example, 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" type="Examples.ExampleObject, ExamplesLibrary"> <constructor-arg name="objectOne" ref="anotherExampleObject"/> <constructor-arg name="objectTwo" ref="yetAnotherObject"/> <constructor-arg name="IntegerProperty" value="1"/> @@ -1462,9 +1560,9 @@ Public Class ExampleObject myObjectTwo = yetAnotherObject Me.i = i End Sub -End ClassAs you can see, the constructor arguments specified - in the object definition will be used to pass in as arguments to the - constructor of the ExampleObject. +End ClassGhe 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 is told to call a static factory method to return @@ -1502,16 +1600,16 @@ public class ExampleFactoryMethodObject // Property definitions -} 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. These arguments are optional. - 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, although in this - example it is. An instance (non-static) factory method, mentioned - previously, would be used in an essentially identical fashion (aside - from the use of the factory-object attribute instead of the type - attribute), so will not be detailed here. +}Arguments to the static factory method are supplied via + <constructor-arg/> elements, exactly the same + as if a constructor had actually been used. 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, although + in this example it is. An instance (non-static) factory method would + be used in an essentially identical fashion (aside from the use of the + factory-object attribute instead of the + type attribute), so will not be detailed + here. Note that Setter Injection and Constructor Injectionare not mutually exclusive. It is perfectly reasonable to use both for a @@ -1555,33 +1653,29 @@ public class MixedIocObject 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's - XML-based configuration metadata supports a number of sub-element types - within its <property/> and + XML-based configuration metadata supports sub-element types within its + <property/> and <constructor-arg/> elements for this - purpose.a + purpose. - Straight values (primitives, <literal>strings</literal>, - etc.) + Straight values (primitives, <literal>strings</literal>, and so + on) - The <value/> element specifies a - property or constructor argument as a human-readable string - representation. As mentioned previously, - TypeConverter instances are used to convert these - string values from a System.String to the actual - property or argument type. Custom TypeConverter - implementations in the - Spring.Objects.TypeConverters namespace are used to - augment the functionality offered by the .NET BCL's default - TypeConverter implementations. + The value attribute of the + <property/> element specifies a property or + constructor argument as a human-readable string representation. As + mentioned previously, TypeConverter instances are + used to convert these string values from a + System.String to the actual property or argument + type. In the following example, we use a SqlConnection from the - System.Data.SqlClient namespace of the BCL. This - class (like many other existing classes) can easily be used in a - Spring.NET object factory, as it offers a convenient public property - for configuration of its ConnectionString - property. + System.Data.SqlClient namespace. This class (like + many other existing classes) can easily configured by Spring as it + offers a convenient public property for configuration of its + ConnectionString property. <objects xmlns="http://www.springframework.net"> <object id="myConnection" type="System.Data.SqlClient.SqlConnection"> @@ -1595,10 +1689,11 @@ public class MixedIocObject The idref element - An idref element is simply a shorthand and error-proof way to - set a property to the String id or - name of another object in the - container.<object id="theTargetObject" type="..."> + An idref element is simply an error-proof way to pass the + id of another object in the container to a + <constructor-arg/> or + <property/> element.<object id="theTargetObject" type="..."> . . . </object> @@ -1606,28 +1701,30 @@ public class MixedIocObject <property name="targetName"> <idref object="theTargetObject"/> </property> -</object>This is exactly equivalent at runtime to the - following fragment:<object id="theTargetObject" type="..."> +</object>This above object definition snipped is + exactly equivalent (at runtime) to the + following snippit:<object id="theTargetObject" type="..."> . . . </object> <object id="theClientObject" type="..."> <property name="targetName" value="theTargetObject"/> -</object>The main reason the first form is preferable - to the second is that using the idref tag will - allow Spring.NET to validate at deployment time that the other - object actually exists. In the second variation, the class that is - having its targetName property injected is - forced to do its own validation, and that will only happen when that - class is actually instantiated by the container, possibly long after - the container is actually up and running. +</object>The first form is preferable to the second is + that using the idref tag allows the container to + validate at deployment time that the + referenced, named object actually exists. In the second variation, + no validation is performed on the value that is passed to the + targetName property of the client object. Typos + are only discovered (with ost mikely fatal results) when the + 'client' object is actually instantiated. If the 'client' bean is a + prototype bean, this typo and the resulting exception may only be + discovered long after the container is deployed. - Additionally, if the object being referred to is in the same - actual XML file, and the object name is the object - id, the local attribute may - be used, which will allow the XML parser itself to validate the - object name even earlier, at parse time. <property name="targetName"> + Additionally, if the reference object is in the same XML unit, + and the object name is the object id, the + local attribute may be used, which will allow the + XML parser itself to validate the object name even earlier, at XML + document parse time. <property name="targetName"> <idref local="theTargetObject"/> </property> @@ -1655,31 +1752,25 @@ public class MixedIocObject Referring to collaborating objects The ref element is the final element allowed - inside a 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, so to speak. As you - saw in the previous example to set collection properties, we used the - SqlConnection instance from the initial example as - a collaborator and specified it using a <ref object/> element. - 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, but there are 3 variations on how the id/name of the - other object may be specified, which determines how scoping and - validation is handled. + inside a <constructor-arg/> or + <property/> definition element. You use it to set the + value of the specified property to be a reference to another object + managed by the container (a collaborator). The referenced object is a + dependency of the object whose property will be set, and it is + initialzed on demand as needed before the property is set. (if it is a + singleton object it may bye initialized already by the container) All + references are ultimately just a reference to another object, but you + can specify the id/name of the other object in three different ways + which determines how scoping and validation is handled. Specifying the target object by using the object attribute of the ref tag - is the most general form, and will allow creating a reference to any - object in the same IObjectFactory / - IApplicationContext (whether or not in the same XML - file), or parent IObjectFactory / - IApplicationContext. The value of the - object attribute may be the same as either the - id attribute of the target object, or one of the - values in the name attribute of the target + is the most general form, and will allows creation of a reference to + any object in the same container (whether or not in the same XML + file), or parent container. The value of the + 'object' attribute may be the same as the + 'id' attribute of the target object, or as one of + the values in the 'name' attribute of the target object.<ref object="someObject"/> Specifying the target object by using the @@ -1693,34 +1784,39 @@ public class MixedIocObject same XML file.<ref local="someObject"/> Specifying the target object by using the - parent attribute allows a reference to be created - to an object that is in a parent IObjectFactory - (orIApplicationContext) of the current - IObjectFactory (or - IApplicationContext). The value of the - parent attribute may be the same as either the - id attribute of the target object, or one of the - values in the name attribute of the target object, - and the target object must be in a - parent IObjectFactory or - IApplicationContext of the current one. The main - use of this object reference variant is when there is a need to wrap - an existing object in a parent context with some sort of proxy (which - may have the same name as the parent), and needs the original object - so it may wrap it. - - <ref parent="someObject"/> + 'parent' attribute creates a reference to an object + that is in a parent container of the current container. The value of + the 'parent' attribute may be the same as either + the 'id' attribute of the target object, or one of + the values in the 'name' attribute of the target + object, and the target object must be in a parent container to the + current one. You us ethis object reference variant mainly when you + have a hierarchy of containers and you want to wrap an existing bean + in a parent container with some sort of proxy which will have the same + name as the parent bean.<!-- in the parent context --> +<object id="AccountService" type="MyApp.SimpleAccountService, MyApp"> +<!-- insert dependencies as required as here --> +</object><!-- in the child (descendant) context --> +<object id="AccountService" <-- notice that the name of this bean is the same as the name of the 'parent' bean + type="Spring.Aop.Framework.ProxyFactoryBean, Spring.Aop"> + <property name="target"> + <ref parent="AccountService"/> <-- notice how we refer to the parent bean + </property> + <!-- insert other configuration and dependencies as required as here --> +</object> - Inline objects + Inner objects - An object element inside the - property element is used to define an object value - inline, instead of referring to an object defined elsewhere in the - container. The inline object definition does not need to have any id - or name defined (indeed, if any are defined, they will be ignored). - <object id="outer" type="..."> + An <object/> element inside the + <constructor-arg/> or <property/> + element defines so called inner object. An inner object definition + does not need to have any id or name defined, and it is best not to + even specify any id or name value because the id or name value simply + will be ignored by the container. + + <object id="outer" type="..."> <!-- Instead of using a reference to target, just use an inner object --> @@ -1731,6 +1827,12 @@ public class MixedIocObject </object> </property> </object> + + In the specific case of inner objects, the 'singleton' flag and + any 'id' or 'name' attribute are effectively ignored. Inner objects + are always anonymous and they are always scoped as prototypes. It is + not possible to inject inner objects into collaborating beans other + than into the enclosing object. @@ -1791,8 +1893,8 @@ public class MixedIocObject additive behavior for collection properties that are exposed in this manner. - Note that the value of a Dictionary entry, or a set - value, can also again be any of the elements: + The value of a Dictionary entry, or a set value, can + also again be any of the following elements: (object | ref | idref | expression | list | set | dictionary | name-values | value | null)