From 187cd43729900c7cc4b203a6581372a0b77c937a Mon Sep 17 00:00:00 2001 From: Thomas Trageser Date: Tue, 30 Oct 2012 21:52:41 +0000 Subject: [PATCH] Updated documentation and add section for using the [Autowire] attribute inlcuding [Value] and [Qualifier] --- doc/reference/src/objects.xml | 326 ++++++++++++++++++++++++++++++++++ 1 file changed, 326 insertions(+) diff --git a/doc/reference/src/objects.xml b/doc/reference/src/objects.xml index 94e4848a..b34d9920 100644 --- a/doc/reference/src/objects.xml +++ b/doc/reference/src/objects.xml @@ -2702,11 +2702,337 @@ source.OnClick(); // First eventListener1.HandleEvent is invoked, then eventList arbitrarily resolved. Instead, if no unique object definition is available, an Exception will be thrown. + In the latter scenario, you have several options: + + + + Abandon autowiring in favor of explicit wiring. + + + + Avoid autowiring for a bean definition by setting its + autowire-candidate attributes to false as described in the next + section. + + + + Designate a single bean definition as the primary candidate by + setting the primary attribute of its <object/> element to + true. + + + + Implement the more fine-grained control available with + annotation-based configuration. + + + 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. + + + Excluding a bean from autowiring + + On a per-bean basis, you can exclude a bean from autowiring. In + Spring's XML format, set the autowire-candidate + attribute of the <object/> element to + false; the container makes that specific object + definition unavailable to the autowiring infrastructure (including + annotation style configurations such as + [Autowired]). + + You can also limit autowire candidates based on pattern-matching + against object names. The top-level + <objects/> element accepts one or more + patterns within its default-autowire-candidates + attribute. For example, to limit autowire candidate status to any + object whose name ends with Repository, provide a + value of *Repository. To provide multiple + patterns, define them in a comma-separated list. An explicit value of + true or false for a object + definitions autowire-candidate attribute always + takes precedence, and for such objects, the pattern matching rules do + not apply. + + These techniques are useful for objects that you never want to + be injected into other objects by autowiring. It does not mean that an + excluded object cannot itself be configured using autowiring. Rather, + the object itself is not a candidate for autowiring other + objects. + + + + Using [Autowire] Attribute for fine-grained control + + The [Autowire] attribute in the + Spring.Objects.Factory.Attributes namespace can be + used to mark a variable, property or method for automatically wiring + by injection. It works similar to the autowire configuration described + in the paragraph above with a byType setting, + except that you can define variables, properties or methods + specifically that you want to autowire. In a latter paragraph you will + see how you can even further define the object or value to + inject. + + To get the [Autowire] attribute working you + need to add the autowire post processer into your spring configuration + file. + + <object type="Spring.Objects.Factory.Attributes.RequiredAttributeObjectPostProcessor, Spring.Core"/> + + To use the autowire attribute on a variable, it can be private + or public. The folowing code shows how to use the attribute. The post + processer will try to find a registered object that is from the + requested type. If more than one registered objects are found from + that type you will get an ObjectCreationException. + To prevent or control this situation you can use the + primary attribute in the + <object> defintion, later you will see an + example for this situation. + + public class SomeObject +{ + ... + + [Autowired] + private IFoo hello; + + [Autowired] + public IFoo Hello { get; set; } + + ... +} + + You can also use the autowire attribute to inject into methods. + In this case all parameters are looked up and found objects of the + requested type injected into the method parameters. You are not + restricted to a single method parameter. + + public class SomeObject +{ + public IFoo hello; + + [Autowired] + private void Prepare(IFoo hello) + { + this.hello = hello; + } +} + + If you have several objects defined from the same type you can + make the following change to the <object> + definition and define one of the objects as + primary. In case the container will find several + objects from a requested type but will check if there is a + primary object and if true will use this object + instead. The container will not throw a + ObjectCreationException. If the container finds + more than one objects for the requested type as + primary, the container will throw a + ObjectCreationException. + + <object id="HelloFoo" type="Spring.Objects.Factory.Attributes.ByType.HelloFoo, Spring.Core.Tests" + primary="true"/> + + You can also use the autowire attribute for injection in to a + List<T>, ISet<T> or Dictionary<string, T> type. In + this case the container looks up for the requested type defined in the + generic part of the definition and will create a List<T>, + HashedSet<T> or Dictionary<string, T> with all found + objects injected. For the dictionary type the key is the registered + name of the object. + + public class AutowireLists +{ + [Autowired] + public IList<IFoo> foosList; + + [Autowired] + public Spring.Collections.Generic.ISet<IFoo> foosSet; + + [Autowired] + public IDictionary<string, IFoo> foosDictionary; +} + + By default all found autowired objects are treated as required. + This means if the container can't find an registered object of the + requested type it will throw on + ObjectCreationException. For this situation you can + use the Required property of the + [Autowire] attribute to mark an object as not + required and therefore will not throw an + ObjectCreationException. + + public class AutowirePropertyNotRequired +{ + [Autowired(Required = false)] + public IFoo Hello { get; set; } +} + + + + Using [Value] attribute for fine grained autowiring + injection + + The [Autowire] attribute is wiring + byType and therefore not fine-grained enough for + some situations. You can also not inject values from loaded + PropertyPlaceHolder files. For these cases you can use the + [Value] attribute instead and this allows the + following situations: + + Inject an object by their Id: + + public class AutowireViaValue +{ + [Value("@(CiaoFoo)")] + public IFoo ciao; +} + + This works on private variables and also on properties. + + You can also use this scenario for autowiring with a + method: + + public class AutowireMethodWithValue +{ + public IFoo ciao; + + [Autowired] + private void Prepare([Value("@(CiaoFoo)")] IFoo ciao) + { + this.ciao = ciao; + } +} + + You can also use the [Value] attribute to access properties from + a PropertyPlaceHolder configuration: + + public class AutowirePropertyPlaceHolder +{ + [Value("${greeting}")] + public string greeting; +} + + Basically you can use the full Spring Expression Language, here + we only showed these two examples of how you could use the + [Value] attribute. + + + + Using the plain [Qualifier] attribute to fine-grain the + autowiring finding process + + The [Qualifier] attribute allows you to + define a qualification property on top of giving the object a name. + This can be used for defining several objects from the same type and + inject different values, later via autowiring you can refer to this + definition property. Here an example. First we create our basic + object. + + public interface IFoo +{ + string Say(); +} + +public class SayFoo : IFoo +{ + private string _message; + + public string Say() + { + return "hello"; + } +} + + + Now we define our objects within our spring configuration file. + We create tow object that use the same base object type but we inject + different values. If we you use the [Autowire] we + would get an ObjectCreationException because we two + objects of the same type and most likely we would not got the object + we wanted. + + <object id="HelloFoo" type="Spring.Objects.Factory.Attributes.ByType.SayFoo, Spring.Core.Tests"> + <qualifier value="hello" /> + <property name="_message" value="Hello" /> +</object> + +<object id="CiaoFoo" type="Spring.Objects.Factory.Attributes.ByType.SayFoo, Spring.Core.Tests"> + <qualifier value="ciao" /> + <property name="_message" value="Hello" /> +</object> + + With the <qualifier> element in our + object defintion we provided further information that we can use + during the autowire process. See the code below and how to use the + [Qualifier] attribute to inject the object we want + without getting a ObjectCreationException. + + public class AutowireQithQualifier +{ + [Autowired] + [Qualifier("ciao")] + public IFoo Ciao { get; set; } +} + + + + Using a inherited [Qualifier] attribute with meta + properties + + The inherited QualifierAttribute class allows + you to define an object by more properties than a single qualifier + value. You can define objects by fine grained, own defined, properties + within a attribute. The first thing you need to do is to create a new + attribute derived from QualifierAttribute and + define your properties. + + public class DialectAttribute : QualifierAttribute +{ + private string _language = ""; + public string Language { get { return _language; } set { _language = value; } } +} + + The next step is to define your objects and the meta information + attached to them. The attributes you define within the + <qualifier> element are the same as your + peroperties in your created attribute. + + <object id="HelloFoo" type="Spring.Objects.Factory.Attributes.ByType.SayFoo, Spring.Core.Tests"> + <qualifier type="Spring.Objects.Factory.Attributes.ByQualifierAttribute.DialectAttribute"> + <attribute key="Language" value="English" /> + </qualifier> + <property name="_message" value="Hello" /> +</object> + +<object id="CiaoFoo" type="Spring.Objects.Factory.Attributes.ByType.SayFoo, Spring.Core.Tests"> + <qualifier type="Spring.Objects.Factory.Attributrf4res.ByQualifierAttribute.DialectAttribute"> + <attribute key="Language" value="Italian" /> + </qualifier> + <property name="_message" value="Ciao" /> +</object> + + Now you have defined your objects with new meta information. To + use this meta information within the autowiring process you need to + add your created attribute as additional annotation to the [Autowire] + attributes in your code. The properties you use within the added + attribute will be matched with all registered objects. If they + properties are matching the object is used for injection. If more then + one object is found in the matching process and no object is defined + as primary a + ObjectCreationException is thrown. + + public class AutowireByMetaInformation +{ + [Autowired] + [Dialect(Language = "Italian")] + public IFoo ciao; +} +