0% found this document useful (0 votes)
847 views516 pages

Spring Net Reference

Copies of this document may be made for your own use and for distribution to others. Copies may be made provided that you do not charge any fee for such copies. Each copy contains this Copyright notice, whether distributed in print or electronically.

Uploaded by

a9925492
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
847 views516 pages

Spring Net Reference

Copies of this document may be made for your own use and for distribution to others. Copies may be made provided that you do not charge any fee for such copies. Each copy contains this Copyright notice, whether distributed in print or electronically.

Uploaded by

a9925492
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Reference Documentation

Version 1.3.2

Last Updated August 1, 2011 (Latest documentation)

Copyright 2004-2008 Mark Pollack, Rick Evans, Aleksandar Seovic, Bruno Baia, Erich Eichinger, Federico Spinazzi, Rob Harrop, Griffin Caprio, Ruben Bartelink, Choy Rim, Erez Mazor, Stephen Bohlen, The Spring Java Team

Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.

1. Preface ................................................................................................................................................ 1 2. Introduction ......................................................................................................................................... 2 2.1. Overview .................................................................................................................................... 2 2.2. Background ................................................................................................................................. 2 2.3. Modules ...................................................................................................................................... 3 2.4. Usage Scenarios .......................................................................................................................... 4 2.5. Quickstart applications ................................................................................................................. 5 2.6. Associated Spring.NET Projects ................................................................................................... 6 2.7. License Information ..................................................................................................................... 6 2.8. Support ....................................................................................................................................... 6 3. Background information ....................................................................................................................... 7 3.1. Inversion of Control .................................................................................................................... 7 4. Migrating from 1.1 M2 ........................................................................................................................ 8 4.1. Introduction ................................................................................................................................. 8 4.2. Important Changes ...................................................................................................................... 8 4.2.1. Namespaces .................................................................................................................. 8 4.2.2. Core ............................................................................................................................. 9 4.2.3. Web ............................................................................................................................. 9 4.2.4. Data ............................................................................................................................. 9 4.3. Support for .NET 4 ...................................................................................................................... 9 I. Core Technologies .............................................................................................................................. 10 5. The IoC container ........................................................................................................................ 11 5.1. Introduction ................................................................................................................... 11 5.2. Container overview ........................................................................................................ 11 5.2.1. Configuration metadata ............................................................................. 12 5.2.2. Instantiating a container ............................................................................ 13 5.2.3. Using the container ................................................................................... 17 5.2.4. Object definition overview ........................................................................ 17 5.2.5. Instantiating objects .................................................................................. 19 5.2.6. Object creation of generic types ................................................................. 21 5.3. Dependencies ................................................................................................................ 23 5.3.1. Dependency injection ................................................................................ 23 5.3.2. Dependencies and configuration in detail .................................................... 30 5.3.3. Declarative Event Listener Registration ...................................................... 39 5.3.4. Using depends-on ..................................................................................... 41 5.3.5. Lazily-initialized objects ............................................................................ 41 5.3.6. Autowiring collaborators ........................................................................... 42 5.3.7. Checking for dependencies ........................................................................ 43 5.3.8. Method injection ....................................................................................... 44 5.3.9. Setting a reference using the members of other objects and classes. ............... 47 5.3.10. Provided IFactoryObject implementations ................................................. 51 5.4. Object Scopes ............................................................................................................... 51 5.4.1. The singleton scope .................................................................................. 52 5.4.2. The prototype scope .................................................................................. 52 5.4.3. Singleton objects with prototype-object dependencies .................................. 53 5.4.4. Request, session and web application scopes ............................................... 53 5.5. Type conversion ............................................................................................................ 53 5.5.1. Type Conversion for Enumerations ............................................................ 54 5.5.2. Built-in TypeConverters ............................................................................ 54

Spring Framework (Version 1.3.2)

ii

The Spring.NET Framework 5.5.3. Custom Type Conversion .......................................................................... 55 5.6. Customizing the nature of an object ................................................................................ 57 5.6.1. Lifecycle interfaces ................................................................................... 57 5.6.2. IApplicationContextAware and IObjectNameAware .................................... 58 5.7. Object definition inheritance .......................................................................................... 59 5.8. Container extension points ............................................................................................. 60 5.8.1. Obtaining an IFactoryObject, not its product ............................................... 61 5.9. Container extension points ............................................................................................. 61 5.9.1. Customizing objects with IObjectPostProcessors ......................................... 61 5.9.2. Customizing configuration metadata with ObjectFactoryPostProcessors ........ 66 5.9.3. Customizing instantiation logic using IFactoryObjects ................................. 71 5.10. The IApplicationContext .............................................................................................. 72 5.10.1. IObjectFactory or IApplicationContext? .................................................... 73 5.11. Configuration of IApplicationContext ........................................................................... 73 5.11.1. Registering custom parsers ...................................................................... 74 5.11.2. Registering custom resource handlers ....................................................... 75 5.11.3. Registering Type Aliases ......................................................................... 76 5.11.4. Registering Type Converters .................................................................... 77 5.12. Added functionality of the IApplicationContext ............................................................. 77 5.12.1. Context Hierarchies ................................................................................. 77 5.12.2. Using IMessageSource ............................................................................ 78 5.12.3. Using resources within Spring.NET .......................................................... 80 5.12.4. Loosely coupled events ........................................................................... 80 5.12.5. Event notification from IApplicationContext ............................................. 81 5.13. Customized behavior in the ApplicationContext ............................................................. 83 5.13.1. The IApplicationContextAware marker interface ....................................... 83 5.13.2. The IObjectPostProcessor ........................................................................ 83 5.13.3. The IObjectFactoryPostProcessor ............................................................. 83 5.13.4. The PropertyPlaceholderConfigurer .......................................................... 83 5.14. Configuration of ApplicationContext without using XML ............................................... 83 5.15. Service Locator access ................................................................................................. 84 5.16. Stereotype attributes ..................................................................................................... 85 6. The IObjectWrapper and Type conversion ..................................................................................... 86 6.1. Introduction ................................................................................................................... 86 6.2. Manipulating objects using the IObjectWrapper ............................................................... 86 6.2.1. Setting and getting basic and nested properties ............................................ 86 6.2.2. Other features worth mentioning ................................................................ 88 6.3. Type conversion ............................................................................................................ 88 6.3.1. Type Conversion for Enumerations ............................................................ 89 6.4. Built-in TypeConverters ................................................................................................. 89 6.4.1. Custom type converters ............................................................................. 90 7. Resources .................................................................................................................................... 91 7.1. Introduction ................................................................................................................... 91 7.2. The IResource interface ................................................................................................. 91 7.3. Built-in IResource implementations ................................................................................ 92 7.3.1. Registering custom IResource implementations ........................................... 92 7.4. The IResourceLoader ..................................................................................................... 93 7.5. The IResourceLoaderAware interface ............................................................................. 93 7.6. Application contexts and IResource paths ....................................................................... 94

Spring Framework (Version 1.3.2)

iii

The Spring.NET Framework 8. Threading and Concurrency Support ............................................................................................. 95 8.1. Introduction ................................................................................................................... 95 8.2. Thread Local Storage ..................................................................................................... 95 8.3. Synchronization Primitives ............................................................................................. 96 8.3.1. ISync ........................................................................................................ 96 8.3.2. SyncHolder ............................................................................................... 96 8.3.3. Latch ........................................................................................................ 97 8.3.4. Semaphore ................................................................................................ 97 9. Object Pooling ............................................................................................................................. 99 9.1. Introduction ................................................................................................................... 99 9.2. Interfaces and Implementations ...................................................................................... 99 10. Spring.NET miscellanea ............................................................................................................ 100 10.1. Introduction ............................................................................................................... 100 10.2. PathMatcher ............................................................................................................... 100 10.2.1. General rules ......................................................................................... 100 10.2.2. Matching filenames ............................................................................... 100 10.2.3. Matching subdirectories ......................................................................... 101 10.2.4. Case does matter, slashes don't ............................................................... 101 11. Expression Evaluation ............................................................................................................... 103 11.1. Introduction ............................................................................................................... 103 11.2. Evaluating Expressions ............................................................................................... 103 11.3. Language Reference ................................................................................................... 104 11.3.1. Literal expressions ................................................................................. 104 11.3.2. Properties, Arrays, Lists, Dictionaries, Indexers ....................................... 105 11.3.3. Methods ................................................................................................ 106 11.3.4. Operators .............................................................................................. 106 11.3.5. Assignment ........................................................................................... 109 11.3.6. Expression lists ..................................................................................... 109 11.3.7. Types .................................................................................................... 109 11.3.8. Type Registration .................................................................................. 110 11.3.9. Constructors .......................................................................................... 110 11.3.10. Variables ............................................................................................. 110 11.3.11. Ternary Operator (If-Then-Else) ........................................................... 111 11.3.12. List Projection and Selection ................................................................ 111 11.3.13. Collection Processors and Aggregators .................................................. 112 11.3.14. Spring Object References ..................................................................... 115 11.3.15. Lambda Expressions ............................................................................ 116 11.3.16. Delegate Expressions ........................................................................... 117 11.3.17. Null Context ....................................................................................... 117 11.4. Classes used in the examples ...................................................................................... 117 12. Validation Framework .............................................................................................................. 119 12.1. Introduction ............................................................................................................... 119 12.2. Example Usage .......................................................................................................... 119 12.3. Validator Groups ....................................................................................................... 121 12.4. Validators .................................................................................................................. 121 12.4.1. Condition Validator ............................................................................... 121 12.4.2. Required Validator ................................................................................ 122 12.4.3. Regular Expression Validator ................................................................. 122 12.4.4. Generic Validator .................................................................................. 123

Spring Framework (Version 1.3.2)

iv

The Spring.NET Framework 12.4.5. Conditional Validator Execution ............................................................. 12.5. Validator Actions ....................................................................................................... 12.5.1. Error Message Action ............................................................................ 12.5.2. Exception Action ................................................................................... 12.5.3. Generic Actions .................................................................................... 12.6. Validator References .................................................................................................. 12.7. Progammatic usage .................................................................................................... 12.8. Usage tips within ASP.NET ....................................................................................... 12.8.1. Rendering Validation Errors ................................................................... 12.8.2. How Validate() and Validation Controls play together ............................. 13. Aspect Oriented Programming with Spring.NET ........................................................................ 13.1. Introduction ............................................................................................................... 13.1.1. AOP concepts ....................................................................................... 13.1.2. Spring.NET AOP capabilities ................................................................. 13.1.3. AOP Proxies in Spring.NET .................................................................. 13.2. Pointcut API in Spring.NET ....................................................................................... 13.2.1. Concepts ............................................................................................... 13.2.2. Operations on pointcuts ......................................................................... 13.2.3. Convenience pointcut implementations ................................................... 13.2.4. Custom pointcuts ................................................................................... 13.3. Advice API in Spring.NET ......................................................................................... 13.3.1. Advice Lifecycle ................................................................................... 13.3.2. Advice types ......................................................................................... 13.4. Advisor API in Spring.NET ....................................................................................... 13.5. Using the ProxyFactoryObject to create AOP proxies ................................................... 13.5.1. Basics ................................................................................................... 13.5.2. ProxyFactoryObject Properties ............................................................... 13.5.3. Proxying Interfaces ................................................................................ 13.5.4. Proxying Classes ................................................................................... 13.5.5. Concise proxy definitions ...................................................................... 13.6. Proxying mechanisms ................................................................................................. 13.6.1. InheritanceBasedAopConfigurer ............................................................. 13.7. Creating AOP Proxies Programatically with the ProxyFactory ...................................... 13.8. Manipulating Advised Objects .................................................................................... 13.9. Using the "autoproxy" facility .................................................................................... 13.9.1. Autoproxy object definitions .................................................................. 13.9.2. Using attribute-driven auto-proxying ...................................................... 13.10. Using AOP Namespace ............................................................................................ 13.11. Using TargetSources ................................................................................................ 13.11.1. Hot swappable target sources ............................................................... 13.11.2. Pooling target sources .......................................................................... 13.11.3. Prototype target sources ....................................................................... 13.11.4. ThreadLocal target sources ................................................................... 13.12. Defining new Advice types ....................................................................................... 13.13. Further reading and resources ................................................................................... 14. Aspect Library .......................................................................................................................... 14.1. Introduction ............................................................................................................... 14.2. Caching ..................................................................................................................... 14.3. Exception Handling .................................................................................................... 123 124 124 124 125 125 126 126 127 128 130 130 130 131 132 132 133 133 134 136 137 137 137 142 142 143 143 144 146 146 147 148 148 149 150 150 155 155 156 157 157 158 159 159 159 160 160 160 162

Spring Framework (Version 1.3.2)

The Spring.NET Framework 14.3.1. Language Reference .............................................................................. 14.4. Logging ..................................................................................................................... 14.5. Retry ......................................................................................................................... 14.5.1. Language Reference .............................................................................. 14.6. Transactions ............................................................................................................... 14.7. Parameter Validation .................................................................................................. 15. Common Logging ..................................................................................................................... 15.1. Introduction ............................................................................................................... 16. Testing ..................................................................................................................................... 16.1. Introduction ............................................................................................................... 16.2. Unit testing ................................................................................................................ 16.3. Integration testing ...................................................................................................... 16.3.1. Context management and caching ........................................................... 16.3.2. Dependency Injection of test fixtures ...................................................... 16.3.3. Transaction management ........................................................................ 16.3.4. Convenience variables ........................................................................... II. Middle Tier Data Access .................................................................................................................. 17. Transaction management ........................................................................................................... 17.1. Introduction ............................................................................................................... 17.2. Motivations ................................................................................................................ 17.3. Key Abstractions ....................................................................................................... 17.4. Resource synchronization with transactions ................................................................. 17.4.1. High-level approach .............................................................................. 17.4.2. Low-level approach ............................................................................... 17.5. Declarative transaction management ............................................................................ 17.5.1. Understanding Spring's declarative transaction implementation ................. 17.5.2. Example of declarative transaction implementation .................................. 17.5.3. Declarative transactions using the transaction namespace ......................... 17.5.4. Transaction attribute settings .................................................................. 17.5.5. Declarative Transactions using AutoProxy .............................................. 17.6. Programmatic transaction management ........................................................................ 17.6.1. Using the TransactionTemplate .............................................................. 17.6.2. Using the PlatformTransactionManager .................................................. 17.7. Choosing between programmatic and declarative transaction management ..................... 17.8. Transaction lifecycle and status information ................................................................ 18. DAO support ............................................................................................................................ 18.1. Introduction ............................................................................................................... 18.2. Consistent exception hierarchy .................................................................................... 18.3. Consistent abstract classes for DAO support ................................................................ 19. DbProvider ............................................................................................................................... 19.1. Introduction ............................................................................................................... 19.2. IDbProvider and DbProviderFactory ........................................................................... 19.3. XML based configuration ........................................................................................... 19.4. Connection String management ................................................................................... 19.5. Additional IDbProvider implementations ..................................................................... 19.5.1. UserCredentialsDbProvider .................................................................... 19.5.2. MultiDelegatingDbProvider ................................................................... 20. Data access using ADO.NET .................................................................................................... 20.1. Introduction ............................................................................................................... 165 165 167 168 168 168 170 170 171 171 171 171 172 172 174 175 176 177 177 177 179 180 181 181 181 182 183 185 190 191 192 192 194 195 195 196 196 196 199 201 201 201 204 205 206 206 207 209 209

Spring Framework (Version 1.3.2)

vi

The Spring.NET Framework 20.2. Motivations ................................................................................................................ 20.3. Provider Abstraction .................................................................................................. 20.3.1. Creating an instance of IDbProvider ....................................................... 20.4. Namespaces ............................................................................................................... 20.5. Approaches to Data Access ........................................................................................ 20.6. Introduction to AdoTemplate ...................................................................................... 20.6.1. Execute Callback ................................................................................... 20.6.2. Execute Callback in .NET 2.0 ................................................................ 20.6.3. Execute Callback in .NET 1.1 ................................................................ 20.6.4. Quick Guide to AdoTemplate Methods ................................................... 20.6.5. Quick Guide to AdoTemplate Properties ................................................. 20.7. Transaction Management ............................................................................................ 20.8. Exception Translation ................................................................................................. 20.9. Parameter Management .............................................................................................. 20.9.1. IDbParametersBuilder ............................................................................ 20.9.2. IDbParameters ....................................................................................... 20.9.3. Parameter names in SQL text ................................................................. 20.10. Custom IDataReader implementations ....................................................................... 20.11. Basic data access operations ..................................................................................... 20.11.1. ExecuteNonQuery ................................................................................ 20.11.2. ExecuteScalar ...................................................................................... 20.12. Queries and Lightweight Object Mapping .................................................................. 20.12.1. ResultSetExtractor ............................................................................... 20.12.2. RowCallback ....................................................................................... 20.12.3. RowMapper ........................................................................................ 20.12.4. Query for a single object ...................................................................... 20.12.5. Query using a CommandCreator ........................................................... 20.13. DataTable and DataSet ............................................................................................. 20.13.1. DataTables .......................................................................................... 20.13.2. DataSets .............................................................................................. 20.14. TableAdapters and participation in transactional context ............................................. 20.15. Database operations as Objects ................................................................................. 20.15.1. AdoQuery ........................................................................................... 20.15.2. MappingAdoQuery .............................................................................. 20.15.3. AdoNonQuery ..................................................................................... 20.15.4. Stored Procedure ................................................................................. 21. Object Relational Mapping (ORM) data access .......................................................................... 21.1. Introduction ............................................................................................................... 21.2. NHibernate ................................................................................................................ 21.2.1. Resource management ........................................................................... 21.2.2. Transaction Management ....................................................................... 21.2.3. SessionFactory set up in a Spring container ............................................. 21.2.4. Implementing DAOs based on plain Hibernate 1.2/2.x API ....................... 21.2.5. Declarative transaction demarcation ........................................................ 21.2.6. Programmatic transaction demarcation .................................................... 21.2.7. Transaction management strategies ......................................................... 21.2.8. Web Session Management ..................................................................... 21.2.9. Session Scope ....................................................................................... 21.2.10. Integration Testing ............................................................................... 210 211 212 212 212 213 213 213 215 216 218 219 219 219 220 220 221 221 221 222 222 222 222 223 224 225 225 227 228 228 230 231 231 232 232 233 235 235 236 236 237 238 240 242 244 245 245 246 246

Spring Framework (Version 1.3.2)

vii

The Spring.NET Framework III. The Web ........................................................................................................................................ 248 22. Spring.NET Web Framework .................................................................................................... 249 22.1. Introduction to Spring.NET Web Framework ............................................................... 249 22.2. Comparing Spring.NET and ASP.NET ........................................................................ 250 22.3. Automatic context loading and hierarchical contexts .................................................... 251 22.3.1. Configuration of a web application ......................................................... 251 22.3.2. Context hierarchy .................................................................................. 253 22.4. Dependency injection for ASP.NET pages ................................................................... 254 22.4.1. Injecting dependencies into controls ....................................................... 255 22.4.2. Injecting dependencies into custom HTTP modules ................................. 256 22.4.3. Injecting dependencies into HTTP handlers and handler factories .............. 256 22.4.4. Injecting dependencies in custom ASP.NET providers ............................. 257 22.4.5. Customizing control dependency injection .............................................. 258 22.5. Web object scopes ..................................................................................................... 259 22.6. Support for ASP.NET 1.1 master pages in Spring.Web ................................................. 259 22.6.1. Linking child pages to their master page file ........................................... 261 22.7. Bidirectional data binding and data model management ................................................ 261 22.7.1. Data binding under the hood .................................................................. 265 22.7.2. Using DataBindingPanel ........................................................................ 270 22.7.3. Customizing model persistence .............................................................. 271 22.8. Localization and message sources ............................................................................... 271 22.8.1. Working with localizers ......................................................................... 272 22.8.2. Automatic localization with localizers ("push" localization) ...................... 273 22.8.3. Global message sources ......................................................................... 274 22.8.4. Applying resources manually ("pull" localization) ................................... 275 22.8.5. Localizing images within a web application ............................................ 276 22.8.6. User culture management ....................................................................... 276 22.8.7. Changing cultures .................................................................................. 277 22.9. Result mapping .......................................................................................................... 278 22.9.1. Registering user defined transfer modes .................................................. 280 22.10. Client-side scripting ................................................................................................. 281 22.10.1. Registering scripts within the head HTML section ................................. 281 22.10.2. Adding CSS definitions to the head section ........................................... 282 22.10.3. Well-known directories ........................................................................ 282 22.11. Spring user controls ................................................................................................. 282 22.11.1. Validation controls .............................................................................. 282 22.11.2. Databinding controls ............................................................................ 283 22.11.3. Calendar control .................................................................................. 283 22.11.4. Panel control ....................................................................................... 283 23. ASP.NET AJAX ....................................................................................................................... 284 23.1. Introduction ............................................................................................................... 284 23.2. Web Services ............................................................................................................. 284 23.2.1. Exposing Web Services ......................................................................... 284 23.2.2. Calling Web Services by using JavaScript ............................................... 285 24. Spring.NET ASP.NET MVC Infrastructure for ASP.NET MVC 2.0 ............................................. 286 24.1. Introduction to Spring.NET ASP.NET MVC Infrastructure ........................................... 286 24.2. Automatic context loading and hierarchical contexts .................................................... 286 24.2.1. Configuration of a ASP.NET MVC Application ...................................... 286 24.2.2. Customizing the Behavior of the ASP.NET MVC Application Class ......... 287

Spring Framework (Version 1.3.2)

viii

The Spring.NET Framework 24.3. Web object scopes ..................................................................................................... 289 25. Spring.NET ASP.NET MVC Infrastructure for ASP.NET MVC 3.0 ............................................. 290 25.1. Introduction to Spring.NET ASP.NET MVC Infrastructure ........................................... 290 25.2. Automatic context loading and hierarchical contexts .................................................... 290 25.2.1. Configuration of a ASP.NET MVC Application ...................................... 290 25.2.2. Customizing the Behavior of the ASP.NET MVC Application Class ......... 291 25.3. Web object scopes ..................................................................................................... 292 IV. Services ......................................................................................................................................... 294 26. Introduction to Spring Services ................................................................................................. 295 26.1. Introduction ............................................................................................................... 295 27. .NET Remoting ......................................................................................................................... 297 27.1. Introduction ............................................................................................................... 297 27.2. Publishing SAOs on the Server ................................................................................... 297 27.2.1. SAO Singleton ...................................................................................... 297 27.2.2. SAO SingleCall ..................................................................................... 298 27.2.3. IIS Application Configuration ................................................................ 299 27.3. Accessing a SAO on the Client .................................................................................. 300 27.4. CAO best practices .................................................................................................... 301 27.5. Registering a CAO object on the Server ...................................................................... 301 27.5.1. Applying AOP advice to exported CAO objects ...................................... 302 27.6. Accessing a CAO on the Client .................................................................................. 302 27.6.1. Applying AOP advice to client side CAO objects. ................................... 302 27.7. XML Schema for configuration .................................................................................. 303 27.8. Additional Resources ................................................................................................. 303 28. .NET Enterprise Services .......................................................................................................... 304 28.1. Introduction ............................................................................................................... 304 28.2. Serviced Components ................................................................................................. 304 28.3. Server Side ................................................................................................................ 304 28.4. Client Side ................................................................................................................ 306 29. Web Services ........................................................................................................................... 307 29.1. Introduction ............................................................................................................... 307 29.2. Server-side ................................................................................................................. 307 29.2.1. Removing the need for .asmx files .......................................................... 307 29.2.2. Injecting dependencies into web services ................................................ 308 29.2.3. Exposing POCOs as Web Services ......................................................... 310 29.2.4. Exporting an AOP Proxy as a Web Service ............................................. 311 29.3. Client-side ................................................................................................................. 312 29.3.1. Using VS.NET generated proxy ............................................................. 312 29.3.2. Generating proxies dynamically ............................................................. 312 29.3.3. Configuring the proxy instance .............................................................. 313 30. Windows Communication Foundation (WCF) ............................................................................ 314 30.1. Introduction ............................................................................................................... 314 30.2. Configuring WCF services via Dependency Injection ................................................... 314 30.2.1. Dependency Injection ............................................................................ 314 30.3. Apply AOP advice to WCF services ........................................................................... 316 30.4. Creating client side proxies declaratively ..................................................................... 316 30.5. Exporting POCOs as WCF Services ............................................................................ 317 V. Integration ....................................................................................................................................... 318 31. Message Oriented Middleware - Apache ActiveMQ and TIBCO EMS ......................................... 319

Spring Framework (Version 1.3.2)

ix

The Spring.NET Framework 31.1. Introduction ............................................................................................................... 31.1.1. Multiple Vendor Support ....................................................................... 31.1.2. Separation of Concerns .......................................................................... 31.1.3. Interoperability and provider portability .................................................. 31.1.4. The role of Messaging API in a 'WCF world' .......................................... 31.2. Using Spring Messaging ............................................................................................. 31.2.1. Messaging Template overview ............................................................... 31.2.2. Connections .......................................................................................... 31.2.3. Caching Messaging Resources ............................................................... 31.2.4. Dynamic Destination Management ......................................................... 31.2.5. Message Listener Containers .................................................................. 31.2.6. Transaction Management ....................................................................... 31.3. Sending a Message .................................................................................................... 31.3.1. Using MessageConverters ...................................................................... 31.. Session and Producer Callback ..................................................................................... 31.5. Receiving a message .................................................................................................. 31.5.1. Synchronous Reception .......................................................................... 31.5.2. Asynchronous Reception ........................................................................ 31.5.3. The ISessionAwareMessageListener interface ......................................... 31.5.4. MessageListenerAdapater ....................................................................... 31.5.5. Processing messages within a messaging transaction ................................ 31.5.6. Messaging Namespace support ............................................................... 32. Message Oriented Middleware - TIBCO EMS ............................................................................ 32.1. Introduction ............................................................................................................... 32.2. Interface based APIs .................................................................................................. 32.3. Using Spring's EMS based Messaging ......................................................................... 32.3.1. Overivew .............................................................................................. 32.3.2. Connections .......................................................................................... 32.3.3. Caching Messaging Resources ............................................................... 32.3.4. Dynamic Destination Management ......................................................... 32.3.5. Accessing Admistrated objects via JNDI ................................................. 32.3.6. MessageListenerContainers .................................................................... 32.3.7. Transaction Management ....................................................................... 32.3.8. Sending a Message ................................................................................ 32.4. Using MessageConverters ........................................................................................... 32.5. Session and Producer Callback ................................................................................... 32.6. Receiving a messages ................................................................................................. 32.6.1. Synchronous Reception .......................................................................... 32.6.2. Asynchronous Reception ........................................................................ 32.6.3. The ISessionAwareMessageListener interface ......................................... 32.6.4. MessageListenerAdapter ........................................................................ 32.6.5. Processing messages within a messaging transaction ................................ 32.6.6. Messaging Namespace support ............................................................... 33. Message Oriented Middleware - MSMQ .................................................................................... 33.1. Introduction ............................................................................................................... 33.2. A quick tour for the impatient .................................................................................... 33.3. Using Spring MSMQ ................................................................................................. 33.3.1. MessageQueueTemplate ......................................................................... 33.3.2. MessageQueueFactoryObject ................................................................. 319 319 320 321 321 321 321 322 322 323 324 324 324 325 327 327 327 328 330 330 332 332 335 335 335 336 336 336 336 337 337 339 339 339 340 340 340 340 341 341 342 342 342 343 343 344 347 347 348

Spring Framework (Version 1.3.2)

The Spring.NET Framework 33.3.3. MessageQueue and IMessageConverter resource management .................. 33.3.4. Message Listener Containers .................................................................. 33.4. MessageConverters .................................................................................................... 33.4.1. Using MessageConverters ...................................................................... 33.5. Interface based message processing ............................................................................. 33.5.1. ............................................................................................................ 33.6. Comparison with using WCF ...................................................................................... 34. Scheduling and Thread Pooling ................................................................................................. 34.1. Introduction ............................................................................................................... 34.2. Using the Quartz.NET Scheduler ................................................................................ 34.2.1. Using the JobDetailObject ..................................................................... 34.2.2. Using the MethodInvokingJobDetailFactoryObject .................................. 34.2.3. Wiring up jobs using triggers and the SchedulerFactoryObject .................. 35. Template Engine Support .......................................................................................................... 35.1. Introduction ............................................................................................................... 35.2. Dependencies ............................................................................................................. 35.3. Configuring a VelocityEngine ..................................................................................... 35.3.1. Simple file based template engine definition ........................................... 35.3.2. Configuration Options ........................................................................... 35.3.3. Assembly based template loading ........................................................... 35.3.4. Using Spring's IResourceLoader to load templates ................................... 35.3.5. Defining a custom resource loader .......................................................... 35.3.6. Resource Loader configuration options ................................................... 35.3.7. Using a custom configuration file ........................................................... 35.3.8. Logging ................................................................................................ 35.4. Merging a template .................................................................................................... 35.5. Configuring a VelocityEngine without a custom namespace .......................................... VI. VS.NET Integration ........................................................................................................................ 36. Visual Studio.NET Integration .................................................................................................. 36.1. XML Editing and Validation ...................................................................................... 36.2. Enhancing the XML Editing and Validation Experience using the Spring.NET Visual Studio 2010 Extension ........................................................................................................ 36.3. Solution Templates .................................................................................................... 36.3.1. Class Library ........................................................................................ 36.3.2. ADO.NET based application library ....................................................... 36.3.3. NHibernate based application library ...................................................... 36.3.4. Spring based web application ................................................................. 36.4. Resharper Type Completion ....................................................................................... 36.5. Resharper templates ................................................................................................... 36.6. Versions of XML Schema .......................................................................................... 36.7. API documentation .................................................................................................... VII. Quickstart applications .................................................................................................................. 37. IoC Quickstarts ......................................................................................................................... 37.1. Introduction ............................................................................................................... 37.2. Movie Finder ............................................................................................................. 37.2.1. Getting Started - Movie Finder ............................................................... 37.2.2. First Object Definition ........................................................................... 37.2.3. Setter Injection ...................................................................................... 37.2.4. Constructor Injection ............................................................................. 349 349 354 354 355 355 356 358 358 358 358 359 360 361 361 361 361 361 361 362 362 363 363 363 364 364 364 366 367 367 369 369 370 371 372 373 374 375 376 376 377 378 378 378 378 379 380 380

Spring Framework (Version 1.3.2)

xi

The Spring.NET Framework 37.2.5. Summary .............................................................................................. 37.2.6. Logging ................................................................................................ 37.3. ApplicationContext and IMessageSource ..................................................................... 37.3.1. Introduction .......................................................................................... 37.4. ApplicationContext and IEventRegistry ....................................................................... 37.4.1. Introduction .......................................................................................... 37.5. Pooling example ........................................................................................................ 37.5.1. Implementing Spring.Pool.IPoolableObjectFactory .................................. 37.5.2. Being smart using pooled objects ........................................................... 37.5.3. Using the executor to do a parallel grep .................................................. 37.6. AOP .......................................................................................................................... AOP QuickStart ........................................................................................................................ 38.1. Introduction ............................................................................................................... 38.2. The basics ................................................................................................................. 38.2.1. Applying advice .................................................................................... 38.2.2. Using Pointcuts - the basics ................................................................... 38.3. Going deeper ............................................................................................................. 38.3.1. Other types of Advice ........................................................................... 38.3.2. Using Attributes to define Pointcuts ....................................................... 38.4. The Spring.NET AOP Cookbook ................................................................................ 38.4.1. Caching ................................................................................................ 38.4.2. Performance Monitoring ........................................................................ 38.4.3. Retry Rules ........................................................................................... 38.5. Spring.NET AOP Best Practices ................................................................................. Portable Service Abstraction Quick Start ................................................................................... 39.1. Introduction ............................................................................................................... 39.2. .NET Remoting Example ............................................................................................ 39.3. Implementation .......................................................................................................... 39.4. Running the application .............................................................................................. 39.5. Remoting Schema ...................................................................................................... 39.6. .NET Enterprise Services Example .............................................................................. 39.7. Web Services Example ............................................................................................... 39.8. Additional Resources ................................................................................................. Web Quickstarts ....................................................................................................................... 40.1. Introduction ............................................................................................................... SpringAir - Reference Application ............................................................................................. 41.1. Introduction ............................................................................................................... 41.2. Getting Started ........................................................................................................... 41.3. Container configuration .............................................................................................. 41.4. Bi-directional data binding ......................................................................................... 41.5. Declarative Validation ................................................................................................ 41.6. Internationalization ..................................................................................................... 41.7. Web Services ............................................................................................................. ADO.NET Data Access QuickStart ............................................................................................ 42.1. Introduction ............................................................................................................... 42.1.1. Database configuration .......................................................................... 42.1.2. CommandCallback ................................................................................ Transactions QuickStart ............................................................................................................ 43.1. Introduction ............................................................................................................... 381 382 383 383 385 385 386 386 388 389 389 390 390 390 390 393 395 395 401 402 402 403 403 403 404 404 404 406 411 412 413 414 418 419 419 420 420 420 420 422 422 423 423 425 425 425 426 428 428

38.

39.

40. 41.

42.

43.

Spring Framework (Version 1.3.2)

xii

The Spring.NET Framework 43.2. Application Overview ................................................................................................ 428 43.2.1. Interfaces .............................................................................................. 428 43.3. Implementation .......................................................................................................... 429 43.4. Configuration ............................................................................................................. 432 43.4.1. Rollback Rules ...................................................................................... 433 43.5. Adding additional Aspects .......................................................................................... 434 NHibernate QuickStart .............................................................................................................. 436 44.1. Introduction ............................................................................................................... 436 44.2. Getting Started ........................................................................................................... 436 44.3. Implementation ......................................................................................................... 439 44.3.1. The Data Access Layer .......................................................................... 439 44.3.2. The domain objects ............................................................................... 440 44.3.3. NHibernate based DAO implementation ................................................. 441 44.3.4. The Service layer .................................................................................. 444 44.3.5. Integration testing .................................................................................. 445 44.3.6. Web Application ................................................................................... 447 Quartz QuickStart ..................................................................................................................... 449 45.1. Introduction ............................................................................................................... 449 45.2. Application Overview ................................................................................................ 449 45.3. Standard job scheduling ............................................................................................. 449 45.4. Scheduling arbitrary methods as jobs .......................................................................... 450 NMS QuickStart ....................................................................................................................... 452 46.1. Introduction ............................................................................................................... 452 46.2. Message Destinations ................................................................................................. 452 46.3. Gateways ................................................................................................................... 453 46.4. Message Data ............................................................................................................ 453 46.5. Message Handlers ...................................................................................................... 455 46.6. Message Converters ................................................................................................... 456 46.7. Messaging Infrastructure ............................................................................................ 456 46.8. Running the application .............................................................................................. 457 TIBCO EMS QuickStart ........................................................................................................... 459 47.1. Introduction ............................................................................................................... 459 47.2. Message Destinations ................................................................................................. 459 47.3. Messaging Infrastructure ............................................................................................ 460 47.4. Running the application .............................................................................................. 461 MSMQ QuickStart .................................................................................................................... 463 48.1. Introduction ............................................................................................................... 463 48.2. Message Destinations ................................................................................................. 463 48.3. Gateways ................................................................................................................... 463 48.4. Message Data ............................................................................................................ 463 48.5. Message Handlers ...................................................................................................... 464 48.6. MessageConverters .................................................................................................... 464 48.7. Messaging Infrastructure ............................................................................................ 464 48.8. Running the application .............................................................................................. 466 WCF QuickStart ....................................................................................................................... 467 49.1. Introduction ............................................................................................................... 467 49.2. The server side .......................................................................................................... 467 49.2.1. WCF Dependency Injection and AOP in self-hosted application ................ 468 49.2.2. WCF Dependency Injection and AOP in IIS web application .................... 468

44.

45.

46.

47.

48.

49.

Spring Framework (Version 1.3.2)

xiii

The Spring.NET Framework 49.3. Client access .............................................................................................................. VIII. Spring.NET for Java developers ................................................................................................... 50. Spring.NET for Java Developers ............................................................................................... 50.1. Introduction ............................................................................................................... 50.2. Beans to Objects ........................................................................................................ 50.3. PropertyEditors to TypeConverters .............................................................................. 50.4. ResourceBundle-ResourceManager ............................................................................. 50.5. Exceptions ................................................................................................................. 50.6. Application Configuration .......................................................................................... 50.7. AOP Framework ........................................................................................................ 50.7.1. Cannot specify target name at the end of interceptorNames for ProxyFactoryObject .......................................................................................... IX. Appendices .................................................................................................................................... A. Classic Spring Usage ................................................................................................................. A.1. Classic Hibernate Usage .............................................................................................. A.1.1. The HibernateTemplate ........................................................................... A.1.2. Implementing Spring-based DAOs without callbacks ................................ A.2. Classic Declarative Transaction Configurations ............................................................. A.2.1. Declarative Transaction Configuration using DefaultAdvisorAutoProxyCreator ...................................................................... A.2.2. Declarative Transactions using TransactionProxyFactoryObject ................. A.2.3. Concise proxy definitions ....................................................................... A.2.4. Declarative Transactions using ProxyFactoryObject .................................. B. XML Schema-based configuration .............................................................................................. B.1. Introduction ................................................................................................................ B.2. XML Schema-based configuration ............................................................................... B.2.1. Referencing the schemas ......................................................................... B.2.2. The tx (transaction) schema .................................................................... B.2.3. The aop schema ..................................................................................... B.2.4. The db schema ....................................................................................... B.2.5. The wcf schema ..................................................................................... B.2.6. The remoting schema .............................................................................. B.2.7. The nms messaging schema .................................................................... B.2.8. The validation schema ............................................................................ B.2.9. The objects schema ................................................................................ B.3. Setting up your IDE .................................................................................................... C. Extensible XML authoring ......................................................................................................... C.1. Introduction ................................................................................................................ C.2. Authoring the schema .................................................................................................. C.3. Coding a INamespaceParser ......................................................................................... C.4. Coding an IObjectDefinitionParser ............................................................................... C.5. Registering the handler and the schema ........................................................................ C.5.1. NamespaceParsersSectionHandler ............................................................ C.6. Using a custom extension in your Spring XML configuration ......................................... C.7. Further Resources ....................................................................................................... D. Spring.NET's spring-objects.xsd ................................................................................................. 468 470 471 471 471 472 472 472 472 473 473 475 476 476 476 477 478 478 479 480 481 483 483 483 483 484 485 486 486 487 488 488 489 489 490 490 490 491 492 493 493 493 494 495

Spring Framework (Version 1.3.2)

xiv

Chapter 1. Preface
Developing software applications is hard enough even with good tools and technologies. Spring provides a lightweight solution for building enterprise-ready applications. Spring provides a consistent and transparent means to configure your application and integrate AOP into your software. Highlights of Spring's functionality are providing declarative transaction management for your middle tier as well as a full-featured ASP.NET framework. Spring could potentially be a one-stop-shop for many areas of enterprise application development; however, Spring is modular, allowing you to use just those parts of it that you need, without having to bring in the rest. You can use just the IoC container to configure your application and use traditional ADO.NET based data access code, but you could also choose to use just the Hibernate integration code or the ADO.NET abstraction layer. Spring has been (and continues to be) designed to be non-intrusive, meaning dependencies on the framework itself are generally none (or absolutely minimal, depending on the area of use). This document provides a reference guide to Spring's features. Since this document is still to be considered very much work-in-progress, if you have any requests or comments, please post them on the user mailing list or on the support forums at forum.springframework.net. Before we go on, a few words of gratitude are due to Christian Bauer (of the Hibernate team), who prepared and adapted the DocBook-XSL software in order to be able to create Hibernate's reference guide, thus also allowing us to create this one. Also thanks to Russell Healy for doing an extensive and valuable review of some of the material.

Spring Framework (Version 1.3.2)

Chapter 2. Introduction
2.1. Overview
Spring.NET is an application framework that provides comprehensive infrastructural support for developing enterprise .NET applications. It allows you to remove incidental complexity when using the base class libraries makes best practices, such as test driven development, easy practices. Spring.NET is created, supported and sustained by SpringSource. The design of Spring.NET is based on the Java version of the Spring Framework, which has shown real-world benefits and is used in thousands of enterprise applications world wide. Spring .NET is not a quick port from the Java version, but rather a 'spiritual port' based on following proven architectural and design patterns in that are not tied to a particular platform. The breadth of functionality in Spring .NET spans application tiers which allows you to treat it as a one stop shop but that is not required. Spring .NET is not an all-or-nothing solution. You can use the functionality in its modules independently. These modules are described below. Enterprise applications typically are composed of a number of a variety of physical tiers and within each tier functionality is often split into functional layers. The business service layer for example typically uses a objects in the data access layer to fulfill a use-case. No matter how your application is architected, at the end of the day there are a variety of objects that collaborate with one another to form the application proper. The objects in an application can thus be said to have dependencies between themselves. The .NET platform provides a wealth of functionality for architecting and building applications, ranging all the way from the very basic building blocks of primitive types and classes (and the means to define new classes), to rich full-featured application servers and web frameworks. One area that is decidedly conspicuous by its absence is any means of taking the basic building blocks and composing them into a coherent whole; this area has typically been left to the purvey of the architects and developers tasked with building an application (or applications). Now to be fair, there are a number of design patterns devoted to the business of composing the various classes and object instances that makeup an all-singing, all-dancing application. Design patterns such as Factory, Abstract Factory, Builder, Decorator, and Service Locator (to name but a few) have widespread recognition and acceptance within the software development industry (presumably that is why these patterns have been formalized as patterns in the first place). This is all very well, but these patterns are just that: best practices given a name, typically together with a description of what the pattern does, where the pattern is typically best applied, the problems that the application of the pattern addresses, and so forth. Notice that the last paragraph used the phrase ... a description of what the pattern does...; pattern books and wikis are typically listings of such formalized best practice that you can certainly take away, mull over, and then implement yourself in your application. The Spring Framework takes best practices that have been proven over the years in numerous applications and formalized as design patterns, and actually codifies these patterns as first class objects that you as an architect and developer can take away and integrate into your own application(s). This is a Very Good Thing Indeed as attested to by the numerous organizations and institutions that have used the Spring Framework to engineer robust, maintainable applications. For example, the IoC component of the Spring Framework addresses the enterprise concern of taking the classes, objects, and services that are to compose an application, by providing a formalized means of composing these various disparate components into a fully working application ready for use

2.2. Background
In early 2004, Martin Fowler asked the readers of his site: when talking about Inversion of Control: the question is, what aspect of control are [they] inverting?. Fowler then suggested renaming the principle (or at least giving

Spring Framework (Version 1.3.2)

Introduction it a more self-explanatory name), and started to use the term Dependency Injection. His article then continued to explain the ideas underpinning the Inversion of Control (IoC) and Dependency Injection (DI) principle. If you need a decent insight into IoC and DI, please do refer to the article : http://martinfowler.com/articles/ injection.html.

2.3. Modules
The Spring Framework contains a lot of features, which are well-organized into modules shown in the diagram below. The diagram below shows the various core modules of Spring.NET.

Click on the module name for more information. Spring.Core is the most fundamental part of the framework allowing you to configure your application using Dependency Injection. Other supporting functionality, listed below, is located in Spring.Core Spring.Aop - Use this module to perform Aspect-Oriented Programming (AOP). AOP centralizes common functionality that can then be declaratively applied across your application in a targeted manner. Spring's aspect library provides predefined easy to use aspects for transactions, logging, performance monitoring, caching, method retry, and exception handling. Spring.Data - Use this module to achieve greater efficiency and consistency in writing data access functionality in ADO.NET and to perform declarative transaction management. Spring.Data.NHibernate - Use this module to integrate NHibernate with Springs declarative transaction management functionality allowing easy mixing of ADO.NET and NHibernate operations within the same transaction. NHibernate 1.0 users will benefit from ease of use APIs to perform data access operations. Spring.Messaging - Use this module to raise the level of abstraction when interacting with the Microsoft MSMQ message queing middleware Spring.Messaging.NMS - Use this module to raise the level of abstraction when interacting with the Apache ActiveMQ (NMS) message queing middleware Spring.Messaging.EMS - Use this module to raise the level of abstraction when interacting with the Tibco Enterprise Message Service (EMS) message queing middleware

Spring Framework (Version 1.3.2)

Introduction Spring.Web - Use this module to raise the level of abstraction when writing ASP.NET web applications allowing you to effectively address common pain-points in ASP.NET such as data binding, validation, and ASP.NET page/ control/module/provider configuration. Spring.Web.Mvc - Use this module to integrate the functionality of the Spring.Core and Spring.Aop modules into your ASP.NET MVC 2 projects. Spring.Web.Mvc3 - Use this module to integrate the functionality of the Spring.Core and Spring.Aop modules into your ASP.NET MVC 3 projects. Spring.Web.Extensions - Use this module to raise the level of abstraction when writing ASP.NET web applications allowing you to effectively address common pain-points in ASP.NET such as data binding, validation, and ASP.NET page/control/module/provider configuration. Spring.Services - Use this module to adapt plain CLR objects so they can be used with a specific distributed communication technology, such as .NET Remoting, Enterprise Services, and ASMX Web Services. These services can be configured via dependency injection and decorated by applying AOP. Spring.Testing.NUnit - Use this module to perform integration testing with NUnit. Spring.Testing.MSTest - Use this module to perform integration testing with MSTest Spring.Scheduling.Quartz - Use this module to support interacting with the Quartz.NET job scheduler infrastructure. The Spring.Core module also includes the following additional features Expression Language - provides efficient querying and manipulation of an object graphs at runtime. Validation Framework - a robust UI agnostic framework for creating complex validation rules for business objects either programatically or declaratively. Data binding Framework - a UI agnostic framework for performing data binding. Dynamic Reflection - provides a high performance reflection API Threading - provides additional concurrency abstractions such as Latch, Semaphore and Thread Local Storage. Resource abstraction - provides a common interface to treat the InputStream from a file and from a URL in a polymorphic and protocol-independent manner.

2.4. Usage Scenarios


With the building blocks described above you can use Spring in all sorts of scenarios, from simple stand alone console applications to fully-fledged enterprise applications using Spring's transaction management functionality and web framework integration. It is important to note that the Spring Framework does not force you to use everything within it; it is not an allor-nothing solution. Existing front-ends built using standard ASP.NET can be integrated perfectly well with a Spring-based middle-tier, allowing you to use the transaction and/or data access features that Spring offers. The only things you need to do is wire up your business logic using Spring's IoC container and integrate it into your web layer using WebApplicationContext to locate middle tier services and/or configure your standard ASP.NET pages with depdenency injection.

Spring Framework (Version 1.3.2)

Introduction While the Spring framework does not force any particular application architecure it encourages the use of a well layered application architecture with distinct tiers for the presentation, service, data access, and database.

2.5. Quickstart applications


There are several sample applications that showcase individual features. If you are already familiar with the concepts of dependency injection, AOP, or have experience using the Java version of the Spring framework you may find jumping into the examples a better way to bootstrap the learning processing process. The following quickstart applications are available and can be found in the examples directory in the distribution. Click on the links for additional information. Movie Finder - A simple demonstration of Dependency Injection (DI) techniques using Spring's Inversion of Control (IoC) container. Application Context - Demonstrates IoC container features such as localization, accessing of ResourceSet objects, and applying resources to object properties. Aspect Oriented Programming - Demonstrates use of the AOP framework to add additional behavior to your existing objects. Examples of programmatic and declarative AOP configuration are shown. Distributed Computing - A calculator demonstrating remote service abstractions that let you 'export' a plain CLR object (POCO) via .NET Remoting, Web Services, or an EnterpriseService ServiceComponent. Corresponding client side proxies are also demonstrated. WCF - Shows a WCF based calculator example that configures your WCF service via dependency injection and apply AOP advice. Web Application - SpringAir -A ticket booking application that demonstrates the ASP.NET framework showing features such as DI for ASP.NET pages, data binding, validation, and localization. Web Development - Introductory examples showing use of dependency injection and Spring's bi-directional data binding in ASP.NET. ASP.NET MVC2 - Introductory example showing use of dependency injection and container integration into the ASP.NET MVC2 framework. ASP.NET MVC3 - Introductory example showing use of dependency injection and container integration into the ASP.NET MVC3 framework. Data Access - Demonstrates the ADO.NET framework showing how to simplify developing ADO.NET based data access layers. Transaction Management : Demonstrates the use of declarative transaction management for both local and distributed transaction in both .NET 1.1 and 2.0. AJAX : Demonstrates how to access a plain CLR object (POCO) as a webservice in client side JavaScript NHibernate Northwind: Demonstrates use of Spring's NHibernate integration to simplify the use of NHibernate. Web tier is also included showing how to use the Open-Session In View approach to session management in the web tier. Quartz Quickstart - Application that shows the use of Quartz.NET integration for scheduling. MSMQ - Application demonstrating MSMQ helper classes.

Spring Framework (Version 1.3.2)

Introduction NMS - Applicatoin demonstrating NMS helper classes.

2.6. Associated Spring.NET Projects


There is a lot more to Spring.NET than just the Spring.NET project itself. Spring.NET is enriched and empowered by a collection of supporting projects that provide additional capabilities beyond those found in the core Spring.NET Framework. Ranging from configuration-enhancing tools and libraries to REST clients to support for additional messaging frameworks and standards, the list of associated projects is growing rapidly and includes some of the following: Spring.NET CodeConfig Spring.NET CodeConfig provides the ability to configure a Spring container using standard .NET code instead of or in addition to XML configuration. See http://springframework.net/codeconfig/ for resources, downloads, and more information Spring.NET REST Client Spring.NET REST Client simplifies communication with HTTP servers, and enforces RESTful principles. It handles HTTP connections, leaving application code to provide URLs (with possible template variables) and extract results. See http://springframework.net/rest/ for resources, downloads, and more information Spring.NET AMQP Spring.NET AMQP supports the Spring programming model with AMQP, especially but not limited to RabbitMQ See http://springframework.net/amqp/ for resources, downloads, and more information Spring.NET Visual Studio Add-In Spring.NET Visual Studio Add-In provides intellisense assistance in authoring Spring XML configuration files in VS.NET 2010 See http://springframework.net/vsaddin/ downloads, and more information
[http://springframework.net/amqp/]

for resources,

Adopters of Spring.NET are encouraged to explore these projects (and more!) that help to round out the comprehensive Spring.NET experience and provide additional capabilities beyond those of the core Spring.NET Framework to increase developer efficiency and effectiveness.

2.7. License Information


Spring.NET is licensed according to the terms of the Apache License, Version 2.0. The full text of this license are available online at http://www.apache.org/licenses/LICENSE-2.0 . You can also view the full text of the license in the license.txt file located in the root installation directory.

2.8. Support
Training and support are available through SpringSource in addition to the mailing lists and forums you can find on the main Spring.NET website.

Spring Framework (Version 1.3.2)

Chapter 3. Background information


3.1. Inversion of Control
In early 2004, Martin Fowler asked the readers of his site: when talking about Inversion of Control: "the question, is what aspect of control are they inverting?". After talking about the term Inversion of Control Martin suggests renaming the pattern, or at least giving it a more self-explanatory name, and starts to use the term Dependency Injection. His article continues to explain some of the ideas behind this important software engineering principle. Other references you may find useful are Wikipedia Article - Dependency Injection CodeProject article - Dependency Injection for Loose Coupling

Spring Framework (Version 1.3.2)

Chapter 4. Migrating from 1.1 M2


4.1. Introduction
Several API changes were made after 1.1 M2 (before 1.1 RC1)due primarily by the need to refactor the code base to remove circular dependency cycles, which are now all removed. Class and schema name changes were also made to provide a more consistent naming convention across the codebase. As a result of these changes, you can not simply drop in the new .dlls as you may have done in previous release. This document serves as a high level guide to the most likely areas where you will need to make changes to either your configuration or your code. The file, BreakingChanges-1.1.txt, in the root directory of the distribution contains the full listing of breaking changes made for RC1 and higher

4.2. Important Changes


This section covers the common areas were you will need to make changes in code/configuration when migration from M2 to RC1or higher.

4.2.1. Namespaces
Note: If you previously installed Spring .xsd files to your VS.NET installation directory, remove them manually, and copy over the new ones, which have the -1.1.xsd suffix. The names of the section handlers to register custom schemas has changed, from ConfigParsersSectionHandler to NamespaceParsersSectionHandler. The target namespaces have changed, the 'directory' named /schema/ has been removed. For example, the target schema changed from http://www.springframework.net/schema/tx to http://www.springframework.net/tx. A typical declaration to use custom schemas within your configuration file looks like this
<objects xmlns='http://www.springframework.net' xmlns:db="http://www.springframework.net/database" xmlns:tx="http://www.springframework.net/tx" xmlns:aop="http://www.springframework.net/aop">

The class XmlParserRegistry was renamed to NamespaceParserRegistry. Renamed


Spring.Validation.ValidationConfigParser

to

Spring.Validation.Config.ValidationNamespaceParser

Renamed from DatabaseConfigParser to DatabaseNamespaceParser Renamed/Moved Remoting.RemotingConfigParser to Remoting.Config.RemotingNamespaceParser A typical registration of custom parsers within your configuration file looks like this
<configuration> <configSections> <sectionGroup name="spring"> <section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core"/> </sectionGroup> </configSections>

Spring Framework (Version 1.3.2)

Migrating from 1.1 M2


<spring> <parsers> <parser type="Spring.Aop.Config.AopNamespaceParser, Spring.Aop" /> <parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" /> <parser type="Spring.Transaction.Config.TxNamespaceParser, Spring.Data" /> </parsers> </spring>

A manual registration would look like this


NamespaceParserRegistry.RegisterParser(typeof(AopNamespaceParser)); NamespaceParserRegistry.RegisterParser(typeof(DatabaseNamespaceParser)); NamespaceParserRegistry.RegisterParser(typeof(TxNamespaceParser));

4.2.2. Core
Moved Spring.Util.DynamicReflection to Spring.Reflection.Dynamic Moved TypeRegistry and related classes from Spring.Context.Support to Spring.Core.TypeResolution Moved Spring.Objects.TypeConverters to Spring.Core.TypeConvesion

4.2.3. Web
Moved Spring.Web.Validation to Spring.Web.UI.Validation

4.2.4. Data
Changed schema to use 'provider' instead of 'dbProvider' element, usage is now <db:provider ... /> and not <db:dbProvider .../> Moved TransactionTemplate, Spring.Data.Support TransactionDelegate and ITransactionCallback from Spring.Data to

Moved AdoTemplate, AdoAccessor, AdoDaoSupport, RowMapperResultSetExtractor from Spring.Data to Spring.Data.Core Moved AdoPlatformTransactionManager, ServiceDomainPlatformTransactionManager, TxScopeTransactionManager from Spring.Data to Spring.Data.Core and

4.3. Support for .NET 4


Beginning with the 1.3.2 release of Spring.NET, full compatibility with the .NET 4 Common Language Runtime (CLR) is provided via a comprehensive collection of Spring.NET compiled assemblies specifically targeting the .NET 4 framework. Spring.NET 1.3.1 provided interim support for .NET 4 via the approach typically refered to as In-Process Side-by-Side or just In-Proc SxS.

Note
For more information on the In-Process Side-by-Side support introduced into the .NET 4 Framework, see the MSDN Magazine article located here: http://msdn.microsoft.com/en-us/magazine/
ee819091.aspx

Beginning with Spring.NET 1.3.2, this approach is no longer necessary and fuill native support of .NET is now provided.

Spring Framework (Version 1.3.2)

Part I. Core Technologies


This initial part of the reference documentation covers all of those technologies that are absolutely integral to the Spring Framework. Foremost amongst these is the Spring Framework's Inversion of Control (IoC) container. A thorough treatment of the Spring Framework's IoC container is closely followed by comprehensive coverage of Spring's AspectOriented Programming (AOP) technologies. The Spring Framework has its own AOP framework, which is conceptually easy to understand, and which successfully addresses the 80% sweet spot of AOP requirements in enterprise programming. The core functionality also includes an expression language for lightweight scripting and a ui-agnostic validation framework. Finally, the adoption of the test-driven-development (TDD) approach to software development is certainly advocated by the Spring team, and so coverage of Spring's support for integration testing is covered (alongside best practices for unit testing). The Spring team have found that the correct use of IoC certainly does make both unit and integration testing easier (in that the presence of properties and appropriate constructors on classes makes them easier to wire together on a test without having to set up service locator registries and suchlike)... the chapter dedicated solely to testing will hopefully convince you of this as well. Chapter 5, The IoC container Chapter 6, The IObjectWrapper and Type conversion Chapter 7, Resources Chapter 8, Threading and Concurrency Support Chapter 9, Object Pooling Chapter 11, Expression Evaluation Chapter 10, Spring.NET miscellanea Chapter 12, Validation Framework Chapter 13, Aspect Oriented Programming with Spring.NET Chapter 14, Aspect Library Chapter 15, Common Logging Chapter 16, Testing

Spring Framework (Version 1.3.2)

10

Chapter 5. The IoC container


5.1. Introduction
This chapter covers the Spring Framework implementation of the Inversion of Control (IoC) 1 principle The The
Spring.Core

assembly

is

the

basis

for

Spring.NET's

IoC

container.

IObjectFactory

[http://www.springframework.net/doc-latest/api/net-2.0/html/

Spring.Core~Spring.Objects.Factory.IObjectFactory.html]

mechanism

capable

of

managing

any

type

of

interface provides an advanced configuration object. IApplicationContext [http://

www.springframework.net/doc-latest/api/net-2.0/html/

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.
Spring.Core~Spring.Context.IApplicationContext.html]

In short, the IObjectFactory provides the 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 in descriptions of Spring's IoC container. If you are new to Spring.NET or IoC containers in general, you may want to consider starting with Chapter 37, IoC Quickstarts, which contains a number of introductory level examples that actually demonstrate a lot of what is described in detail below. Don't worry if you don't absorb everything at once... those examples serve only to paint a picture of how Spring.NET hangs together in really broad brushstrokes. Once you have finished with those examples, you can come back to this section which will fill in all the fine detail.

5.2. Container overview


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.

Note
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. Several implementations of the IApplicationContext interface are supplied out-of-the-box with Spring. 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.

See the section entitled Section 3.1, Inversion of Control

Spring Framework (Version 1.3.2)

11

The IoC container 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.

5.2.1. Configuration metadata


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

Note
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 and typically more than one object definition that the container must manage. XML- based configuration shows these objects as <object/> elements inside a top-level <objects/> element.

Spring Framework (Version 1.3.2)

12

The IoC container 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 finegrained domain objects in the container, because it is usually the responsibility of DAOs and business logic to create/load domain objects. The following example shows the basic structure of XML-based configuration metadata:
<objects xmlns="http://www.springframework.net"> <object id="..." type="..."> <!-- collaborators and configuration for this object go here --> </object> <object id="...." type="..."> <!-- collaborators and configuration for this object go here --> </object> <!-- more object definitions go here --> </objects>

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 thoroughly documented so feel free to take a peek inside (see Appendix D, Spring.NET's spring-objects.xsd). 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 Chapter 36, Visual Studio.NET Integration for more information regarding such integration.

5.2.2. 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 object definitions for services go here --> </objects>

The following example shows the data access objects (daos.xml) configuration file:

Spring Framework (Version 1.3.2)

13

The IoC container


<objects xmlns="http://www.springframework.net"> <object id="AccountDao" type="Petstore.Dao.HibernateAccountDao, PetStore"> <!-- additional collaborators and configuration for this object go here --> </object> <object id="ItemDao" type="Petstore.Dao.HibernateItemDao, PetStore"> <!-- additional collaborators and configuration for this object go here --> </object> <!-- more object definitions for data access objects go here --> </objects>

In the preceeding 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. 5.2.2.1. 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 [http://www.springframework.net/doc-latest/api/net-2.0/html/ Spring.Core~Spring.Core.IO.IResource.html] 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 [http://www.springframework.net/doc-latest/api/net-2.0/html/ Spring.Core~Spring.Core.IO.IResource.html] 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.

Note
After you learn about Spring's IoC container, you may want to know more about Spring's IResource [http://www.springframework.net/doc-latest/api/net-2.0/html/ Spring.Core~Spring.Core.IO.IResource.html] abstraction to load metadata from other locations as desribed below and alsoin the chapter Chapter 7, Resources 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 Section 7.1, Introduction.

Note
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

Spring Framework (Version 1.3.2)

14

The IoC container 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. 5.2.2.2. 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 Section 5.15, Service Locator access 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 Appendix D, Spring.NET's spring-objects.xsd). 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

Spring Framework (Version 1.3.2)

15

The IoC container Studio). You may wish to refer to Chapter 36, Visual Studio.NET Integration 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"> <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/> <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /> </sectionGroup> </configSections> <spring> <context> <resource uri="config://spring/objects"/> </context> <objects xmlns="http://www.springframework.net"> ... </objects> </spring> </configuration>

Other options available to structure the configuration files are described in Section 5.12.1, Context Hierarchies and Section 5.2.2.3, Composing XML-based configuration metadata. 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 Section 5.11, Configuration of IApplicationContext 5.2.2.3. Composing XML-based configuration metadata It can be useful to have object definitions span multiple XML files. Often each individual XML configuration file represents a logical layer or module in your architecture. You can use the IApplicationContext constructor to load object definitions from all these XML fragments. This constructor takes multiple IResource locations, as was shown in the previous section. Alternatively, use one or more occurrences of the <import/> element to load object definitions from another file (or files). For example:
<objects xmlns="http://www.springframework.net"> <import resource="services.xml"/> <import resource="resources/messageSource.xml"/> <import resource="/resources/themeSource.xml"/> <object id="object1" type="..."/> <object id="object2" type="..."/> </objects>

In the preceeding example, external object definitions are being loaded from three files, services.xml, messageSource.xml, and themeSource.xml. All location paths are relative to the definition file doing the importing, so services.xml must be in the same directory as the file doing the importing, while messageSource.xml and themeSource.xml must be in a resources location below the location of the importing file. As you can see, a leading slash is ignored, but given that these paths are relative, it is better form not to use

Spring Framework (Version 1.3.2)

16

The IoC container the slash at all. The contents of the files being imported, including the top level <objects/> element, must be valid XML object definitions according to the Spring Schema.

5.2.3. 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 objects 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.

Note
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.

5.2.4. Object definition overview


A Spring IoC container manages one or more objects. These objects are created with 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: 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 container (i.e. prototype or singleton, lifecycle callbacks, and so forth) 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 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. This metadata translates to a set of properties that make up each object definition. The following table lists some of these properties, with links to documentation Table 5.1. Object definition explanation Property type More info Section 5.2.5, Instantiating objects

Spring Framework (Version 1.3.2)

17

The IoC container Property id and name singleton or prototype object properties constructor arguments autowiring mode dependency checking mode initialization method destruction method More info Section 5.2.4.1, Naming objects Section 5.4, Object Scopes Section 5.3.1, Dependency injection Section 5.3.1, Dependency injection Section 5.3.6, Autowiring collaborators Section 5.3.7, Checking for dependencies Section 5.6.1, Lifecycle interfaces Section 5.6.1, Lifecycle interfaces

In addition to object definitions which contain information on how to create a specific object, the IApplicationContext implementations also permit the registration of existing objects that are created outside the container, by users. This is done by accessing the ApplicationContext's IObjectFactory via the property ObjectFactory which returns the IObjectFactory implementation DefaultListableObjectFactory. DefaultListableObjectFactory supports registration through the methods RegisterSingleton(..) and RegisterObjectDefinition(..). However, typical applications work soley with objects defined through metadata object definitions. 5.2.4.1. Naming objects 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' and/or 'name'attributes to specify the object identifier(s). The 'id' 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 can specify them in the 'name' attribute , separated by a comma (,), semicolon (;), or whitespace.

Note
You are not required to supply a name or id for a object. If no name or id is supplied explicitly, the container will generate a unique name for that object. However, if you want to refer to that object

Spring Framework (Version 1.3.2)

18

The IoC container by name, through the use of the ref element or Service Location style lookup, you must provide a name. The motivations for not supplying a name for a object are to use autowiring and inline-objects which will be discussed later.

5.2.4.1.1. 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 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. 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"/>

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. For example, the configuration metadata for subsystem A may refer to a DbProvider via the name 'SubsystemADbProvider. The configuration metadata for subsystem B may refer to a DbProvider via the name 'SubsystemBDbProvider'. 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="SubsystemA-DbProvider" alias="SubsystemB-DbProvider"/> <alias name="SubsystemA-DbProvider" alias="MyApp-DbProvider"/>

Now each component and the main app can refer to the 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.

5.2.5. 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 asked, and uses the configuration metadata encapsulated by that object definition to create (or acquire) an actual object. If you are using XML-based configuration metadata, you can specify the type of object that is to be instantiated in the 'type' attribute of the <object/> element. This 'type' attribute (which internally is a Type property on a IObjectDefinition instance) is usually 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: Typically, to specify the type of of the object to be constructed in the case where the container itself directly creates the object by calling its constructor reflectively, somewhat equivalent to C# code using the 'new' operator. To specify the actual class containing the static factory method that will be invoked to create the object, in the less common case where the container invokes a static factory method on a class to create the object. The object type returned from the invocation of the static factory method may be the same type or another type entirely.

Spring Framework (Version 1.3.2)

19

The IoC container 5.2.5.1. Instantiatoin with a constructor When you create an object using the constructor approach, all normal classes are usable by and compatible with Spring. That is, the class being developed does not need to implement any specific interfaces or to be coded in a specific fashion. Simply specifying the object type should be sufficient. However, depending on what type of IoC you are going to use for that specific object, you may need to create a default constructor. With XML-based configuration metadata you can specify your object class as follows:
<object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary"/>

For details about the mechanism for supplying arguments to the constructor (if required), and setting object instance properties after the object is constructed, see Section 5.3.1, Dependency injection. This XML fragment describes an object definition that will be identified by the exampleObject name, instances of which will be of the Examples.ExampleObject type that has been compiled into the ExamplesLibrary assembly. Take special note of the structure of the type attribute's value... the namespace-qualified name of the class is specified, followed by a comma, followed by (at a bare minimum) the name of the assembly that contains the class. In the preceding example, the ExampleObject class is defined in the Examples namespace, and it has been compiled into the ExamplesLibrary assembly. The name of the assembly that contains the type must be specified in the type attribute. Furthermore, it is recommended that you specify the fully qualified assembly name 2 in order to guarantee that the type that Spring.NET uses to instantiate your object (s) is indeed the one that you expect. Usually this is only an issue if you are using classes from (strongly named) assemblies that have been installed into the Global Assembly Cache (GAC). If you have defined nested classes use the addition symbol, +, to reference the nested class. For example, if the class Examples.ExampleObject had a nested class Person the XML declaration would be
<object id="exampleObject" type="Examples.ExampleObject+Person, ExamplesLibrary"/>

If you are defining classes that have been compiled into assemblies that are available to your application (such as the bin directory in the case of ASP.NET applications) via the standard assembly probing mechanisms, then you can specify simply the name of the assembly (e.g. ExamplesLibrary.Data)... this way, when (or if) the assemblies used by your application are updated, you won't have to change the value of every <object/> definition's type attribute to reflect the new version number (if the version number has changed)... Spring.NET will automatically locate and use the newer versions of your assemblies (and their attendant classes) from that point forward. 5.2.5.2. Instantiation with a static factory method When defining an object which is to be created using a static 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 subsequently is treated as if it had been created through a constructor. One use for such an object definition is to call static factories in legacy code. The following object definition specifies that the object will 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.
2

More information about assembly names can be found in the Assembly Names section of the .NET Framework Developer's Guide (installed as part of the .NET SDK), or online at Microsoft's MSDN website, by searching for Assembly Names.

Spring Framework (Version 1.3.2)

20

The IoC container


<object id="exampleObject" type="Examples.ExampleObjectFactory, ExamplesLibrary" factory-method="CreateInstance"/>

For details about the mechanism for supplying (optional) arguments to the factory method and setting object instance properties after it has been returned from the factory, see Section 5.3.2, Dependencies and configuration in detail 5.2.5.3. Object creation via an instance factory method Similar to instantiation through a static factory method, instantiation with an instance factory method invokes a 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="..."> <!-- inject any dependencies required by this object --> </object> <!-- the object that is to be created by the factory object --> <object id="exampleObject" factory-method="CreateInstance" factory-object="exampleFactory"/>

This approach shows that the factory object itself can be managed and configured through dependency injection (DI). See Dependencies and configuraiton in detail.

Note
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 .

5.2.6. Object creation of generic types


Generic types can also be created in much the same manner an non-generic types. 5.2.6.1. Object creation of generic types via constructor invocation The following examples shows the definition of simple generic types and how they can be created in Spring's XML based configuration file.
namespace GenericsPlay { public class FilterableList<T> { private List<T> list; private String name; public List<T> Contents { get { return list; } set { list = value; } } public String Name { get { return name; }

Spring Framework (Version 1.3.2)

21

The IoC container


set { name = value; } } public List<T> ApplyFilter(string filterExpression) { /// should really apply filter to list ;) return new List<T>(); } } }

The XML configuration to create and configure this object is shown below
<object id="myFilteredIntList" type="GenericsPlay.FilterableList&lt;int>, GenericsPlay"> <property name="Name" value="My Integer List"/> </object>

There are a few items to note in terms how to specify a generic type. First, the left bracket that specifies the generic type, i.e. <, is replaced with the string &lt; due to XML escape syntax for the less than symbol. Yes, we all realize this is less than ideal from the readability point of view. Second, the generic type arguments can not be fully assembly qualified as the comma is used to separate generic type arguments. Alternative characters used to overcome the two quirks can be implemented in the future but so far, all proposals don't seem to help clarify the text. The suggested solution to improve readability is to use type aliases as shown below
<typeAliases> <alias name="GenericDictionary" type=" System.Collections.Generic.Dictionary&lt;,>" /> <alias name="myDictionary" type="System.Collections.Generic.Dictionary&lt;int,string>" /> </typeAliases>

So that instead of something like this


<object id="myGenericObject" type="GenericsPlay.ExampleGenericObject&lt;System.Collections.Generic.Dictionary&lt;int , string>>, GenericsPlay" />

It can be shortened to
<object id="myOtherGenericObject" type="GenericsPlay.ExampleGenericObject&lt;GenericDictionary&lt;int , string>>, GenericsPlay" />

or even shorter
<object id="myOtherOtherGenericObject" type="GenericsPlay.ExampleGenericObject&lt;MyIntStringDictionary>, GenericsPlay" />

Refer to Section 5.11, Configuration of IApplicationContext for additional information on using type aliases. 5.2.6.2. Object creation of generic types via static factory method The following classes are used to demonstrate the ability to create instances of generic types that themselves are created via a static generic factory method.
public class TestGenericObject<T, U> { public TestGenericObject() { } private IList<T> someGenericList = new List<T>(); private IDictionary<string, U> someStringKeyedDictionary = new Dictionary<string, U>(); public IList<T> SomeGenericList {

Spring Framework (Version 1.3.2)

22

The IoC container


get { return someGenericList; } set { someGenericList = value; } } public IDictionary<string, U> SomeStringKeyedDictionary { get { return someStringKeyedDictionary; } set { someStringKeyedDictionary = value; } } }

The accompanying factory class is


public class TestGenericObjectFactory { public static TestGenericObject<V, W> StaticCreateInstance<V, W>() { return new TestGenericObject<V, W>(); } public TestGenericObject<V, W> CreateInstance<V, W>() { return new TestGenericObject<V, W>(); } }

The XML snippet to create an instance of TestGenericObject where V is a List of integers and W is an integer is shown below
<object id="myTestGenericObject" type="GenericsPlay.TestGenericObjectFactory, GenericsPlay" factory-method="StaticCreateInstance&lt;System.Collections.Generic.List&lt;int>,int>" />

The StaticCreateInstance method is responsible for instantiating the object that will be associated with the id 'myTestGenericObject'. 5.2.6.3. Object creation of generic types via instance factory method Using the class from the previous example the XML snippet to create an instance of a generic type via an instance factory method is shown below
<object id="exampleFactory" type="GenericsPlay.TestGenericObject&lt;int,string>, GenericsPlay"/> <object id="anotherTestGenericObject" factory-object="exampleFactory" factory-method="CreateInstance&lt;System.Collections.Generic.List&lt;int>,int>"/>

This creates an instance of TestGenericObject<List<int>,int>

5.3. Dependencies
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.

5.3.1. Dependency injection


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

Spring Framework (Version 1.3.2)

23

The IoC container 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 object. This process is fundamentally the inverse to the case when the object itself is controlling the instantiation or location of its dependencies 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. 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. 5.3.1.1. Constructor-based dependency injection 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 with constructor injection. Notice that there is nothing special about this class (no container specific interfaces, base classes or attributes)
public class SimpleMovieLister { // the SimpleMovieLister has a dependency on a MovieFinder private IMovieFinder movieFinder; // a constructor so that the Spring container can 'inject' a MovieFinder public MovieLister(IMovieFinder movieFinder) { this.movieFinder = movieFinder; } // business logic that actually 'uses' the injected IMovieFinder is omitted... }

5.3.1.1.1. Constructor argument resolution


Constructor argument resolution matching occurs using the 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 are supplied to the appropriate constructor when the object being instantiated. Consider the following class:
namespace X.Y { public class Foo { public Foo(Bar bar, Baz baz) { // ... } } }

Spring Framework (Version 1.3.2)

24

The IoC container No potential 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 id="foo" type="X.Y.Foo, Example"> <constructor-arg ref="bar"/> <constructor-arg ref="baz"/> </object> <object id="bar" type="X.Y.Bar, Example"/> <object id="baz" type="X.Y.Baz, Example"/>

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 <value>true<value>, Spring cannot determine the type of the value, and so cannot match by type without help. Consider the following class:
using System; namespace SimpleApp { public class ExampleObject { private int years; private string ultimateAnswer;

//No. of years to the calculate the Ultimate Answer //The Answer to Life, the Universe, and Everything

public ExampleObject(int years, string ultimateAnswer) { this.years = years; this.ultimateAnswer = ultimateAnswer; } }

5.3.1.1.1.1. Constructor argument type matching 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>

The type attribute specifies the System.Type of the constructor argument, such as System.Int32. Alias' are available to for common simple types (and their array equivalents). These alias' are... Table 5.2. Type aliases Type Alias' Array Alias' char[], Char() short[], Short() int[], Integer() long[], Long() ushort[] uint[]

System.Char Char char, System.Int16 Short short, System.Int32 Integer int, System.Int64 Long long, System.UInt16 ushort System.UInt32 uint

Spring Framework (Version 1.3.2)

25

The IoC container Type Alias' Array Alias' ulong[] float[], Single() double[], Double() date[], Date() decimal[], Decimal() bool[], Boolean() string[], String()

System.UInt64 ulong System.Float Single float, System.Double Double double, System.Date Date date, System.Decimal Decimal decimal, System.Bool Boolean bool, System.String String string, 5.3.1.1.1.2. Constructor argument Index

Use the index attribute to specify explicitly the index of constructor arguments. For example:
<object name="exampleObject" type="SimpleApp.ExampleObject, SimpleApp"> <constructor-arg index="0" value="7500000"/> <constructor-arg index="1" value="42"/> </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. 5.3.1.1.1.3. Constructor arguments by name You can specify constructor argumetn by name using name attribute of the <constructor-arg> element.
<object name="exampleObject" type="SimpleApp.ExampleObject, SimpleApp"> <constructor-arg name="years" value="7500000"/> <constructor-arg name="ultimateAnswer" value="42"/> </object>

5.3.1.2. Setter-based dependency injection Setter-based DI is accomplished by the container invoking setter properties on your objects after invoking a noargument constructor or no-argument static factory method to instantiate your object. The following eample shows a class that can only be dependency injected using pure setter injection.
public class MovieLister { private IMovieFinder movieFinder; public IMovieFinder MovieFinder { set { movieFinder = value; } } // business logic that actually 'uses' the injected IMovieFinder is omitted... }

Spring Framework (Version 1.3.2)

26

The IoC container 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 properties also makes objects of that class amenable to reconfigured or reinjection later. Managment through WMI is a compelling use case. 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. 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 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. Refer to Section 6.3, Type conversion for more information regarding type conversion, and how you can design your classes to be convertible by Spring.NET. The container resolves object dependeices as: 1. 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. 2. Each object has dependencies expressed in the form of properties, constructor arguments, or arguments to the 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. 3. Each property or constructor argument is either an actual definition of the value to set, or a reference to another object in the container. 4. Each property or constructor argument which is a value must be able to be converted from whatever format it was specified in, to the actual System.Type of 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. The Spring container validates the configuration of each object 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.

Spring Framework (Version 1.3.2)

27

The IoC container Circular Dependencies If you are using predominantly constructor injection it is possible to create unresolvable circular dependency scenario. 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. 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 circular dependency between object A and object B will force one of the objects to be injected into the other prior to being fully initialized itself (a classic chicken/egg scenario). You can generally trust Spring.NET to do the right thing. It detects configuration problems, such as references to non-existent object definitions and circular dependencies, at container load-time. 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 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. 5.3.1.3. Examples of dependency injection First, an example of using XML-based configuration metadata for 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"/> <property name="objectTwo" ref="yetAnotherObject"/> <property name="IntegerProperty" value="1"/> </object> <object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/> <object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/>

[C#] public class ExampleObject {

Spring Framework (Version 1.3.2)

28

The IoC container


private AnotherObject objectOne; private YetAnotherObject objectTwo; private int i; public AnotherObject ObjectOne { set { this.objectOne = value; } } public YetAnotherObject ObjectTwo { set { this.objectTwo = value; } } public int IntegerProperty { set { this.i = value; } } }

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"/> </object> <object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/> <object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/>

[Visual Basic.NET] Public Class ExampleObject Private myObjectOne As AnotherObject Private myObjectTwo As YetAnotherObject Private i As Integer Public Sub New ( anotherObject as AnotherObject, yetAnotherObject as YetAnotherObject, i as Integer) myObjectOne = anotherObject myObjectTwo = yetAnotherObject Me.i = i End Sub End Class

Ghe 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 an instance of the object
<object id="exampleObject" type="Examples.ExampleFactoryMethodObject, ExamplesLibrary" factory-method="CreateInstance"> <constructor-arg name="objectOne" ref="anotherExampleObject"/> <constructor-arg name="objectTwo" ref="yetAnotherObject"/> <constructor-arg name="intProp" value="1"/> </object> <object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/> <object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/>

[C#] public class ExampleFactoryMethodObject { private AnotherObject objectOne;

Spring Framework (Version 1.3.2)

29

The IoC container


private YetAnotherObject objectTwo; private int i; // a private constructor private ExampleFactoryMethodObject() { } public static ExampleFactoryMethodObject CreateInstance(AnotherObject objectOne, YetAnotherObject objectTwo, int intProp) { ExampleFactoryMethodObject fmo = new ExampleFactoryMethodObject(); fmo.AnotherObject = objectOne; fmo.YetAnotherObject = objectTwo; fmo.IntegerProperty = intProp; return fmo; } // Property definitions }

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 single object definition, as can be seen in the following example:
<object id="exampleObject" type="Examples.MixedIocObject, ExamplesLibrary"> <constructor-arg name="objectOne" ref="anotherExampleObject"/> <property name="objectTwo" ref="yetAnotherObject"/> <property name="IntegerProperty" value="1"/> </object> <object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/> <object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/>

[C#] public class MixedIocObject { private AnotherObject objectOne; private YetAnotherObject objectTwo; private int i; public MixedIocObject (AnotherObject obj) { this.objectOne = obj; } public YetAnotherObject ObjectTwo { set { this.objectTwo = value; } } public int IntegerProperty { set { this.i = value; } } }

5.3.2. Dependencies and configuration in detail


As mentioned in the previous section, you can define object properties and constructor arguments as either references to other managed objects (collaborators), or as values defined inline. Spring's XML-based

Spring Framework (Version 1.3.2)

30

The IoC container configuration metadata supports sub-element types within its <property/> and <constructor-arg/> elements for this purpose. 5.3.2.1. Straight values (primitives, strings, and so on) 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. 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"> <!-- results in a call to the setter of the ConnectionString property --> <property name="ConnectionString" value="Integrated Security=SSPI;database=northwind;server=mySQLServer"/> </object> </objects>

5.3.2.1.1. The idref element


An idref element is simply an error-proof way to pass the id (string value - not a reference) of another object in the container to a <constructor-arg/> or <property/> element.
<object id="theTargetObject" type="..."> . . . </object> <object id="theClientObject" type="..."> <property name="targetName"> <idref object="theTargetObject"/> </property> </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 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' object is a prototype object, this typo and the resulting exception may only be discovered long after the container is deployed. Additionally, if the reference object is in the same XML unit, and the object name is the object id, you can use the local attribute which allows the XML parser itself to validate the object name earlier, at XML document parse time.
<property name="targetName"> <idref local="theTargetObject"/> </property>

Spring Framework (Version 1.3.2)

31

The IoC container

5.3.2.1.2. Whitespace Handling


Usually all leading and trailing whitespaces are trimmed from a <value /> element's text. In some cases it is necessary to maintain whitespaces exactly as they are written into the xml element. The parser does understand the xml:space attribute in this case:
<property name="myProp"> <value xml:space="preserve"> &#x000a;&#x000d;&#x0009;</value> </property>

The above configuration will result in the string " \n\r\t". Note, that you don't have to explicitely specifiy the 'xml' namespace on top of your configuration. 5.3.2.2. References to other objects (collaborators) The ref element is the final element allowed inside a <constructor-arg/> or <property/> definition element. Here you set the value of the specified property to be a reference to another object (a collaborator) managed by the container. 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 the collaborator is a singleton object it may be initialized already by the container.) All references are ultimately just a reference to another object. Scoping and validation depend on whether you specify the id/name of the object through the object, local, or parent attributes. Specifying the target object through the object attribute of the ref tag is the most general form, and allows creation of a reference to any object in the same container or parent container, regardless of whether it is in the same XML file. 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 local attribute leverages the ability of the XML parser to validate XML id references within the same file. The value of the local attribute must be the same as the id attribute of the target object. The XML parser will issue an error if no matching element is found in the same file. As such, using the local variant is the best choice (in order to know about errors are early as possible) if the target object is in the same XML file.
<ref local="someObject"/>

Specifying the target object through the 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 use this object reference variant mainly when you have a hierarchy of containers and you want to wrap an existing object in a parent container with some sort of proxy which will have the same name as the parent object.
<!-- 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 object is the same as the name of the 'parent' object type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop"> <property name="target"> <ref parent="AccountService"/> <-- notice how we refer to the parent object --> </property> <!-- insert other configuration and dependencies as required as here --> </object>

Spring Framework (Version 1.3.2)

32

The IoC container 5.3.2.3. Inner objects An <object/> element inside the <constructor-arg/> or <property/> element defines so called inner object.
<object id="outer" type="..."> <!-- Instead of using a reference to target, just use an inner object --> <property name="target"> <object type="ExampleApp.Person, ExampleApp"> <property name="name" value="Tony"/> <property name="age" value="51"/> </object> </property> </object>

An inner object definition does not require a defined id or name; the container ignores these values. It also ignores the scope flag. Inner object are always anonymous and they are always scoped as prototypes. It is not possible to inject inner objects into collaborating objects other than into the enclosing object. 5.3.2.4. Setting collection values The list, set, name-values and dictionary elements allow properties and arguments of the type IList, ISet, NameValueCollection and IDictionary, respectively, to be defined and set.
<objects xmlns="http://www.springframework.net"> <object id="moreComplexObject" type="Example.ComplexObject"> <!-results in a call to the setter of the SomeList (System.Collections.IList) property --> <property name="SomeList"> <list> <value>a list element followed by a reference</value> <ref object="myConnection"/> </list> </property> <!-results in a call to the setter of the SomeDictionary (System.Collections.IDictionary) property --> <property name="SomeDictionary"> <dictionary> <entry key="a string => string entry" value="just some string"/> <entry key-ref="myKeyObject" value-ref="myConnection"/> </dictionary> </property> <!-results in a call to the setter of the SomeNameValue (System.Collections.NameValueCollection) property --> <property name="SomeNameValue"> <name-values> <add key="HarryPotter" value="The magic property"/> <add key="JerrySeinfeld" value="The funny (to Americans) property"/> </name-values> </property> <!-results in a call to the setter of the SomeSet (Spring.Collections.ISet) property --> <property name="someSet"> <set> <value>just some string</value> <ref object="myConnection"/> </set> </property> </object> </objects>

Many classes in the BCL expose only read-only properties for collection classes. When Spring.NET encounters a read-only collection, it will configure the collection by using the getter property to obtain a reference to the

Spring Framework (Version 1.3.2)

33

The IoC container collection class and then proceed to add the additional elements to the existing collection. This results in an additive behavior for collection properties that are exposed in this manner. 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)

The shortcut forms for value and references are useful to reduce XML verbosity when setting collection properties. See Section 5.3.2.9, Value and ref shortcut forms for more information. 5.3.2.5. Setting generic collection values Spring supports setting values for classes that expose properties based on the generic collection interfaces IList<T> and IDictionary<TKey, TValue>. The type parameter for these collections is specified by using the XML attribute element-type for IList<T> and the XML attributes key-type and valuetype for IDictionary<TKey, TValue>. The values of the collection are automaticaly converted from a string to the appropriate type. If you are using your own user-defined type as a generic type parameter you will likely need to register a custom type converter. Refer to Section 5.5, Type conversion for more information. The implementations of IList<T> and IDictionary<TKey, TValue> that is created are System.Collections.Generic.List and System.Collections.Generic.Dictionary. The following class represents a lottery ticket and demonstrates how to set the values of a generic IList.
public class LotteryTicket { List<int> list; DateTime date; public List<int> Numbers { set { list = value; } get { return list; } } public DateTime Date { get { return date; } set { date = value; } } }

The XML fragment that can be used to configure this class is shown below
<object id="MyLotteryTicket" type="GenericsPlay.Lottery.LotteryTicket, GenericsPlay"> <property name="Numbers"> <list element-type="int"> <value>11</value> <value>21</value> <value>23</value> <value>34</value> <value>36</value> <value>38</value> </list> </property> <property name="Date" value="4/16/2006"/> </object>

The following shows the definition of a more complex class that demonstrates the use of generics using the Spring.Expressions.IExpression interface as the generic type parameter for the IList element-type and the value-type for IDictionary. Spring.Expressions.IExpression has an associated type converter, Spring.Objects.TypeConverters.ExpressionConverter that is already pre-registered with Spring.
public class GenericExpressionHolder

Spring Framework (Version 1.3.2)

34

The IoC container


{ private System.Collections.Generic.IList<IExpression> expressionsList; private System.Collections.Generic.IDictionary<string,IExpression> expressionsDictionary; public System.Collections.Generic.IList<IExpression> ExpressionsList { set { this.expressionsList = value; } } public System.Collections.Generic.IDictionary<string, IExpression> ExpressionsDictionary { set { this.expressionsDictionary = value; } } public IExpression this[int index] { get { return this.expressionsList[index]; } } public IExpression this[string key] { get { return this.expressionsDictionary[key]; } } }

An example XML configuration of this class is shown below


<object id="genericExpressionHolder" type="Spring.Objects.Factory.Xml.GenericExpressionHolder, Spring.Core.Tests"> <property name="ExpressionsList"> <list element-type="Spring.Expressions.IExpression, Spring.Core"> <value>1 + 1</value> <value>date('1856-7-9').Month</value> <value>'Nikola Tesla'.ToUpper()</value> <value>DateTime.Today > date('1856-7-9')</value> </list> </property> <property name="ExpressionsDictionary"> <dictionary key-type="string" value-type="Spring.Expressions.IExpression, Spring.Core"> <entry key="zero"> <value>1 + 1</value> </entry> <entry key="one"> <value>date('1856-7-9').Month</value> </entry> <entry key="two"> <value>'Nikola Tesla'.ToUpper()</value> </entry> <entry key="three"> <value>DateTime.Today > date('1856-7-9')</value> </entry> </dictionary> </property> </object>

5.3.2.6. Collection Merging As of Spring 1.3, the container supports the merging of collections. An application developer can define a parentstyle <list/>, <dictionary/>, <set/> or <name-value/> element, and have child-style <list/>, <dictionary/ >, <set/> or <name-value/> elements inherit and override values from the parent collection. That is, the child collection's values are the result of merging the elements of the parent and child collections, with the child's collection elements overriding values specified in the parent collection. This section on merging discusses the parent-child object mechanism. Readers unfamiliar with parent and child object definitions may wish to read the relevant section before continuing.

Spring Framework (Version 1.3.2)

35

The IoC container The following example demonstrates collection merging:


<object id="parent" abstract="true" type="Example.ComplexObject, Examples"> <property name="AdminEmails"> <name-values> <add key="administrator" value="[email protected]"/> <add key="support" value="[email protected]"/> </name-values> </property> </object> <object id="child" parent="parent" > <property name="AdminEmails"> <!-- the merge is specified on the *child* collection definition --> <name-values merge="true"> <add key="sales" value="[email protected]"/> <add key="support" value="[email protected]"/> </name-values> </property> </object>

Notice the use of the merge=true attribute on the <name-values/> element of the AdminEmails property of the child object definition. When the child object is resolved and instantiated by the container, the resulting instance has an AdminEmails Properties collection that contains the result of the merging of the child's AdminEmails collection with the parent's AdminEmails collection.
[email protected] [email protected] [email protected]

The child Properties collection's value set inherits all property elements from the parent <name-values/>, and the child's value for the support value overrides the value in the parent collection. This merging behavior applies similarly to the <list/>, <dictionary/>, and <set/> collection types. In the specific case of the <list/> element, the semantics associated with the IList collection type, that is, the notion of an ordered collection of values, is maintained; the parent's values precede all of the child list's values. In the case of the IDictionary, ISet, and NameValue collection types, no ordering exists. Hence no ordering semantics are in effect for the collection types that underlie the associated IDictionary, ISet, and NameValueCollection implementation types that the container uses internally. 5.3.2.7. Null and empty values Spring treats empty arguments for properties and the like as empty Strings. The following XML-based configuration metadata snippet sets the email property to the empty String value ("")
<object type="Examples.ExampleObject, ExamplesLibrary"> <property name="email" value=""/> </object>

This results in the email property being set to the empty string value (""), in much the same way as can be seen in the following snippet of C# code
exampleObject.Email = "";

The <null> element is used to handle null values. For example:


<object type="Examples.ExampleObject, ExamplesLibrary"> <property name="email"><null/></property> </object>

This results in the email property being set to null, again in much the same way as can be seen in the following snippet of C# code:

Spring Framework (Version 1.3.2)

36

The IoC container


exampleObject.Email = null;

5.3.2.8. Setting indexer properties An indexer lets you set and get values from a collection using a familiar bracket [] notation. Spring's XML configuration supports the setting of indexer properties. Overloaded indexers as well as multiparameter indexers are also supported. The property expression parser described in Chapter 11, Expression Evaluation is used to perform the type conversion of the indexer name argument from a string in the XML file to a matching target type. As an example consider the following class
public class Person { private IList favoriteNames = new ArrayList(); private IDictionary properties = new Hashtable(); public Person() { favoriteNames.Add("p1"); favoriteNames.Add("p2"); } public string this[int index] { get { return (string) favoriteNames[index]; } set { favoriteNames[index] = value; } } public string this[string keyName] { get { return (string) properties[keyName]; } set { properties.Add(keyName, value); } } }

The XML configuration snippet to populate this object with data is shown below
<object id="person" type="Test.Objects.Person, Test.Objects"> <property name="[0]" value="Master Shake"/> <property name="['one']" value="uno"/> </object>

Note
The use of the property expression parser in Release 1.0.2 changed how you configure indexer properties. The following section describes this usage. The older style configuration uses the following syntax
<object id="objectWithIndexer" type="Spring.Objects.TestObject, Spring.Core.Tests"> <property name="Item[0]" value="my string value"/> </object>

You can also change the name used to identify the indexer by adorning your indexer method declaration with the attribute [IndexerName("MyItemName")]. You would then use the string MyItemName[0] to configure the first element of that indexer. There are some limitations to be aware in the older indexer configuration. The indexer can only be of a single parameter that is convertible from a string to the indexer parameter type. Also, multiple indexers are not supported. You can get around that last limitation currently if you use the IndexerName attribute.

Spring Framework (Version 1.3.2)

37

The IoC container 5.3.2.9. Value and ref shortcut forms Spring XML used to be even more verbose. What is now popular usage is actually the shortcut from of the original way to specify values and references. There are also some shortcut forms that are less verbose than using the full value and ref elements. The property, constructor-arg, and entry elements all support a value attribute which may be used instead of embedding a full value element. Therefore, the following:
<property name="myProperty"> <value>hello</value> </property> <constructor-arg> <value>hello</value> </constructor-arg> <entry key="myKey"> <value>hello</value> </entry>

are equivalent to:


<property name="myProperty" value="hello"/> <constructor-arg value="hello"/> <entry key="myKey" value="hello"/>

In general, when typing definitions by hand, you will probably prefer to use the less verbose shortcut form. The property and constructor-arg elements support a similar shortcut ref attribute which may be used instead of a full nested ref element. Therefore, the following...
<property name="myProperty"> <ref object="anotherObject"/> </property> <constructor-arg index="0"> <ref object="anotherObject"/> </constructor-arg>

is equivalent to...
<property name="myProperty" ref="anotherObject"/> <constructor-arg index="0" ref="anotherObject"/>

Note
The shortcut form is equivalent to a <ref object="xxx"> element; there is no shortcut for either the <ref local="xxx"> or <ref parent="xxx"> elements. For a local or parent ref, you must still use the long form. Finally, the entry element allows a shortcut form the specify the key and/or value of a dictionary, in the form of key/key-ref and value/value-ref attributes. Therefore, the following
<entry> <key> <ref object="MyKeyObject"/> </key> <ref object="MyValueObject"/> </entry>

Spring Framework (Version 1.3.2)

38

The IoC container Is equivalent to:


<entry key-ref="MyKeyObject" value-ref="MyValueObject"/>

As mentioned previously, the equivalence is to <ref object="xxx"> and not the local or parent forms of object references. 5.3.2.10. Compound property names and Spring expression references You can use compound or nested property names when you set object properties. Property names are interpreted using the Spring Expression Language (SpEL) and therefore can leverage its many features to set property names. For example, in this object definition a simple nested property name is configured
<object id="foo" type="Spring.Foo, Spring.Foo"> <property name="bar.baz.name" value="Bingo"/> </object>

As an example of some alternative ways to declare the property name, you can use SpEL's support for indexers to configure a Dictionary key value pair as an alternative to the nested <dictionary> element. More importantly, you can use the 'expression' element to refer to a Spring expression as the value of the property. Simple examples of this are shown below
<property name=minValue expression=int.MinValue /> <property name=weekFromToday expression="DateTime.Today + 7"/>

Using SpEL's support for method evaluation, you can easily call static method on various helper classes in your XML configuraiton.

5.3.3. Declarative Event Listener Registration


In C# events are built right into the language thanks to the event keyword. Under the scenes, events are essentially a shorthand notation for delegates with some additional guidelines as to what the parameters to an event handler method should be (i.e. a sender System.Object and an System.EventArgs object).
public class EventSource public event EventHandler Click;

In use, .NET events are combined with one or more event handler methods. Each handler method is programmatically added, or removed, from the event and corresponds to an object's method that should be invoked when a particular event occurs. When more than one handler method is added to an event, then each of the registered methods will be invoked in turn when an event occurs.
TestObject source = new TestObject(); TestEventHandler eventListener1 = new TestEventHandler(); TestEventHandler eventListener2 = new TestEventHandler(); source.Click += eventListener1.HandleEvent; // Adding the first event handler method to the event source.Click += eventListener2.HandleEvent; // Adding a second event handler method to the event source.OnClick(); // First eventListener1.HandleEvent is invoked, then eventListener2.HandleEvent

When OnClick() is invoked, the event is fired.


public void OnClick() { if (Click != null) { Click(this, EventArgs.Empty); // Fire the event off to the registered handler methods }

Spring Framework (Version 1.3.2)

39

The IoC container


}

One of the not so nice things about using events is that, without employing late binding, you declare the objects that are registered with a particular event programmatically. Spring .NET offers a way to declaratively register your handler methods with particular events using the <listener> element inside your <object> elements. 5.3.3.1. Declarative event handlers Rather than having to specifically declare in your code that you are adding a method to be invoked on an event, using the <listener> element you can register a plain object's methods with the corresponding event declaratively in your application configuration. Using the listener element you can: Configure a method to be invoked when an event is fired. Register a collection of handler methods based on a regular expression. Register a handler method against an event name that contains a regular expression. 5.3.3.2. Configuring a method to be invoked when an event is fired The same event registration in the example above can be achieved using configuration using the <listener> element.
<object id="eventListener1" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample"> <!-- wired up to an event exposed on an instance --> <listener event="Click" method="HandleEvent"> <ref object="source"/> </listener> </object> <object id="eventListener2" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample"> <!-- wired up to an event exposed on an instance --> <listener event="Click" method="HandleEvent"> <ref object="source"/> </listener> </object>

In this case the two different objects will have their HandleEvent method invoked, as indicated explicitly using the method attribute, when a Click event, as specified by the event attribute, is triggered on the object referred to by the ref element. 5.3.3.3. Registering a collection of handler methods based on a regular expression Regular expressions can be employed to wire up more than one handler method to an object that contains one or more events.
<object id="eventListener" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample"> <listener method="Handle.+"> <ref object="source"/> </listener> </object>

Here all the eventListener's handler methods that begin with 'Handle', and that have the corresponding two parameters of a System.Object and a System.EventArgs, will be registered against all events exposed by the source object. You can also use the name of the event in regular expression to filter your handler methods based on the type of event triggered.

Spring Framework (Version 1.3.2)

40

The IoC container


<object id="eventListener" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample"> <!-- For the Click event, the HandleClick handler method will be invoked. --> <listener method="Handle${event}"> <ref object="source"/> </listener> </object>

5.3.3.4. Registering a handler method against an event name that contains a regular expression Finally, you can register an object's handler methods against a selection of events, filtering based on their name using a regular expression.
<object id="eventListener" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample"> <listener method="HandleEvent" event="Cl.+"> <ref object="source"/> </listener> </object>

In this example the eventListener's HandleEvent handler method will be invoked for any event that begins with 'Cl'.

5.3.4. Using depends-on


If an object is a dependency of another that usually means that one object is set as a property of another. Typically you accomplish this with the <ref/> element in XML-based configuration metadata. However, sometimes dependencies between objects are less direct; for example, a static initializer in a class needs to be triggered, such as device driver registration. The depends-on attribute can explicitly force one or more objects to be initialized before the object using this element is initialized. The following example uses the depends-on attribute to express a dependency on a single object:
<object id="objectOne" type="Examples.ExampleObject, ExamplesLibrary" depends-on="manager"> <property name="manager" ref="manager"/> </object> <object id="manager" type="Examples.ManagerObject, ExamplesLibrary"/>

To express a dependency on multiple objects, supply a list of object names as the value of the 'depends-on' attribute, with commas, whitespace and semicolons used as valid delimiters:
<object id="objectOne" type="Examples.ExampleObject, ExamplesLibrary" depends-on="manager,accountDao"> <property name="manager" ref="manager" /> </object> <object id="manager" type="Examples.ManagerObject, ExamplesLibrary" /> <object id="accountDao" type="Examples.AdoAccountDao, ExamplesLibrary" />

Note
The depends-on attribute in the object definition can specify both an initialization time dependency and, in the case of a singleton object only, a corresponding destroy time dependency. Dependent objects that define a depends-on relationship with a given object are destroyed first, prior to the given object itself being destroyed. Thus depends-on can also control shutdown order.

5.3.5. Lazily-initialized objects


By default, IApplicationContext implementations eagerly pre-instantiate all singleton objects as part of the initialization process. Generally this pre-instantiation is desirable, because errors in configuration or the

Spring Framework (Version 1.3.2)

41

The IoC container surrounding environment are discovered immediately, as opposed to hours or even days later. When this behavior is not desirable, you can prevent pre-instantiation of a singleton object by marking the object definition as lazyinitialized. A lazy-initialized object tells the IoC container to create an object instance when it is first requested, rather than at startup. In XML, this behavior is controlled by the 'lazy-init'attribute on the <object/> element; for example:
<object id="lazy" type="MyCompany.ExpensiveToCreateObject, MyApp" lazy-init="true"/> <object name="not.lazy" type="MyCompany.AnotherObject, MyApp"/>

When the preceding configuration is consumed by an IApplicationContext, the object named lazy is not eagerly pre-instantiated when the IApplicationContext is starting up, whereas the not.lazy object is eagerly preinstantiated. However, when a lazy-initialized object is a dependency of a singleton object that is not lazy-initialized, the IApplicationContext creates the lazy-initialized object at startup, because it must satisfy the singleton's dependencies. The lazy-initialized object is injected into a singleton object elsewhere that is not lazy-initialized. You can also control lazy-initialization at the container level by using the default-lazy-init attribute on the <objects/> element; for example:
<objects default-lazy-init="true"> <!-- no objects will be pre-instantiated... --> </objects>

5.3.6. Autowiring collaborators


The Spring container is able to autowire relationships between collaborating objects. This means that it is possible to automatically let Spring resolve collaborators (other objects) for your object by inspecting the contents of the IoC container.. The autowiring functionality has five modes. Autowiring is specified per object and can thus be enabled for some object, while other objects will not be autowired. Using autowiring, it is possible to reduce or eliminate the need to specify properties or constructor arguments, thus saving a significant amount of typing. When using XML-based configuration metadata, the autowire mode for an object definition is specified by using the autowire attribute of the <object/> element. The following values are allowed: Table 5.3. Autowiring modes Mode no Explanation No autowiring at all. This is the default value and you are encouraged not to change this for large applications, since specifying your collaborators explicitly gives you a feeling for what you're actually doing (always a bonus) and is a great way of somewhat documenting the structure of your system. This option will inspect the objects within the container, and look for an object named exactly the same as the property which needs to be autowired. For example, if you have an object definition that is set to autowire by name, and it contains a Master property, Spring.NET will look for an object definition named Master, and use it as the value of the Master property on your object definition. This option gives you the ability to resolve collaborators by type instead of by name. Supposing you have an IObjectDefinition with a collaborator typed SqlConnection, Spring.NET will search the entire object factory for an object definition of type SqlConnection and use it as the collaborator. If 0 (zero) or more than 1 (one) object

byName

byType

Spring Framework (Version 1.3.2)

42

The IoC container Mode Explanation definitions of the desired type exist in the container, a failure will be reported and you won't be able to use autowiring for that specific object. constructor This is analogous to byType, but applies to constructor arguments. If there isn't exactly one object of the constructor argument type in the object factory, a fatal error is raised. Chooses constructor or byType through introspection of the object class. If a default constructor is found, byType gets applied.

autodetect

Note that explicit dependencies in property and constructor-arg settings always override autowiring. Please also note that it is not currently possible to autowire so-called simple properties such as primitives, Strings, and Types (and arrays of such simple properties). (This is by-design and should be considered a feature.) When using either the byType or constructor autowiring mode, it is possible to wire arrays and typed-collections. In such cases all autowire candidates within the container that match the expected type will be provided to satisfy the dependency. Strongly-typed IDictionaries can even be autowired if the expected key type is string. An autowired IDictionary values will consist of all object instances that match the expected type, and the IDictionary's keys will contain the corresponding object names. Autowire behavior can be combined with dependency checking, which will be performed after all autowiring has been completed. It is important to understand the various advantages and disadvantages of autowiring. Some advantages of autowiring include: Autowiring can significantly reduce the volume of configuration required. However, mechanisms such as the use of a object template (discussed elsewhere in this chapter) are also valuable in this regard. Autowiring can cause configuration to keep itself up to date as your objects evolve. For example, if you need to add an additional dependency to a class, that dependency can be satisfied automatically without the need to modify configuration. Thus there may be a strong case for autowiring during development, without ruling out the option of switching to explicit wiring when the code base becomes more stable. Some disadvantages of autowiring: Autowiring is more magical than explicit wiring. Although, as noted in the above table, Spring is careful to avoid guessing in case of ambiguity which might have unexpected results, the relationships between your Spring-managed objects are no longer documented explicitly. Wiring information may not be available to tools that may generate documentation from a Spring container. Another issue to consider when autowiring by type is that multiple object definitions within the container may match the type specified by the setter method or constructor argument to be autowired. For arrays, collections, or IDictionary, this is not necessarily a problem. However for dependencies that expect a single value, this ambiguity will not be arbitrarily resolved. Instead, if no unique object definition is available, an Exception will be thrown. 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.

5.3.7. Checking for dependencies


The Spring IoC container can check for unresolved dependencies of an object deployed into the container. When enabling checking for unresolved dependencies all properties of the object must have an explicit values set for them in the object definition or have their values set via autowiring.

Spring Framework (Version 1.3.2)

43

The IoC container This feature useful when you want to ensure that all properties (or all properties of a certain type) are set on an object. An object often has default values for many properties, or some properties do not apply to all usage scenarios, so this feature is of limited use. You can enable dependency checking per object, just as with the autowiring functionality. The default is not not check dependencies. In XML-based configuration metadata, you specify dependency checking via the dependency-check attribute in an object definition, which may have the following values. Table 5.4. Dependency checking modes Mode none Explanation (Default) No dependency checking. Properties of the object which have no value specified for them are simply not set. Dependency checking for primitive types and collections (everything except collaborators). Dependency checking for collaborators only. Dependency checking for collaborators, primitive types and collections.

simple object all

5.3.8. Method injection


In most application scenarios, most object in the container are singletons. When a singleton object needs to collaborate with another singleton object, or a non-singleton object needs to collaborate with another nonsingleton object, you typically handle the dependency by defining one object as a property of the other. A problem arrises when the object lifecycles are different. Suppose singleton object A needs to use a non-singleton (prototype) object B, perhaps on each method invocation on A. The container only creates the singleton object A once, and thus only gets one opportunity to set the properties. The container cannot provide object A with a new instance of object B every time one is needed. A solution is to forego some inversion of control. You can make object A aware of the container by implementing the IApplicationContextAware interface, and by making a GetObject("B") call to the container ask for (a typically new) object B every time it needs it. Find below an example of this approach
using System.Collections; using Spring.Objects.Factory; namespace Fiona.Apple { public class CommandManager : IObjectFactoryAware { private IObjectFactory objectFactory; public object Process(IDictionary commandState) { // grab a new instance of the appropriate Command Command command = CreateCommand(); // set the state on the (hopefully brand new) Command instance command.State = commandState; return command.Execute(); } // the Command returned here could be an implementation that executes asynchronously, or whatever protected Command CreateCommand() { return (Command) objectFactory.GetObject("command"); // notice the Spring API dependency } public IObjectFactory ObjectFactory { set { objectFactory = value; }

Spring Framework (Version 1.3.2)

44

The IoC container


} } }

The preceding is not desirable, because the business code is aware of and coupled to the Sring Framework. Method Injection, a somewhat advanced feature of the Spring IoC container, allows this use case to be handled in a clean fashion. 5.3.8.1. Lookup Method Injection Lookup method injection is the ability of the container to override methods on container managed objects, to return the result of looking up another named object in the container. The lookup typically involves a prototype object as in the scenario described in the preceding section. The Spring framework implements this method injection by a dynamically generating a subclass overriding the method using the classes in the System.Reflection.Emit namespace.

Note
You can read more about the motivation for Method Injection in this blog entry [http:// blog.springframework.com/rod/?p=1]. Looking at the CommandManager class in the previous code snippit, you see that the Spring container will dynamically override the implementation of the CreateCommand() method. Your CommandManager class will not have any Spring dependencies, as can be seen in this reworked example below:
using System.Collections; namespace Fiona.Apple { public abstract class CommandManager { public object Process(IDictionary commandState) { Command command = CreateCommand(); command.State = commandState; return command.Execute(); } // okay... but where is the implementation of this method? protected abstract Command CreateCommand(); } }

In the client class containing the method to be injected (the CommandManager in this case) the method to be injected requires a signature of the following form:
<public|protected> [abstract] <return-type> TheMethodName(no-arguments);

If the method is abstract, the dynamically-generated subclass implements the method. Otherwise, the dynamically-generated subclass overrides the concrete method defined in the original class. Let's look at an example:
<!-- a stateful object deployed as a prototype (non-singleton) --> <object id="command" class="Fiona.Apple.AsyncCommand, Fiona" singleton="false"> <!-- inject dependencies here as required --> </object> <!-- commandProcessor uses a statefulCommandHelpder --> <object id="commandManager" type="Fiona.Apple.CommandManager, Fiona"> <lookup-method name="CreateCommand" object="command"/>

Spring Framework (Version 1.3.2)

45

The IoC container


</object>

The object identified as commandManager will calls its own method CreateCommand whenever it needs a new instance of the command object. You must be careful to deploy the command object as prototype, if that is actually what is needed. If it is deployed as a singleton the same instance of singleShotHelper will be returned each time. Note that lookup method injection can be combined with Constructor Injection (supplying optional constructor arguments to the object being constructed), and also with Setter Injection (settings properties on the object being constructed). 5.3.8.2. Arbitrary method replacement A less commonly useful form of method injection than Lookup Method Injection is the ability to replace arbitrary methods in a managed object with another method implementation. With XML-based configuration metadata, you can use the replaced-method element to replace an existing method implementation with another, for a deployed object. Consider the following class, with a method ComputeValue, which we want to override:
public class MyValueCalculator { public virtual string ComputeValue(string input) { // ... some real code } // ... some other methods }

A class implementing the Spring.Objects.Factory.Support.IMethodReplacer interface is needed to provide the new (injected) method definition.
/// <summary> /// Meant to be used to override the existing ComputeValue(string) /// implementation in MyValueCalculator. /// </summary> public class ReplacementComputeValue : IMethodReplacer { public object Implement(object target, MethodInfo method, object[] arguments) { // get the input value, work with it, and return a computed result... string value = (string) arguments[0]; // compute... return result; } }

The object definition to deploy the original class and specify the method override would look like this:
<object id="myValueCalculator" type="Examples.MyValueCalculator, ExampleAssembly"> <!-- arbitrary method replacement --> <replaced-method name="ComputeValue" replacer="replacementComputeValue"> <arg-type match="String"/> </replaced-method> </object> <object id="replacementComputeValue" type="Examples.ReplacementComputeValue, ExampleAssembly"/>

You can use one or more contained arg-type elements within the replaced-method element to indicate the method signature of the method being overridden. The signature for the arguments is necessaryonly if the method is overloaded and multiple variants exist within the class. For convenience, the type string for an argument may be a substring of the fully qualified type name. For example, the following all match System.String.
System.String

Spring Framework (Version 1.3.2)

46

The IoC container


String Str

Because the number of arguments is often enough to distinguish between each possible choice, this shortcut can save a lot of typing, by allowing you to typ just the shortest string which will match an argument type.

5.3.9. Setting a reference using the members of other objects and classes.
This section details those configuration scenarios that involve the setting of properties and constructor arguments using the members of other objects and classes. This kind of scenario is quite common, especially when dealing with legacy classes that you cannot (or won't) change to accommodate some of Spring.NET's conventions... consider the case of a class that has a constructor argument that can only be calculated by going to say, a database. The MethodInvokingFactoryObject handles exactly this scenario ... it will allow you to inject the result of an arbitrary method invocation into a constructor (as an argument) or as the value of a property setter. Similarly, PropertyRetrievingFactoryObject and FieldRetrievingFactoryObject allow you to retrieve values from another object's property or field value. These classes implement the IFactoryObject interface which indicates to Spring.NET that this object is itself a factory and the factories product, not the factory itself, is what will be associated with the object id. Factory objects are discussed further in Section 5.9.3, Customizing instantiation logic using IFactoryObjects 5.3.9.1. Setting a reference to the value of property. The PropertyRetrievingFactoryObject is an IFactoryObject that addresses the scenario of setting one of the properties and / or constructor arguments of an object to the value of a property exposed on another object or class. One can use it to get the value of any public property exposed on either an instance or a class (in the case of a property exposed on a class, the property must obviously be static). In the case of a property exposed on an instance, the target object that a PropertyRetrievingFactoryObject will evaluate can be either an object instance specified directly inline or a reference to another arbitrary object. In the case of a static property exposed on a class, the target object will be the class (the .NET System.Type) exposing the property. The result of evaluating the property lookup may then be used in another object definition as a property value or constructor argument. Note that nested properties are supported for both instance and class property lookups. The IFactoryObject is discussed more generally in Section 5.9.3, Customizing instantiation logic using IFactoryObjects. Here's an example where a property path is used against another object instance. In this case, an inner object definition is used and the property path is nested, i.e. spouse.age.
<object name="person" type="Spring.Objects.TestObject, Spring.Core.Tests"> <property name="age" value="20"/> <property name="spouse"> <object type="Spring.Objects.TestObject, Spring.Core.Tests"> <property name="age" value="21"/> </object> </property> </object> // will result in 21, which is the value of property 'spouse.age' of object 'person' <object name="theAge" type="Spring.Objects.Factory.Config.PropertyRetrievingFactoryObject, Spring.Core"> <property name="TargetObject" ref="person"/> <property name="TargetProperty" value="spouse.age"/> </object>

An example of using a PropertyRetrievingFactoryObject to evaluate a static property is shown below.

Spring Framework (Version 1.3.2)

47

The IoC container


<object id="cultureAware" type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests"> <property name="culture" ref="cultureFactory"/> </object> <object id="cultureFactory" type="Spring.Objects.Factory.Config.PropertyRetrievingFactoryObject, Spring.Core"> <property name="StaticProperty"> <value>System.Globalization.CultureInfo.CurrentUICulture, Mscorlib</value> </property> </object>

Similarly, an example showing the use of an instance property is shown below.


<object id="instancePropertyCultureAware" type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests"> <property name="Culture" ref="instancePropertyCultureFactory"/> </object> <object id="instancePropertyCultureFactory" type="Spring.Objects.Factory.Config.PropertyRetrievingFactoryObject, Spring.Core"> <property name="TargetObject" ref="instancePropertyCultureAwareSource"/> <property name="TargetProperty" value="MyDefaultCulture"/> </object> <object id="instancePropertyCultureAwareSource" type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests"/>

5.3.9.2. Setting a reference to the value of field. The FieldRetrievingFactoryObject class addresses much the same area of concern as the PropertyRetrievingFactoryObject described in the previous section. However, as its name might suggest, the FieldRetrievingFactoryObject class is concerned with looking up the value of a public field exposed on either an instance or a class (and similarly, in the case of a field exposed on a class, the field must obviously be static). The following example demonstrates using a FieldRetrievingFactoryObject to look up the value of a (public, static) field exposed on a class
<object id="withTypesField" type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests"> <property name="Types" ref="emptyTypesFactory"/> </object> <object id="emptyTypesFactory" type="Spring.Objects.Factory.Config.FieldRetrievingFactoryObject, Spring.Core"> <property name="TargetType" value="System.Type, Mscorlib"/> <property name="TargetField" value="EmPTytypeS"/> </object>

The example in the next section demonstrates the look up of a (public) field exposed on an object instance.
<object id="instanceCultureAware" type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests"> <property name="Culture" ref="instanceCultureFactory"/> </object> <object id="instanceCultureFactory" type="Spring.Objects.Factory.Config.FieldRetrievingFactoryObject, Spring.Core"> <property name="TargetObject" ref="instanceCultureAwareSource"/> <property name="TargetField" value="Default"/> </object> <object id="instanceCultureAwareSource" type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests"/>

Spring Framework (Version 1.3.2)

48

The IoC container 5.3.9.3. Setting a property or constructor argument to the return value of a method invocation. The MethodInvokingFactoryObject rounds out the trio of classes that permit the setting of properties and constructor arguments using the members of other objects and classes. Whereas the PropertyRetrievingFactoryObject and FieldRetrievingFactoryObject classes dealt with simply looking up and returning the value of property or field on an object or class, the MethodInvokingFactoryObject allows one to set a constructor or property to the return value of an arbitrary method invocation, The MethodInvokingFactoryObject class handles both the case of invoking an (instance) method on another object in the container, and the case of a static method call on an arbitrary class. Additionally, it is sometimes necessary to invoke a method just to perform some sort of initialization.... while the mechanisms for handling object initialization have yet to be introduced (see Section 5.6.1.1, IInitializingObject / initmethod), these mechanisms do not permit any arguments to be passed to any initialization method, and are confined to invoking an initialization method on the object that has just been instantiated by the container. The MethodInvokingFactoryObject allows one to invoke pretty much any method on any object (or class in the case of a static method). The following example (in an XML based IObjectFactory definition) uses the MethodInvokingFactoryObject class to force a call to a static factory method prior to the instantiation of the object...
<object id="force-init" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core"> <property name="StaticMethod"> <value>ExampleNamespace.ExampleInitializerClass.Initialize</value> </property> </object> <object id="myService" depends-on="force-init"/>

Note that the definition for the myService object has used the depends-on attribute to refer to the force-init object, which will force the initialization of the force-init object first (and thus the calling of its configured StaticMethod static initializer method, when myService is first initialized. Please note that in order to effect this initialization, the MethodInvokingFactoryObject object must be operating in singleton mode (the default.. see the next paragraph). Note that since this class is expected to be used primarily for accessing factory methods, this factory defaults to operating in singleton mode. As such, as soon as all of the properties for a MethodInvokingFactoryObject object have been set, and if the MethodInvokingFactoryObject object is still in singleton mode, the method will be invoked immediately and the return value cached for later access. The first request by the container for the factory to produce an object will cause the factory to return the cached return value for the current request (and all subsequent requests). The IsSingleton property may be set to false, to cause this factory to invoke the target method each time it is asked for an object (in this case there is obviously no caching of the return value). A static target method may be specified by setting the targetMethod property to a string representing the static method name, with TargetType specifying the Type that the static method is defined on. Alternatively, a target instance method may be specified, by setting the TargetObject property to the name of another Spring.NET managed object definition (the target object), and the TargetMethod property to the name of the method to call on that target object. Arguments for the method invocation may be specified in two ways (or even a mixture of both)... the first involves setting the Arguments property to the list of arguments for the method that is to be invoked. Note that the ordering of these arguments is significant... the order of the values passed to the Arguments property must be the same as the order of the arguments defined on the method signature, including the argument Type. This is shown in the example below

Spring Framework (Version 1.3.2)

49

The IoC container


<object id="myObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core"> <property name="TargetType" value="Whatever.MyClassFactory, MyAssembly"/> <property name="TargetMethod" value="GetInstance"/> <!-- the ordering of arguments is significant --> <property name="Arguments"> <list> <value>1st</value> <value>2nd</value> <value>and 3rd arguments</value> <!-- automatic Type-conversion will be performed prior to invoking the method --> </list> </property> </object>

The second way involves passing an arguments dictionary to the NamedArguments property... this dictionary maps argument names (Strings) to argument values (any object). The argument names are not case-sensitive, and order is (obviously) not significant (since dictionaries by definition do not have an order). This is shown in the example below
<object id="myObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core"> <property name="TargetObject"> <object type="Whatever.MyClassFactory, MyAssembly"/> </property> <property name="TargetMethod" value="Execute"/> <!-- the ordering of named arguments is not significant --> <property name="NamedArguments"> <dictionary> <entry key="argumentName"><value>1st</value></entry> <entry key="finalArgumentName"><value>and 3rd arguments</value></entry> <entry key="anotherArgumentName"><value>2nd</value></entry> </dictionary> </property> </object>

The following example shows how use MethodInvokingFactoryObject to call an instance method.
<object id="myMethodObject" type="Whatever.MyClassFactory, MyAssembly" /> <object id="myObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core"> <property name="TargetObject" ref="myMethodObject"/> <property name="TargetMethod" value="Execute"/> </object>

The above example could also have been written using an anonymous inner object definition... if the object on which the method is to be invoked is not going to be used outside of the factory object definition, then this is the preferred idiom because it limits the scope of the object on which the method is to be invoked to the surrounding factory object. Finally, if you want to use MethodInvokingFactoryObject in conjunction with a method that has a variable length argument list, then please note that the variable arguments need to be passed (and configured) as a list. Let us consider the following method definition that uses the params keyword (in C#), and its attendant (XML) configuration...
[C#] public class MyClassFactory { public object CreateObject(Type objectType, params string[] arguments) { return ... // implementation elided for clarity... } }

<object id="myMethodObject" type="Whatever.MyClassFactory, MyAssembly" />

Spring Framework (Version 1.3.2)

50

The IoC container


<object id="paramsMethodObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core"> <property name="TargetObject" ref="myMethodObject"/> <property name="TargetMethod" value="CreateObject"/> <property name="Arguments"> <list> <value>System.String</value> <!-- here is the 'params string[] arguments' --> <list> <value>1st</value> <value>2nd</value> </list> </list> </object>

5.3.10. Provided IFactoryObject implementations


In addition to
PropertyRetrievingFactoryObject, MethodInvokingFactoryObject,

and

Spring.NET comes with other useful implementations of the IFactoryObject interface. These are discussed below.
FieldRetrievingFactoryObject

5.3.10.1. Common logging The LogFactoryObject is useful when you would like to share a Common.Logging log object across a number of classes instead of creating a logging instance per class or class hierarchy. Information on the Common.Logging project can be found here [http://netcommon.sourceforge.net/]. In the example shown below the same logging instance, with a logging category name of "DAOLogger", is used in both the SimpleAccountDao and SimpleProductDao data access objects.
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd" > <object name="daoLogger" type="Spring.Objects.Factory.Config.LogFactoryObject, Spring.Core"> <property name="logName" value="DAOLogger"/> </object> <object name="productDao" type="PropPlayApp.SimpleProductDao, PropPlayApp "> <property name="maxResults" value="100"/> <property name="dbConnection" ref="myConnection"/> <property name="log" ref="daoLogger"/> </object> <object name="accountDao" type="PropPlayApp.SimpleAccountDao, PropPlayApp "> <property name="maxResults" value="100"/> <property name="dbConnection" ref="myConnection"/> <property name="log" ref="daoLogger"/> </object> <object name="myConnection" type="System.Data.Odbc.OdbcConnection, System.Data"> <property name="connectionstring" value="dsn=MyDSN;uid=sa;pwd=myPassword;"/> </object> </objects>

5.4. Object Scopes


When you create an object definition, you create a recipe for creating actual instances of the class defined by that object definition. The idea that an object definition is a recipe is important, because it means that, as with a class, you can create many object instances from a single recipe. You can control not only the various dependencies and configuration values that are to be plugged into an object that is created from a particular object definition, but also the scope of the objects created from a particular object

Spring Framework (Version 1.3.2)

51

The IoC container definition. This approach powerful and flexible in that you can choose the scope of the objects you create through configuration instead of having to bake in the scope of an object at the .NET class level. Ob jects can be defined to be deployed in one of a number of scopes: out of the box, the Spring Framework supports five scopes, three of which are available only if you use a web-aware IApplicationContext. The following scopes supported. Support for user defined custom scopes is planned for Spring .NET 2.0. Table 5.5. Object Scopes Scope singleton Description Scopes a single object definition to a single object instance per Spring IoC container. Scopes a single object definition to any number of object instances. Scopes a single object definition to the lifecycle of a single HTTP request; that is, each and every HTTP request has its own instance of an object created off the back of a single object definition. Only valid in the context of a web-aware Spring ApplicationContext. Scopes a single object definition to the lifecycle of a HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext. Scopes a single object definition to the lifecycle of a web application. Only valid in the context of a web-aware Spring ApplicationContext.

prototype request

session

application

5.4.1. The singleton scope


Singleton scoped objects have only one shared instance of an object managed by the container. All request for objects with an id or ids matching that object definition result in that one specific object instance being returned by the Spring container. To put it another way, when you define an object definition and it is scoped as a singleton, the Spring IoC container creates exactly one instance of the object defined by that object definition. This single instance is stored in a cache of such singleton object, and all subsequent requests and references for that named object return the cached object. Spring's concept of a singleton differns from the Singleton pattern as defined in the Gang of Four (GoF) patterns book. The GoF Singleton hard-codes the scope of an object such that one and only one instance of a particular class is created per ApplicationDomain. The scope of the Spring singleton is best described as per container and per object. This means that if you define one object for a particular class in a single Spring container, then the Spring container creates one and only one instance of the class defined by that object definition. The singleton scope is the default scope in Spring. To define an object as a singleton in XML, you would write, for example:
<object id="accountService" type="MyApp.DefaultAccountService, MyApp"/> <!-- the following is equivalent, though redundant (singleton scope is the default) --> <object id="accountService" type="MyApp.DefaultAccountService, MyApp" singleton="true"/>

5.4.2. The prototype scope


The non-singleton, prototype scope of object deployment results in the creation of a new object instance every time a request for that specific object is made. That is, the object is injected into another object or you request

Spring Framework (Version 1.3.2)

52

The IoC container through a GetObject() method call on the container. As a rule use the prototype scope for all objects that are stateful and the singleton scope for stateless objects. The following examples defines an object as a prototype in XML:
<object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary" scope="prototype"/>

Note
The <singleton/> attribute was introduced Spring 1.0 as there were only two types of scopes, singleton and prototype. The element singleton=true refers to singleton scope and singleton=false refers to prototype scope. In Spring 1.1 the additional web scopes were introduced along with the new elment 'scope'. The scope element is the preferred element to use. In contrast to the other scopes, Spring does not manage the complete lifecycle of a prototype object: the container instantiates, configures, decorates and otherwise assembles a prototype object, hands it to the client, with no further record of that prototype instance. Thus, although initialization lifecycle callback methods are called on all objects regardless of scope, in the case of prototypes, configured destruction lifecycle callbacks are not called. The client code must clean up prototype-scoped objects and release any expensive resources that the prototype object(s) are holding. To get the Spring container to release resources held by prototype-scoped objects, try using a custom object post processor which would hold a reference to the objects that need to be cleaned up. In some respects, the Spring container's role in regard to a prototype-scoped object is a replacement for the C# 'new' operator. All lifecycle management past that point must be handled by the client. (For details on the lifecycle of an object in the Spring container, see Section 5.6.1, Lifecycle interfaces.

5.4.3. Singleton objects with prototype-object dependencies


When you use singleton-scoped objects with dependencies on prototype objects, be aware that dependencies are resolved at instantiation time. Thus if you dependency-inject a prototype-scoped objects into a singletonscoped object, a new prototype object is instantiated and then dependency-injected into the singleton object. The prototype instance is the sole instance that is ever supplied to the singleton-scoped object. However, suppose you want the singleton-scoped object to acquire a new instance of the prototype-scoped object repeatedly at runtime. You cannot dependency-inject a prototype-scoped object into your singleton object, because that injection occurs only once, when the Spring container is instantiating the singleton object and resolving and injecting its dependencies. If you need a new instance of a prototype object at runtime more than once, see Section 5.3.8, Method injection.

5.4.4. Request, session and web application scopes


The request, session and application scopes are only available if you use a web-aware Spring IApplicationContext implementation, such as WebApplicationContext. If you use these scopes with regular Spring IoC containers such as the XmlApplicationContext, you will get an exception complaining about an unknown object scope. Please refer to the web documentation on object scopes for more information.

5.5. Type conversion


Type converters are responsible for converting objects from one type to another. When using the XML based file to configure the IoC container, string based property values are converted to the target property type. Spring will

Spring Framework (Version 1.3.2)

53

The IoC container rely on the standard .NET support for type conversion unless an alternative TypeConverter is registered for a given type. How to register custom TypeConverters will be described shortly. As a reminder, the standard .NET type converter support works by associating a TypeConverter attribute with the class definition by passing the type of the converter as an attribute argument. 3 For example, an abbreviated class definition for the BCL type Font is shown below.
[Serializable, TypeConverter(typeof(FontConverter)), ...] public sealed class Font : MarshalByRefObject, ICloneable, ISerializable, IDisposable { // Methods ... etc .. }

5.5.1. Type Conversion for Enumerations


The default type converter for enumerations is the System.ComponentModel.EnumConverter class. To specify the value for an enumerated property, simply use the name of the property. For example the TestObject class has a property of the enumerated type FileMode. One of the values for this enumeration is named Create. The following XML fragment shows how to configure this property
<object id="rod" type="Spring.Objects.TestObject, Spring.Core.Tests"> <property name="name" value="Rod"/> <property name="FileMode" value="Create"/> </object>

5.5.2. Built-in TypeConverters


Spring.NET pre-registers a number of custom TypeConverter instances (for example, to convert a type expressed as a string into a real System.Type object). Each of those is listed below and they are all located in the Spring.Objects.TypeConverters namespace of the Spring.Core library. Table 5.6. Built-in TypeConverters Type
RuntimeTypeConverter

Explanation Parses strings representing System.Types to actual System.Types and the other way around. Capable of resolving strings to a System.IO.FileInfo object. Capable of resolving a comma-delimited list of strings to a stringarray and vice versa. Capable of resolving a string representation of a Uri to an actual Uriobject. Capable of resolving a string representation of a credential for Web client authentication into an instance of System.Net.ICredentials Capable of resolving Spring IResource Uri (string) to its corresponding InputStream-object. Capable of resolving Spring IResource Uri (string) to an IResource object.

FileInfoConverter StringArrayConverter

UriConverter

CredentialConverter

StreamConverter

ResourceConverter

More information about creating custom TypeConverter implementations can be found online at Microsoft's MSDN website, by searching for Implementing a Type Converter.

Spring Framework (Version 1.3.2)

54

The IoC container Type


ResourceManagerConverter

Explanation Capable of resolving a two part string (resource name, assembly name) to a System.Resources.ResourceManager object. Capable of resolving a comma separated list of Red, Green, Blue integer values to a System.Drawing.Color structure. Capable of resolving a string into an instance of an object that implements the IExpression interface. Capable of resolving an XML formatted string to a

RgbColorConverter

ExpressionConverter

NameValueConverter

Specialized.NameValueCollection RegexConverter RegistryKeyConverter

Capable of resolving a string into an instance of Regex Capable of resolving a string into a Microsoft.Win32.RegistryKey object.

Spring.NET uses the standard .NET mechanisms for the resolution of System.Types, including, but not limited to checking any configuration files associated with your application, checking the Global Assembly Cache (GAC), and assembly probing.

5.5.3. Custom Type Conversion


There are a few ways to register custom type converters. The fundamental storage area in Spring for custom type converters is the TypeConverterRegistry class. The most convenient way if using an XML based implementation of IObjectFactory or IApplicationContext is to use the custom configuration section handler TypeConverterSectionHandler This is demonstrated in section Section 5.11, Configuration of IApplicationContext An alternate approach, present for legacy reasons in the port of Spring.NET from the Java code base, is to use the object factory post-processor Spring.Objects.Factory.Config.CustomConverterConfigurer. This is described in the next section. If you are constructing your interface. IoC container Programatically
TypeConverter

then

RegisterCustomConverter(Type ConfigurableObjectFactory

requiredType,

should use converter) method of

you

the the

5.5.3.1. Using CustomConverterConfigurer This section shows in detail how to define a custom type converter that does not use the .NET TypeConverter attribute. The type converter class is standalone and inherits from the TypeConverter class. It uses the legacy factory post-processor approach. Consider a user class ExoticType, and another class DependsOnExoticType which needs ExoticType set as a property:
public class ExoticType { private string name; public ExoticType(string name) { this.name = name; }

Spring Framework (Version 1.3.2)

55

The IoC container


public string Name { get { return this.name; } } }

and
public class DependsOnExoticType { public DependsOnExoticType() {} private ExoticType exoticType; public ExoticType ExoticType { get { return this.exoticType; } set { this.exoticType = value; } } public override string ToString() { return exoticType.Name; } }

When things are properly set up, we want to be able to assign the type property as a string, which a TypeConverter will convert into a real ExoticType object behind the scenes:
<object name="sample" type="SimpleApp.DependsOnExoticType, SimpleApp"> <property name="exoticType" value="aNameForExoticType"/> </object>

The TypeConverter looks like this:


public class ExoticTypeConverter : TypeConverter { public ExoticTypeConverter() { } public override bool CanConvertFrom ( ITypeDescriptorContext context, Type sourceType) { if (sourceType == typeof (string)) { return true; } return base.CanConvertFrom (context, sourceType); } public override object ConvertFrom ( ITypeDescriptorContext context, CultureInfo culture, object value) { string s = value as string; if (s != null) { return new ExoticType(s.ToUpper()); } return base.ConvertFrom (context, culture, value); } }

Finally, we use the CustomConverterConfigurer to register the new TypeConverter with the IApplicationContext, which will then be able to use it as needed:
<object id="customConverterConfigurer" type="Spring.Objects.Factory.Config.CustomConverterConfigurer, Spring.Core"> <property name="CustomConverters">

Spring Framework (Version 1.3.2)

56

The IoC container


<dictionary> <entry key="SimpleApp.ExoticType"> <object type="SimpleApp.ExoticTypeConverter"/> </entry> </dictionary> </property> </object>

5.6. Customizing the nature of an object


5.6.1. Lifecycle interfaces
To interact with the container's management of the object lifecycle, you can implement the Spring InitializingObject and standard System.IDisposable interfaces. The container calls AfterPropertiesSet() method for the former and the Dispose() method for the latter, thus allowing you to do things upon the initialization and destruction of your objects. You can also achieve the same integration with the container without coupling your objects to Spring interfaces though the use of init-method and destroy-method object definition metadata. Internally, Spring.NET uses implementations of the IObjectPostProcessor interface to process any call interfaces it can find and call the appropriate methods. If you need custom features or other lifecycle behavior Spring.NET does not offer out-of-the-box, you can implement an IObjectPostProcessor yourself. For more information seeSection 5.9.1, Customizing objects with IObjectPostProcessors. 5.6.1.1. IInitializingObject / init-method The Spring.Objects.Factory.IInitializingObject interface allows an object to perform initialization work after all the necessary properties on an object are set by the container. The IInitializingObject interface specifies a single method: void AfterPropertiesSet(): called after all properties have been set by the container. This method enables you to do checking to see if all necessary properties have been set correctly, or to perform further initialization work. You can throw any Exception to indicate misconfiguration, initialization failures, etc. It is recommended that you do not use the IInitializingObject interface because it unnecessarily coupules the code to Spring. Alternatively, specify an POJO initialization method. In the case of XML-based configuration metadata, you use the init-method attribute to specify the name of the method that has a void no-argument signature. For example, the following definition:
<object id="exampleInitObject" type="Examples.ExampleObject" init-method="init"/> [C#] public class ExampleObject { public void Init() { // do some initialization work } }

...is exactly the same as...


<object id="exampleInitObject" type="Examples.AnotherExampleObject"/> [C#] public class AnotherExampleObject : IInitializingObject { public void AfterPropertiesSet() { // do some initialization work }

Spring Framework (Version 1.3.2)

57

The IoC container


}

... but does not couple the code to Spring.NET. 5.6.1.2. IDisposable / destroy-method Implementing the System.IDisposable interface allows an object to get a callback callback when the container containing it is destroyed. The IDisposable interface specifies a single method: void Dispose(): and is called on destruction of the container. This allows you to release any resources you are keeping in this object (such as database connections). You can throw any Exception here... however, any such Exception will not stop the destruction of the container - it will only get logged.v Since the IDisposable interface resides in the core .NET library, it does not couple your class to Spring as in the case with the IInitializingObject interface. However, you may also specify a destruction method that is not tied to the IDisposable interface. In the case of XML-based configuration metadata, you use the destroy-method attribute to specify the name of the method that has a void no-argument signature. For example, the following definition:
<object id="exampleInitObject" type="Examples.ExampleObject" destroy-method="cleanup"/> [C#] public class ExampleObject { public void cleanup() { // do some destruction work (such as closing any open connection (s)) } }

is exactly the same as:


<object id="exampleInitObject" type="Examples.AnotherExampleObject"/> [C#] public class AnotherExampleObject : IDisposable { public void Dispose() { // do some destruction work } }

5.6.2. IApplicationContextAware and IObjectNameAware


When an IApplicationContext creates a class that implements the IApplicationContextAware interface, the class is provided with a reference to that IApplicationContext.
public interface IApplicationContextAware { IApplicationContext ApplicationContext { set; } }

Thus objects can manipulate programmatically the IApplicationContext that created them, through the IApplicationContext interface, or by casting the reference to a known subclass of this interface, such as IConfigurableApplicationContext, which exposes additional functionality. One use would be the programmatic retrieval of other objects. Sometimes this capability is useful; however, in general you should avoid it, because it couples the code to Spring and does not follow the Inversion of Control style, where collaborators are provided to objects as properties. Other methods of the IApplicationContext provide access to file resources, publishing application events, and accessing a IMessageSource. These additional features are described in Section 5.10, The IApplicationContext

Spring Framework (Version 1.3.2)

58

The IoC container 5.6.2.1. IObjectNameAware When an IApplicationContext creates a class that implements the Spring.Objects.Factory.IObjectNameAware interface, the class is provided with a reference to the name defined in its associated object definition.
public interface IObjectNameAware { string ObjectName { set; } }

The callback is invoked after population of normal object properties but before an initialization callback such as IInitializingObject 's AfterPropertiesSet method or a custom initalization method is invoked.

5.7. Object definition inheritance


An object definition can contain a lot of configuration information, including constructor arguments, property values, and container-specific information such as initialization method, static factory method name, and so on. A child object definition inherits configuration data from a parent definition. The child definition can override some values, or add others, as needed. Using parent and child object definitions can save a lot of typing. Effectively, this is a form of templating. If you work with an IApplicationContext interface programmatically, child object definitions are represented by the ChildObjectDefinition class. Most users do not work with them on this level, instead configuring object definitions declaratively in something like the XmlApplicationContext. When you use XML-based configuration metadata, you indicate a child object using the parent attribute, specifying the parent object definition as the value of this attribute.
<object id="inheritedTestObject" type="Spring.Objects.TestObject, Spring.Core.Tests" abstract="true"> <property name="name" value="parent"/> <property name="age" value="1"/> </object> <object id="inheritsWithDifferentClass" type="Spring.Objects.DerivedTestObject, Spring.Core.Tests" parent="inheritedTestObject" init-method="Initialize"> <property name="name" value="override"/> <!-- age will inherit value of 1 from parent --> </object>

A child object definition uses the object class from the parent definition if none is specified, but can also override it. In the latter case, the child object class must be compatible with the parent, that is, it must accept the parent's property values. A child object definition inherits constructor argument values, property values and method overrides from the parent, with the option to add new values. Any initialization method, destroy method and/or static factory methods that you specify will override the corresponding parent settings. The remaining settings are always be taken from the child definition: depends on, autowire mode, dependency check, singleton, lazy init. The preceding example explicitly marks the parent object definition as abstract using the abstract attribute. If the parent definition does not specify a class, explicitly marking the parent object definition as abstract is required, as follows:
<object id="inheritedTestObjectWithoutClass" abstract="true"> <property name="name" value="parent"/> <property name="age" value="1"/> </object> <object id="inheritsWithClass" type="Spring.Objects.DerivedTestObject, Spring.Core.Tests"

Spring Framework (Version 1.3.2)

59

The IoC container


parent="inheritedTestObjectWithoutClass" init-method="Initialize"> <property name="name" value="override"/> <!-- age will inherit value of 1 from parent --> </object>

The parent object cannot be instantiated on its own since it incomplete, and it is also explicitly marked as abstract. When a definition is abstract like this, it is usable only as a pure template object definition that serves as a parent definition for child definitions. Trying to use such an abstract parent object on its own, by referring to it as a ref property of another object, or doing an explicit GetObject() with the parent object id, returns an error. The container's internal PreInstantiateSingletons method will completely ignore object definitions that are considered abstract.

Note
Application contexts pre-instantiate all singletons by default. Therefore it is important (at least for singleton objects) that if you have a (parent) object definition which you intend to use only as a template, and this definition specifies a class, you must make sure to set the abstract attribute to true , otherwise the application context will actually (attempt to) pre-instantiate the abstract object.

5.8. Container extension points


The Spring container is essentially nothing more than an advanced factory capable of maintaining a registry of different objects and their dependencies. The IObjectFactory enables you to read object definitions and access them using the object factory. When using just the IObjectFactory you would create an instance of one and then read in some object definitions in the XML format as follows:
[C#] IResource input = new FileSystemResource ("objects.xml"); XmlObjectFactory factory = new XmlObjectFactory(input);

That is pretty much it. Using GetObject(string) (or the more concise indexer method factory ["string"]) you can retrieve instances of your objects...
[C#] object foo = factory.GetObject ("foo"); // gets the object defined as 'foo' object bar = factory ["bar"]; // same thing, just using the indexer

You'll get a reference to the same object if you defined it as a singleton (the default) or you'll get a new instance each time if you set the singleton property of your object definition to false.
<object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary"/> <object id="anotherObject" type="Examples.ExampleObject, ExamplesLibrary" singleton="false"/>

[C#] object one = factory ["exampleObject"]; object two = factory ["exampleObject"]; Console.WriteLine (one == two) object three = factory ["anotherObject"]; object four = factory ["anotherObject"]; Console.WriteLine (three == four);

// gets the object defined as 'exampleObject' // prints 'true' // gets the object defined as 'anotherObject' // prints 'false'

The client-side view of the IObjectFactory is surprisingly simple. The IObjectFactory interface has only seven methods (and the aforementioned indexer) for clients to call: bool ContainsObject(string): returns true if the IObjectFactory contains an object definition that matches the given name.

Spring Framework (Version 1.3.2)

60

The IoC container object GetObject(string): returns an instance of the object registered under the given name. Depending on how the object was configured by the IObjectFactory configuration, either a singleton (and thus shared) instance or a newly created object will be returned. An ObjectsException will be thrown when either the object could not be found (in which case it'll be a NoSuchObjectDefinitionException), or an exception occurred while instantiated and preparing the object. Object this [string]: this is the indexer for the IObjectFactory interface. It functions in all other respects in exactly the same way as the GetObject(string) method. The rest of this documentation will always refer to the GetObject(string) method, but be aware that you can use the indexer anywhere that you can use the GetObject(string) method. Object GetObject(string, Type): returns an object, registered under the given name. The object returned will be cast to the given Type. If the object could not be cast, corresponding exceptions will be thrown (ObjectNotOfRequiredTypeException). Furthermore, all rules of the GetObject(string) method apply (see above). bool IsSingleton(string): determines whether or not the object definition registered under the given name is a singleton or a prototype. If the object definition corresponding to the given name could not be found, an exception will be thrown (NoSuchObjectDefinitionException) string[] GetAliases(string): returns the aliases for the given object name, if any were defined in the IObjectDefinition. void ConfigureObject(object target, string name): Injects dependencies into the supplied target instance assigning the supplied name to the abstract object definition. This method is typically used when objects are instantiated outside the control of a developer, for example when ASP.NET instantiates web controls and when a WinForms application creates UserControls. A sub-interface of IObjectFactory, IConfigurableObjectFactory adds some convenient methods such as void RegisterSingleton(string name, object objectInstance) : Register the given existing object as singleton in the object factory under the given object name. void RegisterAlias(string name, string theAlias); Given an object name, create an alias. Check the SDK docs for additional details on IConfigurableObjectFactory methods and properties and the full IObjectFactory class hierarchy.

5.8.1. Obtaining an IFactoryObject, not its product


Sometimes there is a need to ask an IObjectFactory for an actual IFactoryObject instance itself, not the object it produces. This may be done by prepending the object id with & when calling the GetObject method of the IObjectFactory and IApplicationContext interfaces. So for a given IFactoryObject with an id myObject, invoking GetObject("myObject") on the IObjectFactory will return the product of the IFactoryObject, but invoking GetObject("&myObject") will return the IFactoryObject instance itself.

5.9. Container extension points


The IoC component of the Spring Framework has been designed for extension. There is typically no need for an application developer to subclass any of the various IObjectFactory or IApplicationContext implementation classes. The Spring IoC container can be infinitely extended by plugging in implementations of special integration interfaces. The next few sections are devoted to detailing all of these various integration interfaces.

5.9.1. Customizing objects with IObjectPostProcessors


The first extension point that we will look at is the Spring.Objects.Factory.Config.IObjectPostProcessor interface. This interface defines a number of callback methods that you as an application developer can implement

Spring Framework (Version 1.3.2)

61

The IoC container in order to provide your own (or override the containers default) instantiation logic, dependency-resolution logic, and so forth. If you want to do some custom logic after the Spring container has finished instantiating, configuring and otherwise initializing an object, you can plug in one or more IObjectPostProcessor implementations. You can configure multiple IObjectPostProcessors if you wish. You can control the order in which these IObjectPostProcessor execute by setting the 'Order' property (you can only set this property if the IObjectPostProcessor implements the IOrdered interface; if you write your own IObjectPostProcessor you should consider implementing the IOrdered interface too); consult the SDK docs for the IObjectPostProcessor and IOrdered interfaces for more details.

Note
IObjectPostProcessor operate on object instances; that is to say, the Spring IoC container will have

instantiated a object instance for you, and then IObjectPostProcessors get a chance to do their stuff. If you want to change the actual object definition (that is the recipe that defines the object), then you rather need to use a IObjectFactoryPostProcessor (described below in the section entitled Customizing configuration metadata with IObjectFactoryPostProcessors. Also, IObjectPostProcessors are scoped per-container. This is only relevant if you are using container hierarchies. If you define a IObjectPostProcessor in one container, it will only do its stuff on the objects in that container. Objects that are defined in another container will not be postprocessed by IObjectPostProcessors in another container, even if both containers are part of the same hierarchy. The Spring.Objects.Factory.Config.IObjectPostProcessor interface, which consists of two callback methods shown below.
object PostProcessBeforeInitialization(object instance, string name); object PostProcessAfterInitialization(object instance, string name);

When such a class is registered as a post-processor with the container, for each object instance that is created by the container,(see below for how this registration is effected), for each object instance that is created by the container, the post-processor will get a callback from the container both before any initialization methods (such as the AfterPropertiesSet method of the IInitializingObject interface and any declared init method) are called, and also afterwards. The post-processor is free to do what it wishes with the object, including ignoring the callback completely. An object post-processor will typically check for marker interfaces, or do something such as wrap an object with a proxy. Some Spring.NET AOP infrastructure classes are implemented as object postprocessors as they do this proxy-wrapping logic. Other extensions to the IObjectPostProcessors interface are IInstantiationAwareObjectPostProcessor and IDestructionAwareObjectPostProcessor defined below
public interface IInstantiationAwareObjectPostProcessor : IObjectPostProcessor { object PostProcessBeforeInstantiation(Type objectType, string objectName); bool PostProcessAfterInstantiation(object objectInstance, string objectName); IPropertyValues PostProcessPropertyValues(IPropertyValues pvs, PropertyInfo[] pis, object objectInstance, string objectName); } public interface IDestructionAwareObjectPostProcessor : IObjectPostProcessor { void PostProcessBeforeDestruction (object instance, string name); }

Spring Framework (Version 1.3.2)

62

The IoC container The PostProcessBeforeInstantiation callback method is called right before the container creates the object. If the object returned by this method is not null then the default instantiation behavior of the container is short circuited. The returned object is the one registered with the container and no other IObjectPostProcessor callbacks will be invoked on it. This mechanism is useful if you would like to expose a proxy to the object instead of the actual target object. The PostProcessAfterInstantiation callback method is called after the object has been instantiated but before Spring performs property population based on explicit properties or autowiring. A return value of false would short circuit the standard Spring based property population. The callback method PostProcessPropertyValues is called after Spring collects all the property values to apply to the object, but before they are applied. This gives you the opportunity to perform additional processing such as making sure that a property is set to a value if it contains a [Required] attribute or to perform attribute based wiring, i.e. adding the attribute [Inject("objectName")] on a property. Both of these features are scheduled to be included in Spring .12. The
IDestructionAwareObjectPostProcessor

PostProcessBeforeDestruction,

callback contains a single which is called before a singleton's destroy method is invoked.

method,

It is important to know that the IObjectFactory treats object post-processors slightly differently than the IApplicationContext. An IApplicationContext will automatically detect any objects which are deployed into it that implement the IObjectPostProcessor interface, and register them as post-processors, to be then called appropriately by the factory on object creation. Nothing else needs to be done other than deploying the postprocessor in a similar fashion to any other object. On the other hand, when using plain IObjectFactories, object post-processors have to manually be explicitly registered, with a code sequence such as...
ConfigurableObjectFactory factory = new .....; // create an IObjectFactory ... // now register some objects // now register any needed IObjectPostProcessors MyObjectPostProcessor pp = new MyObjectPostProcessor(); factory.AddObjectPostProcessor(pp); // now start using the factory ...

This explicit registration step is not convenient, and this is one of the reasons why the various IApplicationContext implementations are preferred above plain IObjectFactory implementations in the vast majority of Spring-backed applications, especially when using IObjectPostProcessors.

Note
IObjectPostProcessors and AOP auto-proxying Classes that implement the IObjectPostProcessor interface are special, and so they are treated differently by the container. All IObjectPostProcessors and their directly referenced object will be instantiated on startup, as part of the special startup phase of the IApplicationContext, then all those IObjectPostProcessors will be registered in a sorted fashion - and applied to all further objects. Since AOP auto-proxying is implemented as a IObjectPostProcessor itself, no IObjectPostProcessors or directly referenced objects are eligible for auto-proxying (and thus will not have aspects 'woven' into them). For any such object, you should see an info log message: Object 'foo' is not eligible for getting processed by all IObjectPostProcessors (for example: not eligible for auto-proxying). 5.9.1.1. Example: Hello World, IObjectPostProcessor-style This first example is hardly compelling, but serves to illustrate basic usage. All we are going to do is code a custom IObjectPostProcessor implementation that simply invokes the ToString() method of each object as it is

Spring Framework (Version 1.3.2)

63

The IoC container created by the container and prints the resulting string to the system console. Yes, it is not hugely useful, but serves to get the basic concepts across before we move into the second example which is actually useful. The basis of the example is the MovieFinder quickstart that is included with the Spring.NET distribution. Find below the custom IObjectPostProcessor implementation class definition
using System; using Spring.Objects.Factory.Config; namespace Spring.IocQuickStart.MovieFinder { public class TracingObjectPostProcessor : IObjectPostProcessor { public object PostProcessBeforeInitialization(object instance, string name) { return instance; } public object PostProcessAfterInitialization(object instance, string name) { Console.WriteLine("Object '" + name + "' created : " + instance.ToString()); return instance; } } }

And the following configuration


<?xml version="1.0" encoding="utf-8" ?> <objects xmlns="http://www.springframework.net" > <description>An example that demonstrates simple IoC features.</description> <object id="MyMovieLister" type="Spring.IocQuickStart.MovieFinder.MovieLister, Spring.IocQuickStart.MovieFinder"> <property name="movieFinder" ref="MyMovieFinder"/> </object> <object id="MyMovieFinder" type="Spring.IocQuickStart.MovieFinder.SimpleMovieFinder, Spring.IocQuickStart.MovieFinder"/> <!-- when the above objects are instantiated, this custom IObjectPostProcessor implementation will output the fact to the system console --> <object type="Spring.IocQuickStart.MovieFinder.TracingObjectPostProcessor, Spring.IocQuickStart.MovieFinder"/> </objects>

Notice how the TracingObjectPostProcessor is simply defined; it doesn't even have a name, and because it is a object it can be dependency injected just like any other object. Find below a small driver script to exercise the above code and configuration;
IApplicationContext ctx = new XmlApplicationContext( "assembly://Spring.IocQuickStart.MovieFinder/Spring.IocQuickStart.MovieFinder/AppContext.xml"); MovieLister lister = (MovieLister) ctx.GetObject("MyMovieLister"); Movie[] movies = lister.MoviesDirectedBy("Roberto Benigni"); LOG.Debug("Searching for movie..."); foreach (Movie movie in movies) { LOG.Debug(string.Format("Movie Title = '{0}', Director = '{1}'.", movie.Title, movie.Director)); } LOG.Debug("MovieApp Done.");

The output of executing the above program will be:


INFO - Object 'Spring.IocQuickStart.MovieFinder.TracingObjectPostProcessor' is not eligible for being processed by all IObjectPostProcessors

Spring Framework (Version 1.3.2)

64

The IoC container


(for example: not eligible for auto-proxying). Object 'MyMovieFinder' created : Spring.IocQuickStart.MovieFinder.SimpleMovieFinder Object 'MyMovieLister' created : Spring.IocQuickStart.MovieFinder.MovieLister DEBUG - Searching for movie... DEBUG - Movie Title = 'La vita e bella', Director = 'Roberto Benigni'. DEBUG - MovieApp Done.

5.9.1.2. Example: the RequiredAttributeObjectPostProcessor Using callback interfaces or annotations in conjunction with a custom IObjectPostProcessor implementation is a common means of extending the Spring IoC container. The [Required] attribute in the Spring.Objects.Factory.Attributes namespace can be used to mark a property as being 'required-to-be-set' (i.e. an setter property with this attribute applied must be configured to be dependency injected with a value), else an ObjectInitializationException will be thrown by the container at runtime. The best way to illustrate the usage of this attribute is with an example.
public class MovieLister { // the MovieLister has a dependency on the MovieFinder private IMovieFinder _movieFinder; // a setter property so that the Spring container can 'inject' a MovieFinder [Required] public IMovieFinder MovieFinder { set { _movieFinder = value; } } // business logic that actually 'uses' the injected MovieFinder is omitted... }

Hopefully the above class definition reads easy on the eye. Any and all IObjectDefinitions for the MovieLister class must be provided with a value. Let's look at an example of some XML configuraiton that will not pass validation.
<object id="MyMovieLister" type="Spring.IocQuickStart.MovieFinder.MovieLister, Spring.IocQuickStart.MovieFinder"> <!-- whoops, no MovieFinder is set (and this property is [Required]) --> </object>

At runtime the following message will be generated by the Spring container


Error creating context 'spring.root': Property 'MovieFinder' required for object 'MyMovieLister'

There is one last little piece of Spring configuration that is required to actually 'switch on' this behavior. Simply annotating the 'setter' properties of your classes is not enough to get this behavior. You need to enable a component that is aware of the [Required] attribute and that can process it appropriately. This component is the RequiredAttributeObjectPostProcessor class. This is a special IObjectPostProcessor implementation that is [Required]-aware and actually provides the 'blow up if this required property has not been set' logic. It is very easy to configure; simply drop the following object definition into your Spring XML configuration.
<object type="Spring.Objects.Factory.Attributes.RequiredAttributeObjectPostProcessor, Spring.Core"/>

Finally, one can configure an instance of the RequiredAttributeObjectPostProcessor class to look for another Attribute type. This is great if you already have your own [Required]-style attribute. Simply plug it into the definition of a RequiredAttributeObjectPostProcessor and you are good to go. By way of an example,

Spring Framework (Version 1.3.2)

65

The IoC container let's suppose you (or your organization / team) have defined an attribute called [Mandatory]. You can make a RequiredAttributeObjectPostProcessor instance [Mandatory]-aware like so:
<object type="Spring.Objects.Factory.Attributes.RequiredAttributeObjectPostProcessor, Spring.Core"> <property name="RequiredAttributeType" value="MyApp.Attributes.MandatoryAttribute, MyApp"/> </object>

5.9.2. Customizing configuration metadata with ObjectFactoryPostProcessors


The will look at is the Spring.Objects.Factory.Config.IObjectFactoryPostProcessor. The semantics of this interface are similar to the IObjectPostProcessor, with one major difference. IObjectFactoryPostProcessors operate on; that is to say, the Spring IoC container will allow IObjectFactoryPostProcessors to read the configuration metadata and potentially change it before the container has actually instantiated any other objects. By implementing this interface, you will receive a callback after the all the object definitions have been loaded into the IoC container but before they have been instantiated. The signature of the interface is shown below
public interface IObjectFactoryPostProcessor { void PostProcessObjectFactory (IConfigurableListableObjectFactory factory); }

next

extension

point

that

we

You can configure multiple IObjectFactoryPostProcessors if you wish. You can control the order in which these IObjectFactoryPostProcessors execute by setting the 'Order' property (you can only set this property if the IObjectFactoryPostProcessors implements the IOrdered interface; if you write your own IObjectFactoryPostProcessors you should consider implementing the IOrdered interface too); consult the SDK docs for the IObjectFactoryPostProcessors and IOrdered interfaces for more details.

Note
If you want to change the actual object instances (the objects that are created from the configuration metadata), then you rather need to use a IObjectObjectPostProcessor (described above in the section entitled Customizing objects with IObjectPostProcessors. Also, IObjectFactoryPostProcessors are scoped per-container. This is only relevant if you are using container hierarchies. If you define a IObjectFactoryPostProcessors in one container, it will only do its stuff on the object definitions in that container. Object definitions in another container will not be post-processed by IObjectFactoryPostProcessors in another container, even if both containers are part of the same hierarchy. An object factory post-processor is executed manually (in the case of a IObjectFactory) or automatically (in the case of an IApplicationContext) to apply changes of some sort to the configuration metadata that defines a container. Spring.NET includes a number of pre-existing object factory post-processors, such as PropertyResourceConfigurer and PropertyPlaceHolderConfigurer, both described below and ObjectNameAutoProxyCreator, which is very useful for wrapping other objects transactionally or with any other kind of proxy, as described later in this manual. In an IObjectFactory, the process of applying an IObjectFactoryPostProcessor is manual, and will be similar to this:
XmlObjectFactory factory = new XmlObjectFactory(new FileSystemResource("objects.xml")); // create placeholderconfigurer to bring in some property // values from a Properties file

Spring Framework (Version 1.3.2)

66

The IoC container


PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer(); cfg.setLocation(new FileSystemResource("ado.properties")); // now actually do the replacement cfg.PostProcessObjectFactory(factory);

This explicit registration step is not convenient, and this is one of the reasons why the various IApplicationContext implementations are preferred above plain IObjectFactory implementations in the vast majority of Spring-backed applications, especially when using IObjectFactoryPostProcessors. An IApplicationContext will detect any objects which are deployed into it that implement the ObjectFactoryPostProcessor interface, and automatically use them as object factory post-processors, at the appropriate time. Nothing else needs to be done other than deploying these post-processor in a similar fashion to any other object.

Note
Just as in the case of IObjectPostProcessors, you typically don't want to have IObjectFactoryPostProcessors marked as being lazily-initialized. If they are marked as such, then the Spring container will never instantiate them, and thus they won't get a chance to apply their custom logic. If you are using the 'default-lazy-init' attribute on the declaration of your <objects/> element, be sure to mark your various IObjectFactoryPostProcessor object definitions with 'lazy-init="false"'. 5.9.2.1. Example: The PropertyPlaceholderConfigurer The PropertyPlaceholderConfigurer is an excellent solution when you want to externalize a few properties from a file containing object definitions. This is useful to allow the person deploying an application to customize environment specific properties (for example database configuration strings, usernames, and passwords), without the complexity or risk of modifying the main XML definition file or files for the container. Variable substitution is performed on simple property values, lists, dictionaries, sets, constructor values, object type name, and object names in runtime object references. Furthermore, placeholder values can also crossreference other placeholders. Note that IApplicationContexts are able to automatically recognize and apply objects deployed in them that implement the IObjectFactoryPostProcessor interface. This means that as described here, applying a PropertyPlaceholderConfigurer is much more convenient when using an IApplicationContext. For this reason, it is recommended that users wishing to use this or other object factory postprocessors use an IApplicationContext instead of an IObjectFactory. In the example below a data access object needs to be configured with a database connection and also a value for the maximum number of results to return in a query. Instead of hard coding the values into the main Spring.NET configuration file we use place holders, in the NAnt style of ${variableName}, and obtain their values from NameValueSections in the standard .NET application configuration file. The Spring.NET configuration file looks like:
<configuration> <configSections> <sectionGroup name="spring"> <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/> </sectionGroup> <section name="DaoConfiguration" type="System.Configuration.NameValueSectionHandler"/> <section name="DatabaseConfiguration" type="System.Configuration.NameValueSectionHandler"/> </configSections> <DaoConfiguration>

Spring Framework (Version 1.3.2)

67

The IoC container


<add key="maxResults" value="1000"/> </DaoConfiguration> <DatabaseConfiguration> <add key="connection.string" value="dsn=MyDSN;uid=sa;pwd=myPassword;"/> </DatabaseConfiguration> <spring> <context> <resource uri="assembly://DaoApp/DaoApp/objects.xml"/> </context> </spring> </configuration>

Notice the presence of two NameValueSections in the configuration file. These name value pairs will be referred to in the Spring.NET configuration file. In this example we are using an embedded assembly resource for the location of the Spring.NET configuration file so as to reduce the chance of accidental tampering in deployment. This Spring.NET configuration file is shown below.
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd" > <object name="productDao" type="DaoApp.SimpleProductDao, DaoApp "> <property name="maxResults" value="${maxResults}"/> <property name="dbConnection" ref="myConnection"/> </object> <object name="myConnection" type="System.Data.Odbc.OdbcConnection, System.Data"> <property name="connectionstring" value="${connection.string}"/> </object> <object name="appConfigPropertyHolder" type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer, Spring.Core"> <property name="configSections"> <value>DaoConfiguration,DatabaseConfiguration</value> </property> </object> </objects>

The values of ${maxResults} and ${connection.string} match the key names used in the two NameValueSectionHandlers DaoConfiguration and DatabaseConfiguration. The PropertyPlaceholderConfigurer refers to these two sections via a comma delimited list of section names in the configSections property. If you are using section groups, prefix the section group name, for example myConfigSection/DaoConfiguraiton. The PropertyPlaceholderConfigurer class also supports retrieving name value pairs from other IResource locations. These can be specified using the Location and Locations properties of the PropertyPlaceHolderConfigurer class. If there are properties with the same name in different resource locations the default behavior is that the last property processed overrides the previous values. This is behavior is controlled by the LastLocationOverrides property. True enables overriding while false will append the values as one would normally expect using NameValueCollection.Add.

Note
In an ASP.NET environment you must specify the full, four-part name of the assembly when using a NameValueFileSectionHandler

Spring Framework (Version 1.3.2)

68

The IoC container

<section name="hibernateConfiguration" type="System.Configuration.NameValueFileSectionHandler, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>

5.9.2.1.1. Type, Ref, and Expression substitution


The PropertyPlaceholderConfigurer can be used to substitute type names, which is sometimes useful when you have to pick a particular implementation class at runtime. For example:
<object id="MyMovieFinder" type="${custom.moviefinder.type}"/>

If the class is unable to be resolved at runtime to a valid type, resolution of the object will fail once it is about to be created (which is during the PreInstantiateSingletons() phase of an ApplicationContext for a non-lazy-init object.) Similarly you can replace 'ref' and 'expression' metadata, as shown below
<object id="TestObject" type="Simple.TestObject, MyAssembly"> <property name="age" expression="${ageExpression}"/> <property name="spouse" ref="${spouse-ref}"/> </object>

5.9.2.1.2. Replacement with Environment Variables


You may also use the value environment variables to replace property placeholders. The use of environment variables is controlled via the property EnvironmentVariableMode. This property is an enumeration of the type EnvironmentVariablesMode and has three values, Never, Fallback, and Override. Fallback is the default value and will resolve a property placeholder if it was not already done so via a value from a resource location. Override will apply environment variables before applying values defined from a resource location. Never will, quite appropriately, disable environment variable substitution. An example of how the PropertyPlaceholderConfigurer XML is modified to enable override usage is shown below
<object name="appConfigPropertyHolder" type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer, Spring.Core"> <property name="configSections" value="DaoConfiguration,DatabaseConfiguration"/> <property name="EnvironmentVariableMode" value="Override"/> </object> </objects>

5.9.2.2. Example: The PropertyOverrideConfigurer The another object factory post-processor, is similar to the PropertyPlaceholderConfigurer, but in contrast to the latter, the original definitions can have default values or no values at all for object properties. If an overriding configuration file does not have an entry for a certain object property, the default context definition is used. Note that the object factory definition is not aware of being overridden, so it is not immediately obvious when looking at the XML definition file that the override configurer is being used. In case that there are multiple PropertyOverrideConfigurer instances that define different values for the same object property, the last one will win (due to the overriding mechanism). The example usage is similar to when using PropertyPlaceHolderConfigurer except that the key name refers to the name given to the object in the Spring.NET configuration file and is suffixed via 'dot' notation with the name of the property For example, if the application configuration file is
<configuration>

PropertyOverrideConfigurer,

Spring Framework (Version 1.3.2)

69

The IoC container


<configSections> <sectionGroup name="spring"> <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/> </sectionGroup> <section name="DaoConfigurationOverride" type="System.Configuration.NameValueSectionHandler"/> </configSections> <DaoConfigurationOverride> <add key="productDao.maxResults" value="1000"/> </DaoConfigurationOverride> <spring> <context> <resource uri="assembly://DaoApp/DaoApp/objects.xml"/> </context> </spring> </configuration>

Then the value of 1000 will be used to overlay the value of 2000 set in the Spring.NET configuration file shown below
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/springobjects.xsd" > <object name="productDao" type="PropPlayApp.SimpleProductDao, PropPlayApp " > <property name="maxResults" value="2000"/> <property name="dbConnection" ref="myConnection"/> <property name="log" ref="daoLog"/> </object> <object name="daoLog" type="Spring.Objects.Factory.Config.LogFactoryObject, Spring.Core"> <property name="logName" value="DAOLogger"/> </object> <object name="myConnection" type="System.Data.Odbc.OdbcConnection, System.Data"> <property name="connectionstring"> <value>dsn=MyDSN;uid=sa;pwd=myPassword;</value> </property> </object> <object name="appConfigPropertyOverride" type="Spring.Objects.Factory.Config.PropertyOverrideConfigurer, Spring.Core"> <property name="configSections"> <value>DaoConfigurationOverride</value> </property> </object> </objects>

5.9.2.3. IVariableSource The IVariableSource is the base interface for providing the ability to get the value of property placeholders (namevalue) pairs from a variety of sources. Out of the box, Spring.NET supports a number of variable sources that allow users to obtain variable values from .NET config files, java-style property files, environment variables, command line arguments and the registry and the new connection strings configuration section in .NET 2.0. The list of implementing classes is listed below. Please refer to the SDK documentation for more information. ConfigSectionVariableSource PropertyFileVariableSource EnvironmentVariableSource CommandLineArgsVariableSource

Spring Framework (Version 1.3.2)

70

The IoC container RegistryVariableSource SpecialFolderVariableSource ConnectionStringsVariableSource ConfigurableVariableSource You use this by defining an instance of Spring.Objects.Factory.Config.VariablePlaceholderConfigurer in your configuration and set the property VariableSource to a single IVariableSource instance or the list property VariableSources to a list of IVariableSource instances. In the case of the same property defined in multiple IVariableSource implementations, the first one in the list that contains the property value will be used.
<object type="Spring.Objects.Factory.Config.VariablePlaceholderConfigurer, Spring.Core"> <property name="VariableSources"> <list> <object type="Spring.Objects.Factory.Config.PropertyFileVariableSource, Spring.Core"> <property name="Location" value="~\application.properties" /> <property name="IgnoreMissingResources" value="true"/> </object> <object type="Spring.Objects.Factory.Config.ConfigSectionVariableSource, Spring.Core"> <property name="SectionNames" value="CryptedConfiguration" /> </object> </list> </property> </object>

Note
The use of the IgnoreMissingResources property above will mean that if the property file is not found it will be silently ignored and the resolution will continue to ConfigSectionVariableSource. The IVariableSource interface is shown below
public interface IVariableSource { string ResolveVariable(string name); }

This is a simple contract to implement if you should decide to create your own custom implemention. Look at the source code of the current implementations for some inspiration if you go that route. To register your own custom implemenation, simply configure VariablePlaceholderConfigurer to refer to your class.

5.9.3. Customizing instantiation logic using IFactoryObjects


The Spring.Objects.Factory.IFactoryObject interface is to be implemented by objects that are themselves factories. The IFactoryObject interface is a point of pluggability into the Spring IoC containers instantiation logic. If you have some complex initialization code that is better expressed in C# as opposed to a (potentially) verbose amount of XML, you can create your own IFactoryObject, write the complex initialization inside that class, and then plug your custom IFactoryObject into the container. The IFactoryObject interface provides one method and two (read-only) properties: object GetObject(): has to return an instance of the object this factory creates. The instance can possibly be shared (depending on whether this factory provides singletons or prototypes).

Spring Framework (Version 1.3.2)

71

The IoC container bool IsSingleton: has to return true if this IFactoryObject returns singletons, false otherwise. Type ObjectType: has to return either the object type returned by the GetObject() method or null if the type isn't known in advance.
IFactoryObject

The IFactoryObject concept and interface is used in a number of places within the Spring Framework. Some examples of its use is described in Section 5.3.9, Setting a reference using the members of other objects and classes. for the PropertyRetrievingFactoryObject and FieldRetrievingFactoryObject. An additional use of creating an custom IFactoryObject implementation is to retrieve an object from an embedded resource file and use it to set another objects dependency. An example of this is provided here [http://jira.springframework.org/ browse/SPRNET-133#action_19743]. Finally, there is sometimes a need to ask a container for an actual IFactoryObject instance itself, not the object it produces. This may be achieved by prepending the object id with '&' (sans quotes) when calling the GetObject method of the IObjectFactory (including IApplicationContext). So for a given IFactoryObject with an id of 'myObject', invoking GetObject("myObject") on the container will return the product of the IFactoryObject, but invoking GetObject("&myObject") will return the IFactoryObject instance itself. 5.9.3.1. IConfigurableFactoryObject The Spring.Objects.Factory.IConfigurableFactoryObject interface inherits from IFactoryObject interface and adds the following property. IObjectDefinition ProductTemplate : Gets the template object definition that should be used to configure the instance of the object managed by this factory.
IConfigurableFactoryObject WebServiceProxyFactory.

implementions you already have examples of in Section 29.3, Client-side are

5.10. The IApplicationContext


While the Spring.Objects namespace provides basic functionality for managing and manipulating objects, often in a programmatic way, the Spring.Context namespace introduces the IApplicationContext interface, which enhances the functionality provided by the IObjectFactory interface in a more framework-oriented style. Many users will use ApplicationContext in a completely declarative fashion, not even having to create it manually, but instead relying on support classes such as the .NET configuration section handlers such as ContextHandler and WebContextHandler together to declaratively define the ApplicationContext and retrieve it though a ContextRegistry. (Of course it is still possible to create an IApplicationContext Programatically). The basis for the context module is the IApplicationContext interface, located in the Spring.Context namespace. Deriving from the IObjectFactory interface, it provides all the functionality of the IObjectFactory. To be able to work in a more framework-oriented fashion, using layering and hierarchical contexts, the Spring.Context namespace also provides the following functionality Loading of multiple (hierarchical) contexts, allowing some of them to be focused and used on one particular layer, for example the web layer of an application. Access to localized resources at the application level by implementing IMessageSource. Uniform access to resources that can be read in as an InputStream, such as URLs and files by implementing
IResourceLoader

Loosely Coupled Event Propagation. Publishers and subscribers of events do not have to be directly aware of each other as they register their interest indirectly through the application context.

Spring Framework (Version 1.3.2)

72

The IoC container

5.10.1. IObjectFactory or IApplicationContext?


Short version: use an IApplicationContext unless you have a really good reason for not doing so. For those of you that are looking for slightly more depth as to the 'but why' of the above recommendation, keep reading. As the IApplicationContext includes all the functionality the object factory via its inheritance of the IObjectFactory interface, it is generally recommended to be used over the IObjectFactory except for a few limited situations where memory consumption might be critical. This may become more important if the .NET Compact Framework is supported. The history of IObjectFactory comes from the Spring Java framework, where the use of Spring in Applets was a concern to reduce memory consumption. However, for most 'typical' enterprise applications and systems, the IApplicationContext is what you will want to use. Spring generally makes heavy use of the IObjectPostProcessor extension point (to effect proxying and suchlike), and if you are using just a plain IObjectFactory then a fair amount of support such as transactions and AOP will not take effect (at least not without some extra steps on your part), which could be confusing because nothing will actually be wrong with the configuration. Find below a feature matrix that lists what features are provided by the IObjectFactory and IApplicationContext interfaces (and attendant implementations). The following sections describe functionality that IApplicationContext adds to the basic IObjectFactory capabilities in a lot more depth than the said feature matrix.)

Table 5.7. Feature Matrix Feature Object instantiation/wiring Automatic IObjectPostProcessor registration Automatic
IObjectFactoryPostProcessor IObjectFactory IApplicationContext

Yes No

Yes Yes

No

Yes

registration Convenient IMessageSource access


ApplicationEvent

No

Yes

publication

No No

Yes Yes

Singleton service locator style access Declarative registration of custom resource protocol handler, XML Parsers for object definitions, and type aliases

No

Yes

5.11. Configuration of IApplicationContext


Well known locations in the .NET application configuration file are used to register resource handlers, custom parsers, type alias, and custom type converts in addition to the context and objects sections mentioned previously. A sample .NET application configuration file showing all these features is shown below. Each section requires

Spring Framework (Version 1.3.2)

73

The IoC container the use of a custom configuration section handler. Note that the types shown for resource handlers and parsers are fictional.
<configuration> <configSections> <sectionGroup name="spring"> <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/> <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /> <section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core"/> <section name="resourceHandlers" type="Spring.Context.Support.ResourceHandlersSectionHandler, Spring.Core"/> <section name="typeAliases" type="Spring.Context.Support.TypeAliasesSectionHandler, Spring.Core"/> <section name="typeConverters" type="Spring.Context.Support.TypeConvertersSectionHandler, Spring.Core"/> </sectionGroup> </configSections> <spring> <parsers> <parser type="Spring.Aop.Config.AopNamespaceParser, Spring.Aop" /> <parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" /> </parsers> <resourceHandlers> <handler protocol="db" type="MyCompany.MyApp.Resources.MyDbResource"/> </resourceHandlers> <context caseSensitive="false"> <resource uri="config://spring/objects"/> <resource uri="db://user:pass@dbName/MyDefinitionsTable"/> </context> <typeAliases> <alias name="WebServiceExporter" type="Spring.Web.Services.WebServiceExporter, Spring.Web"/> <alias name="DefaultPointcutAdvisor" type="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop"/> <alias name="AttributePointcut" type="Spring.Aop.Support.AttributeMatchMethodPointcut, Spring.Aop"/> <alias name="CacheAttribute" type="Spring.Attributes.CacheAttribute, Spring.Core"/> <alias name="MyType" type="MyCompany.MyProject.MyNamespace.MyType, MyAssembly"/> </typeAliases> <typeConverters> <converter for="Spring.Expressions.IExpression, Spring.Core" type="Spring.Objects.TypeConverters.ExpressionConverter, Spring.Core"/> <converter for="MyTypeAlias" type="MyCompany.MyProject.Converters.MyTypeConverter, MyAssembly"/> </typeConverters> <objects xmlns="http://www.springframework.net"> ... </objects> </spring> </configuration>

The new sections are described below. The attribute caseSensitive allows the for both IObjectFactory and IApplicationContext implementations to not pay attention to the case of the object names. This is important in web applications so that ASP.NET pages can be resolved in a case independent manner. The default value is true.

5.11.1. Registering custom parsers


Instead of using the default XML schema that is generic in nature to define an object's properties and dependencies, you can create your own XML schema specific to an application domain. This has the benefit of being easier to type and getting XML intellisense for the schema being used. The downside is that you need to write code that will transform this XML into Spring object definitions. One would typically implement a custom parser by deriving from the class ObjectsNamespaceParser and overriding the methods int ParseRootElement(XmlElement

Spring Framework (Version 1.3.2)

74

The IoC container and int ParseElement(XmlElement element, XmlResourceReader reader). Registering custom parsers outside of App.config will be addressed in a future release.
root, XmlResourceReader reader)

To

section handler of the type Spring.Context.Support.NamespaceParsersSectionHandler in the configSecitons section of App.config. The parser configuration section contains one or more <parser> elements each with a type attribute. Below is an example that registers all the namespaces provided in Spring.

register

custom

parser

register

Note
As of Spring.NET 1.2.0 it is no longer necessary to explicitly configure the namespace parsers that come with Spring via a custom section in App.config. You will still need to register custom namespace parsers if you are writing your own.
<configuration> <configSections> <sectionGroup name="spring"> <!-- other configuration section handler defined here --> <section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core"/> </sectionGroup> </configSections> <spring> <parsers> <parser type="Spring.Aop.Config.AopNamespaceParser, Spring.Aop" /> <parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" /> <parser type="Spring.Transaction.Config.TxNamespaceParser, Spring.Data" /> <parser type="Spring.Validation.Config.ValidationNamespaceParser, Spring.Core" /> <parser type="Spring.Remoting.Config.RemotingNamespaceParser, Spring.Services" /> </parsers> </spring> </configuration>

You can also register custom parser programmatically using the NamespaceParserRegistry. Here is an example taken from the code used in the Transactions Quickstart application.
NamespaceParserRegistry.RegisterParser(typeof(DatabaseNamespaceParser)); NamespaceParserRegistry.RegisterParser(typeof(TxNamespaceParser)); NamespaceParserRegistry.RegisterParser(typeof(AopNamespaceParser)); IApplicationContext context = new XmlApplicationContext("assembly://Spring.TxQuickStart.Tests/Spring.TxQuickStart/system-test-localconfig.xml");

5.11.2. Registering custom resource handlers


Creating a custom resource handler means implementing the IResource interface. The base class AbstractResource is a useful starting point. Look at the Spring source for classes such as FileSystemResource or AssemblyResource for implementation tips. You can register your custom resource handler either within App.config, as shown in the program listing at the start of this section using a .ResourceHandlersSectionHandler or define an object of the type Spring.Objects.Factory.Config.ResourceHandlerConfigurer as you would any other Spring managed object. An example of the latter is shown below:
<object id="myResourceHandlers" type="Spring.Objects.Factory.Config.ResourceHandlerConfigurer, Spring.Core"> <property name="ResourceHandlers"> <dictionary> <entry key="db" value="MyCompany.MyApp.Resources.MyDbResource, MyAssembly"/> </dictionary> </property> </object>

Spring Framework (Version 1.3.2)

75

The IoC container

5.11.3. Registering Type Aliases


Type aliases allow you to simplify Spring configuration file by replacing fully qualified type name with an alias for frequently used types. Aliases can be registered both within a config file and programatically and can be used anywhere in the context config file where a fully qualified type name is expected. Type aliases can also be defined for generic types. One way to configure a type alias is to define them in a custom config section in the Web/App.config file for your application, as well as the custom configuration section handler. See the previous XML configuration listing for an example that makes an alias for the WebServiceExporter type. Once you have aliases defined, you can simply use them anywhere where you would normally specify a fully qualified type name:
<object id="MyWebService" type="WebServiceExporter"> ... </object> <object id="cacheAspect" type="DefaultPointcutAdvisor"> <property name="Pointcut"> <object type="AttributePointcut"> <property name="Attribute" value="CacheAttribute"/> </object> </property> <property name="Advice" ref="aspNetCacheAdvice"/> </object>

To

a section handler of the type in the configSecitons section of App.config. The type alias configuration section contains one or more <alias> elements each with a name and a type attribute. Below is an example that registers the alias for WebServiceExporter
Spring.Context.Support.TypeAliasesSectionHandler
<configuration> <configSections> <sectionGroup name="spring"> <!-- other configuration section handler defined here --> <section name="typeAliases" type="Spring.Context.Support.TypeAliasesSectionHandler, Spring.Core"/> </sectionGroup> </configSections> <spring> <typeAliases> <alias name="WebServiceExporter" type="Spring.Web.Services.WebServiceExporter, Spring.Web"/> </typeAliases> </spring> </configuration>

register

type

alias

register

For an example showing type aliases for generic types see Section 5.2.6, Object creation of generic types. Another way is to define an object of the type Spring.Objects.Factory.Config.TypeAliasConfigurer within the regular <objects> section of any standard Spring configuration file. This approach allows for more modularity in defining type aliases, for example if you can't access App.config/Web.config. An example of registration using a TypeAliasConfigurer is shown below
<object id="myTypeAlias" type="Spring.Objects.Factory.Config.TypeAliasConfigurer, Spring.Core"> <property name="TypeAliases"> <dictionary> <entry key="WebServiceExporter" value="Spring.Web.Services.WebServiceExporter, Spring.Web"/> <entry key="DefaultPointcutAdvisor" value="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop"/> <entry key="MyType" value="MyCompany.MyProject.MyNamespace.MyType, MyAssembly"/> </dictionary> </property>

Spring Framework (Version 1.3.2)

76

The IoC container


</object>

5.11.4. Registering Type Converters


The standard .NET mechanism for specifying a type converter is to add a TypeConverter attribute to a type definition to specify the type of the Converter. This is the preferred way of defining type converters if you control the source code for the type that you want to define a converter for. However, this configuration section allows you to specify converters for the types that you don't control, and it also allows you to override some of the standard type converters, such as the ones that are defined for some of the types in the .NET Base Class Library. You can specify the type converters in App.config by using Spring.Context.Support.TypeConvertersSectionHandler as shown before or define an object of the type Spring.Objects.Factory.Config.CustomConverterConfigurer. An example of registration using a CustomConverterConfigurer is shown below
<object id="myTypeConverters" type="Spring.Objects.Factory.Config.CustomConverterConfigurer, Spring.Core"> <property name="CustomConverters"> <dictionary> <entry key="System.Date" value="MyCompany.MyProject.MyNamespace.MyCustomDateConverter, MyAssembly"/> </dictionary> </property> </object>

5.12. Added functionality of the IApplicationContext


As already stated in the previous section, the IApplicationContext has a couple of features that distinguish it from the IObjectFactory. Let us review them one-by-one.

5.12.1. Context Hierarchies


You can structure the configuration information of application context into hierarchies that naturally reflect the internal layering of your application. As an example, abstract object definitions may appear in a parent application context configuration file, possibly as an embedded assembly resource so as not to invite accidental changes.
<spring> <context> <resource uri="assembly://MyAssembly/MyProject/root-objects.xml"/> <context name="mySubContext"> <resource uri="file://objects.xml"/> </context> </context> </spring>

The nesting of context elements reflects the parent-child hierarchy you are creating. The nesting can be to any level though it is unlikely one would need a deep application hierarchy. The xml file must contain the <objects> as the root name. Another example of a hierarchy, but using sections in the application configuration file is shown below.
<configSections> <sectionGroup name="spring"> <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/> <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /> <sectionGroup name="child"> <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /> </sectionGroup> </sectionGroup> </configSections> <spring>

Spring Framework (Version 1.3.2)

77

The IoC container

<context name="ParentContext"> <resource uri="config://spring/objects"/> <context name="ChildContext"> <resource uri="config://spring/child/objects"/> </context> </context> <objects xmlns="http://www.springframework.net"> ... </objects> <child> <objects xmlns="http://www.springframework.net"> ... </objects> </child> </spring>

As

the context tag is optional and defaults to Spring.Context.Support.XmlApplicationContext. The name of the context can be used in conjunction with the service locator class, ContextRegistry, discussed in Section 5.15, Service Locator access
type

reminder,

the

attribute

of

5.12.2. Using IMessageSource


The IApplicationContext interface extends an interface called IMessageSource and provides localization (i18n or internationalization) services for text messages and other resource data types such as images. This functionality makes it easier to use .NET's localization features at an application level and also offers some performance enhancements due to caching of retrieved resources. Together with the NestingMessageSource, capable of hierarchical message resolving, these are the basic interfaces Spring.NET provides for localization. Let's quickly review the methods defined there: string GetMessage(string name): retrieves a message from the IMessageSource and using CurrentUICulture. string GetMessage(string name, CultureInfo cultureInfo): retrieves a message from the IMessageSource using a specified culture. string GetMessage(string name, params object[] args): retrieves a message from the IMessageSource using a variable list of arguments as replacement values in the message. The CurrentUICulture is used to resolve the message. string GetMessage(string name, CultureInfo cultureInfo, params object[] args): retrieves a message from the IMessageSource using a variable list of arguments as replacement values in the message. The specified culture is used to resolve the message. string GetMessage(string name, string defaultMessage, CultureInfo culture, params object[] arguments): retrieves a message from the IMessageSource using a variable list of arguments as replacement values in the message. The specified culture is used to resolve the message. If no message can be resolved, the default message is used. string GetMessage(IMessageSourceResolvable resolvable, CultureInfo culture) : all properties used in the methods above are also wrapped in a class - the MessageSourceResolvable, which you can use in this method. object GetResourceObject(string name):Get a localized resource object, i.e. Icon, Image, etc. given the resource name. The CurrentUICulture is used to resolve the resource object. object GetResourceObject(string name, CultureInfo cultureInfo):Get a localized resource object, i.e. Icon, Image, etc. given the resource name. The specified culture is used to resolve the resource object.

Spring Framework (Version 1.3.2)

78

The IoC container void ApplyResources(object value, string objectName, CultureInfo cultureInfo): Uses a ComponentResourceManager to apply resources to all object properties that have a matching key name. Resource key names are of the form objectName.propertyName When an IApplicationContext gets loaded, it automatically searches for an IMessageSource object defined in the context. The object has to have the name messageSource. If such an object is found, all calls to the methods described above will be delegated to the message source that was found. If no message source was found, the IApplicationContext checks to see if it has a parent containing a similar object, with a similar name. If so, it uses that object as the IMessageSource. If it can't find any source for messages, an empty StaticMessageSource will be instantiated in order to be able to accept calls to the methods defined above.

Fallback behavior
The fallback rules for localized resources seem to have a bug that is fixed by applying Service Pack 1 for .NET 1.1. This affects the use of IMessageSource.GetMessage methods that specify CultureInfo. The core of the issue in the .NET BCL is the method ResourceManager.GetObject that accepts CultureInfo. Spring.NET provides two IMessageSource implementations. These are ResourceSetMessageSource and StaticMessageSource. Both implement IHierarchicalMessageSource to resolve messages hierarchically. The StaticMessageSource is hardly ever used but provides programmatic ways to add messages to the source. The ResourceSetMessageSource is more interesting and an example is provided for in the distribution and discussed more extensively in the Chapter 37, IoC Quickstarts section. The ResourceSetMessageSource is configured by providing a list of ResourceManagers. When a message code is to be resolved, the list of ResourceManagers is searched to resolve the code. For each ResourceManager a ResourceSet is retrieved and asked to resolve the code. Note that this search does not replace the standard hub-and-spoke search for localized resources. The ResourceManagers list specifies the multiple 'hubs' where the standard search starts.
<object name="messageSource" type="Spring.Context.Support.ResourceSetMessageSource, Spring.Core"> <property name="resourceManagers"> <list> <value>Spring.Examples.AppContext.MyResource, Spring.Examples.AppContext</value> </list> </property> </object>

You can specify the arguments to construct a ResourceManager as a two part string value containing the base name of the resource and the assembly name. This will be converted to a ResourceManager via the ResourceManagerConverter TypeConverter. This converter can be similarly used to set a property on any object that is of the type ResourceManager. You may also specify an instance of the ResourceManager to use via an object reference. The convenience class Spring.Objects.Factory.Config.ResourceManagerFactoryObject can be used to conveniently create an instance of a ResourceManager.
<object name="myResourceManager" type="Spring.Objects.Factory.Config.ResourceManagerFactoryObject, Spring.Core"> <property name="baseName"> <value>Spring.Examples.AppContext.MyResource</value> </property> <property name="assemblyName"> <value>Spring.Examples.AppContext</value> </property> </object>

In application code, a call to GetMessage will retrieve a properly localized message string based on a code value. Any arguments present in the retrieved string are replaced using String.Format semantics. The ResourceManagers, ResourceSets and retrieved strings are cached to provide quicker lookup performance. The

Spring Framework (Version 1.3.2)

79

The IoC container key 'HelloMessage' is contained in the resource file with a value of Hello {0} {1}. The following call on the application context will return the string Hello Mr. Anderson. Note that the caching of ResourceSets is via the concatenation of the ResourceManager base name and the CultureInfo string. This combination must be unique.
string msg = ctx.GetMessage("HelloMessage", new object[] {"Mr.", "Anderson"}, CultureInfo.CurrentCulture );

It is possible to chain the resolution of messages by passing arguments that are themselves messages to be resolved giving you greater flexibility in how you can structure your message resolution. This is achieved by passing as an argument a class that implements IMessageResolvable instead of a string literal. The convenience class DefaultMessageResolvable is available for this purpose. As an example if the resource file contains a key name error.required that has the value '{0} is required {1}' and another key name field.firstname with the value 'First name'. The following code will create the string 'First name is required dude!'
string[] codes = {"field.firstname"}; DefaultMessageResolvable dmr = new DefaultMessageResolvable(codes, null); ctx.GetMessage("error.required", new object[] { dmr, "dude!" }, CultureInfo.CurrentCulture ));

The examples directory in the distribution contains an example program, Spring.Examples.AppContext, that demonstrates usage of these features. The IMessageSourceAware interface can also be used to acquire a reference to any IMessageSource that has been defined. Any object that is defined in an IApplicationContext that implements the IMessageSourceAware interface will be injected with the application context's IMessageSource when it (the object) is being created and configured.

5.12.3. Using resources within Spring.NET


A lot of applications need to access resources. Resources here, might mean files, but also news feeds from the Internet or normal web pages. Spring.NET provides a clean and transparent way of accessing resources in a protocol independent way. The IApplicationContext has a method (GetResource(string)) to take care of this. Refer to Section 7.1, Introduction for more information on the string format to use and the IResource abstraction in general.

5.12.4. Loosely coupled events


The Eventing Registry allows developers to utilize a loosely coupled event wiring mechanism. By decoupling the event publication and the event subscription, most of the mundane event wiring is handled by the IoC container. Event publishers can publish their event to a central registry, either all of their events or a subset based on criteria such as delegate type, name, return value, etc... Event subscribers can choose to subscribe to any number of published events. Subscribers can subscriber to events based on the type of object exposing them, allowing one subscriber to handle all events of a certain type without regards to how many different instances of that type are created. The Spring.Objects.Events.IEventRegistry interface represents the central registry and defines publish and subscribe methods. void PublishEvents( object sourceObject ): publishes all events of the source object to subscribers that implement the correct handler methods. void Subscribe(object subscriber ): The subscriber receives all events from the source object for which it has matching handler methods.

Spring Framework (Version 1.3.2)

80

The IoC container void Subscribe(object subscriber, Type targetSourceType ): The subscriber receives all events from a source object of a particular type for which it has matching handler methods. void Unsubscribe(object subscriber ): Unsubscribe all events from the source object for which it has matching handler methods. void Unsubscribe(object subscriber, Type targetSourceType ): Unsubscribe all events from a source object of a particular type for which it has matching handler methods. IApplicationContext implements this interface and delegates the implementation to an instance of Spring.Objects.Events.Support.EventRegistry. You are free to create and use as many EventRegistries as you like but since it is common to use only one in an application, IApplicationContext provides convenient access to a single instance. Within the example/Spring/Spring.Examples.EventRegistry directory you will find an example on how to use this functionality. When you open up the project, the most interesting file is the EventRegistryApp.cs file. This application loads a set of object definitions from the application configuration file into an IApplicationContext instance. From there, three objects are loaded up: one publisher and two subscribers. The publisher publishes its events to the IApplicationContext instance:
// Create the Application context using configuration file IApplicationContext ctx = ContextRegistry.GetContext(); // Gets the publisher from the application context MyEventPublisher publisher = (MyEventPublisher)ctx.GetObject("MyEventPublisher"); // Publishes events to the context. ctx.PublishEvents( publisher );

One of the two subscribers subscribes to all events published to the IApplicationContext instance, using the publisher type as the filter criteria.
// Gets first instance of subscriber MyEventSubscriber subscriber = (MyEventSubscriber)ctx.GetObject("MyEventSubscriber"); // Gets second instance of subscriber MyEventSubscriber subscriber2 = (MyEventSubscriber)ctx.GetObject("MyEventSubscriber"); // Subscribes the first instance to the any events published by the type MyEventPublisher ctx.Subscribe( subscriber, typeof(MyEventPublisher) );

This will wire the first subscriber to the original event publisher. Anytime the event publisher fires an event, (publisher.ClientMethodThatTriggersEvent1();) the first subscriber will handle the event, but the second subscriber will not. This allows for selective subscription, regardless of the original prototype definition.

5.12.5. Event notification from IApplicationContext


Event handling in the IApplicationContext is provided through the IApplicationEventListener interface that contains the single method void HandleApplicationEvent( object source, ApplicationEventArgs applicationEventArgs ). Classes that implement the IApplicationEventListener interface are automatically registered as a listener with the IApplicationContext. Publishing an event is done via the context's PublishEvent( ApplicationEventArgs eventArgs ) method. This implementation is based on the traditional Observer design pattern. The event argument type, ApplicationEventArgs, adds the time of the event firing as a property. The derived class ContextEventArgs is used to notify observers on the lifecycle events of the application context. It contains a property ContextEvent Event that returns the enumeration Refreshed or Closed.. The Refreshed enumeration value indicated that the IApplicationContext was either initialized or refreshed. Initialized here means that all objects are loaded, singletons are pre-instantiated and the IApplicationContext is ready for

Spring Framework (Version 1.3.2)

81

The IoC container use. The Closed is published when the IApplicationContext is closed using the Dispose() method on the IConfigurableApplicationContext interface. Closed here means that singletons are destroyed. Implementing custom events can be done as well. Simply call the PublishEvent method on the IApplicationContext, specifying a parameter which is an instance of your custom event argument subclass. Let's have a look at an example. First, the IApplicationContext:
<object id="emailer" type="Example.EmailObject"> <property name="blackList"> <list> <value>[email protected]</value> <value>[email protected]</value> <value>[email protected]</value> </list> </property> </object> <object id="blackListListener" type="Example.BlackListNotifier"> <property name="notificationAddress"> <value>[email protected]</value> </property> </object>

and then, the actual objects:


public class EmailObject : IApplicationContextAware { // the blacklist private IList blackList; public IList BlackList { set { this.blackList = value; } } public IApplicationContext ApplicationContext { set { this.ctx = value; } } public void SendEmail(string address, string text) { if (blackList.contains(address)) { BlackListEvent evt = new BlackListEvent(address, text); ctx.publishEvent(evt); return; } // send email... } } public class BlackListNotifier : IApplicationEventListener { // notification address private string notificationAddress; public string NotificationAddress { set { this.notificationAddress = value; } } public void HandleApplicationEvent(ApplicationEvent evt) { if (evt instanceof BlackListEvent) { // notify appropriate person } } }

Spring Framework (Version 1.3.2)

82

The IoC container

5.13. Customized behavior in the ApplicationContext


The IObjectFactory already offers a number of mechanisms to control the lifecycle of objects deployed in it (such as marker interfaces like IInitializingObject and System.IDisposable, their configuration only equivalents such as init-method and destroy-method) attributes in an XmlObjectFactory configuration, and object post-processors. In an IApplicationContext, all of these still work, but additional mechanisms are added for customizing behavior of objects and the container.

5.13.1. The IApplicationContextAware marker interface


All marker interfaces available with ObjectFactories still work. The IApplicationContext does add one extra marker interface which objects may implement, IApplicationContextAware. An object which implements this interface and is deployed into the context will be called back on creation of the object, using the interface's ApplicationContext property, and provided with a reference to the context, which may be stored for later interaction with the context.

5.13.2. The IObjectPostProcessor


Object classes which implement the interface, have already been mentioned. It is worth mentioning again here though, that post-processors are much more convenient to use in IApplicationContexts than in plain IObjectFactory instances. In an IApplicationContext, any deployed object which implements the above marker interface is automatically detected and registered as an object post-processor, to be called appropriately at creation time for each object in the factory.
Spring.Objects.Factory.Config.IObjectPostProcessor

post-processors

are

5.13.3. The IObjectFactoryPostProcessor


Object classes which implement the Spring.Objects.Factory.Config.IObjectFactoryPostProcessor interface, have already been mentioned. It is worth mentioning again here though, that object factory post-processors are much more convenient to use in IApplicationContexts. In an IApplicationContext, any deployed object which implements the above marker interface is automatically detected as an object factory post-processor, to be called at the appropriate time. factory post-processors are

5.13.4. The PropertyPlaceholderConfigurer


The PropertyPlaceholderConfigurer has already been described in the context of its use within an IObjectFactory. It is worth mentioning here though, that it is generally more convenient to use it with an IApplicationContext, since the context will automatically recognize and apply any object factory postprocessors, such as this one, when they are simply deployed into it like any other object. There is no need for a manual step to execute it.

5.14. Configuration of ApplicationContext without using XML


The class GenericApplicationContext can be used as a basis for creating an IApplicationContext implementation that read the container metadata from sources other than XML. This could be by scanning objects in a .DLL for known attributes or a scripting language that leverages a DSL to create terse IObjectDefinitions. There is a class, Spring.Objects.Factory.Support.ObjectDefinitionBuilder offers some convenience methods for creating an IObjectDefinition in a less verbose manner than using the RootObjectDefinition API. The following shows how to configure the GenericApplicationContext to read from XML, just so show familiar API usage

Spring Framework (Version 1.3.2)

83

The IoC container


GenericApplicationContext ctx = new GenericApplicationContext(); XmlObjectDefinitionReader reader = new XmlObjectDefinitionReader(ctx); reader.LoadObjectDefinitions("assembly://Spring.Core.Tests/Spring.Context.Support/contextB.xml"); reader.LoadObjectDefinitions("assembly://Spring.Core.Tests/Spring.Context.Support/contextC.xml"); reader.LoadObjectDefinitions("assembly://Spring.Core.Tests/Spring.Context.Support/contextA.xml"); ctx.Refresh();

The implementation of IObjectDefinitionReader is responsible for creating the configuration metadata, i.e., implementations of RootObjectDefinition, etc. Note a web version of this application class has not yet been implemented. An example, with a yet to be created DLL scanner, that would get configuration metadata from the .dll named MyAssembly.dll located in the runtime path, would look something like this
GenericApplicationContext ctx = new GenericApplicationContext(); ObjectDefinitionScanner scanner = new ObjectDefinitionScanner(ctx); scanner.scan("MyAssembly.dll"); ctx.refresh();

Refer to the Spring API documentation for more information.

5.15. Service Locator access


The majority of the code inside an application is best written in a Dependency Injection (Inversion of Control) style, where that code is served out of an IObjectFactory or IApplicationContext container, has its own dependencies supplied by the container when it is created, and is completely unaware of the container. However, there is sometimes a need for singleton (or quasi-singleton) style access to an IObjectFactory or IApplicationContext. For example, third party code may try to construct a new object directly without the ability to force it to get these objects out of the IObjectFactory. Similarly, nested user control components in a WinForms application are created inside the generated code in InitializeComponent. If this user control would like to obtain references to objects contained in the container it can use the service locator style approach and 'reach out' from inside the code to obtain the object it requires. (Note support for DI in WinForms is under development.) The Spring.Context.Support.ContextRegistry class allows you to obtain a reference to an IApplicationContext via a static locator method. The ContextRegistry is initialized when creating an IApplicationContext through use of the ContextHandler discussed previously. The simple static method GetContext() can then be used to retrieve the context. Alternatively, if you create an IApplicationContext though other means you can register it with the ContextRegistry via the method void RegisterContext(IApplicationContext context) in the start-up code of your application. Hierarchical context retrieval is also supported though the use of the GetContext(string name) method, for example:
IApplicationContex ctx = ContextRegistry.GetContext("mySubContext");

This would retrieve the nested context for the context configuration shown previously.
<spring> <context> <resource uri="assembly://MyAssembly/MyProject/root-objects.xml"/> <context name="mySubContext"> <resource uri="file://objects.xml"/> </context> </context> </spring>

Do not call ContextRegistry.GetContext within a constructor as it will result in and endless recursion. (This is scheduled to be fixed in 1.1.1) In this case it is quite likely you can use the IApplicationContextAware interface and then retrieve other objects in a service locator style inside an initialization method.

Spring Framework (Version 1.3.2)

84

The IoC container The ContextRegistry.Clear() method will remove all contexts. On .NET 2.0, this will also call the ConfigurationManager's RefreshSection method so that the Spring context configuration section will be reread from disk when it is retrieved again. Note that in a web application RefeshSection will not work as advertised and you will need to touch the web.config files to reload a configuration.

5.16. Stereotype attributes


Beginning with Spring 1.2, the [Repository] attribute was introduced as a marker for any class that fulfills the role or stereotype of a repository (a.k.a. Data Access Object or DAO). Among the possibilities for leveraging such a marker is the automatic translation of exceptions as described in Exception Translation. Spring 1.2 introduces further stereotype annotations: [Component] and [Service]. [Component] serves as a generic stereotype for any Spring-managed component; whereas, [Repository] and [Service] serve as specializations of [Component] for more specific use cases (e.g., in the persistence and service layers, respectively). The ASP.NET MVC [Controller] attribute will serve this purpose for the controller layer. What this means is that you can annotate your component classes with [Component], but by annotating them with [Repository] or [Service] your classes are more properly suited for processing by tools or associating with aspects. For example, these stereotype annotations make ideal targets for pointcuts. Of course, it is also possible that [Repository] and [Service] may carry additional semantics in future releases of the Spring Framework. Thus, if you are making a decision between using [Component] or [Service] for your service layer, [Service] is clearly the better choice. Similarly, as stated above, [Repository] is already supported as a marker for automatic exception translation in your persistence layer. The next version of Spring will use the [Component] attribute to perform attribute based autowiring by-type as in the Spring Java Framework.

Spring Framework (Version 1.3.2)

85

Chapter 6. The IObjectWrapper and Type conversion


6.1. Introduction
The concepts encapsulated by the IObjectWrapper interface are fundamental to the workings of the core Spring.NET libraries The typical application developer most probably will not ever have the need to use the IObjectWrapper directly... because this is reference documentation however, we felt that some explanation of this core interface might be right. The IObjectWrapper is explained in this chapter since if you were going to use it at all, you would probably do that when trying to bind data to objects, which, nicely enough, is precisely the area that the IObjectWrapper addresses.

6.2. Manipulating objects using the IObjectWrapper


One quite important concept of the Spring.Objects namespace is encapsulated in the definition IObjectWrapper interface and its corresponding implementation, the ObjectWrapper class. The functionality offered by the IObjectWrapper includes methods to set and get property values (either individually or in bulk), get property descriptors (instances of the System.Reflection.PropertyInfo class), and to query the readability and writability of properties. The IObjectWrapper also offers support for nested properties, enabling the setting of properties on subproperties to an unlimited depth. The IObjectWrapper usually isn't used by application code directly, but by framework classes such as the various IObjectFactory implementations. The way the IObjectWrapper works is partly indicated by its name: it wraps an object to perform actions on a wrapped object instance... such actions would include the setting and getting of properties exposed on the wrapped object. Note: the concepts explained in this section are not important to you if you're not planning to work with the IObjectWrapper directly.

6.2.1. Setting and getting basic and nested properties


Setting and getting properties is done using the SetPropertyValue() and GetPropertyValue() methods, for which there are a couple of overloaded variants. The details of the various overloads (including return values and method parameters) are all described in the extensive API documentation supplied as a part of the Spring.NET distribution. The aforementioned SetPropertyValue() and GetPropertyValue() methods have a number of conventions for indicating the path of a property. A property path is an expression that implementations of the IObjectWrapper interface can use to look up the properties of the wrapped object; some examples of property paths include... Table 6.1. Examples of property paths Path name account.name Explanation Indicates the name property of the wrapped object. Indicates the nested property name of the account property of the wrapped object.

Spring Framework (Version 1.3.2)

86

The IObjectWrapper and Type conversion Path account[2] Explanation Indicates the third element of the account property of the wrapped object. Indexed properties are typically collections such as lists and dictionaries, but can be any class that exposes an indexer.

Below you'll find some examples of working with the IObjectWrapper to get and set properties. Consider the following two classes:
[C#] public class Company { private string name; private Employee managingDirector; public string Name { get { return this.name; } set { this.name = value; } } public Employee ManagingDirector { get { return this.managingDirector; } set { this.managingDirector = value; } } }

[C#] public class Employee { private string name; private float salary; public string Name { get { return this.name; } set { this.name = value; } } public float Salary { get { return salary; } set { this.salary = value; } } }

The following code snippets show some examples of how to retrieve and manipulate some of the properties of IObjectWrapper-wrapped Company and Employee instances.
[C#] Company c = new Company(); IObjectWrapper owComp = new ObjectWrapper(c); // setting the company name... owComp.SetPropertyValue("name", "Salina Inc."); // can also be done like this... PropertyValue v = new PropertyValue("name", "Salina Inc."); owComp.SetPropertyValue(v); // ok, let's create the director and bind it to the company... Employee don = new Employee(); IObjectWrapper owDon = new ObjectWrapper(don); owDon.SetPropertyValue("name", "Don Fabrizio"); owComp.SetPropertyValue("managingDirector", don); // retrieving the salary of the ManagingDirector through the company float salary = (float)owComp.GetPropertyValue("managingDirector.salary");

Spring Framework (Version 1.3.2)

87

The IObjectWrapper and Type conversion Note that since the various Spring.NET libraries are compliant with the Common Language Specification (CLS), the resolution of arbitrary strings to properties, events, classes and such is performed in a case-insensitive fashion. The previous examples were all written in the C# language, which is a case-sensitive language, and yet the Name property of the Employee class was set using the all-lowercase 'name' string identifier. The following example (using the classes defined previously) should serve to illustrate this...
[C#] // ok, let's create the director and bind it to the company... Employee don = new Employee(); IObjectWrapper owDon = new ObjectWrapper(don); owDon.SetPropertyValue("naMe", "Don Fabrizio"); owDon.GetPropertyValue("nAmE"); // gets "Don Fabrizio" IObjectWrapper owComp = new ObjectWrapper(new Company()); owComp.SetPropertyValue("ManaGINGdirecToR", don); owComp.SetPropertyValue("mANaGiNgdirector.salARY", 80000); Console.WriteLine(don.Salary); // puts 80000

The case-insensitivity of the various Spring.NET libraries (dictated by the CLS) is not usually an issue... if you happen to have a class that has a number of properties, events, or methods that differ only by their case, then you might want to consider refactoring your code, since this is generally regarded as poor programming practice.

6.2.2. Other features worth mentioning


In addition to the features described in the preceding sections there a number of features that might be interesting to you, though not worth an entire section. determining readability and writability: using the IsReadable() and IsWritable() methods, you can determine whether or not a property is readable or writable. retrieving PropertyInfo instances: using GetPropertyInfo(string) and GetPropertyInfos() you can retrieve instances of the System.Reflection.PropertyInfo class, that might come in handy sometimes when you need access to the property metadata specific to the object being wrapped.

6.3. Type conversion


If you associate a TypeConverter with the definition of a custom Type using the standard .NET mechanism (see the example code below), Spring.NET will use the associated TypeConverter to do the conversion.
[C#] [TypeConverter (typeof (FooTypeConverter))] public class Foo { }

The TypeConverter class from the System.ComponentModel namespace of the .NET BCL is used extensively by the various classes in the Spring.Core library, as said class ... provides a unified way of converting types of values to other types, as well as for accessing standard values and subproperties. 1 For example, a date can be represented in a human readable format (such as 30th August 1984), while we're still able to convert the human readable form to the original date format or (even better) to an instance of the System.DateTime class. This behavior can be achieved by using the standard .NET idiom of decorating a class with the TypeConverterAttribute. Spring.NET also offers another means of associating a TypeConverters with a class. You might want to do this to achieve a conversion that is not possible using standard idiom... for example,
1

More information about creating custom TypeConverter implementations can be found online at Microsoft's MSDN website, by searching for Implementing a Type Converter.

Spring Framework (Version 1.3.2)

88

The IObjectWrapper and Type conversion the Spring.Core library contains a custom TypeConverter that converts comma-delimited strings to String array instances. Registering custom converters on an IObjectWrapper instance gives the wrapper the knowledge of how to convert properties to the desired Type. An example of where property conversion is used in Spring.NET is the setting of properties on objects, accomplished using the aforementioned TypeConverters. When mentioning System.String as the value of a property of some object (declared in an XML file for instance), Spring.NET will (if the type of the associated property is System.Type) use the RuntimeTypeConverter class to try to resolve the property value to a Type object. The example below demonstrates this automatic conversion of the Example.Xml.SAXParser (a string) into the corresponding Type instance for use in this factory-style class.
<objects xmlns="http://www.springframework.net"> <object id="parserFactory" type="Example.XmlParserFactory, ExamplesLibrary" destroy-method="Close"> <property name="ParserClass" value="Example.Xml.SAXParser, ExamplesLibrary"/> </object> </objects>

[C#] public class XmlParserFactory { private Type parserClass; public Type ParserClass { get { return this.parserClass; } set { this.parserClass = value; } } public XmlParser GetParser () { return Activator.CreateInstance (ParserClass); } }

6.3.1. Type Conversion for Enumerations


The default type converter for enumerations is the System.ComponentModel.EnumConverter class. To specify the value for an enumerated property, simply use the name of the property. For example the TestObject class has a property of the enumerated type FileMode. One of the values for this enumeration is named Create. The following XML fragment shows how to configure this property
<object id="rod" type="Spring.Objects.TestObject, Spring.Core.Tests"> <property name="name" value="Rod"/> <property name="FileMode" value="Create"/> </object>

6.4. Built-in TypeConverters


Spring.NET has a number of built-in TypeConverters to make life easy. Each of those is listed below and they are all located in the Spring.Objects.TypeConverters namespace of the Spring.Core library. Table 6.2. Built-in TypeConverters Type
RuntimeTypeConverter

Explanation Parses strings representing System.Types to actual System.Types and the other way around. Capable of resolving strings to a System.IO.FileInfo object.

FileInfoConverter

Spring Framework (Version 1.3.2)

89

The IObjectWrapper and Type conversion Type


StringArrayConverter

Explanation Capable of resolving a comma-delimited list of strings to a stringarray and vice versa. Capable of resolving a string representation of a URI to an actual Uri-object. Capable of resolving a string representation of a FileInfo to an actual FileInfo-object. Capable of resolving Spring IResource URI (string) to its corresponding InputStream-object. Capable of resolving Spring IResource URI (string) to an IResource object. Capable of resolving a two part string (resource name, assembly name) to a System.Resources.ResourceManager object. Capable of resolving a comma separated list of Red, Green, Blue integer values to a System.Drawing.Color structure. Converts string representation of regular expression into an instance of System.Text.RegularExpressions.Regex

UriConverter

FileInfoConverter

StreamConverter

ResourceConverter

ResourceManagerConverter

RgbColorConverter

RegexConverter

Spring.NET uses the standard .NET mechanisms for the resolution of System.Types, including, but not limited to checking any configuration files associated with your application, checking the Global Assembly Cache (GAC), and assembly probing.

6.4.1. Custom type converters


You can register a custom type converter either Programatically using the class TypeConverterRegistry or through configuration of Spring's container and described in the section Registering Type Converters.

Spring Framework (Version 1.3.2)

90

Chapter 7. Resources
7.1. Introduction
The IResource interface contained in the Spring.Core.IO namespace provides a common interface to describe and access data from diverse resource locations. This abstraction lets you treat the InputStream from a file and from a URL in a polymorphic and protocol-independent manner... the .NET BCL does not provide such an abstraction. The IResource interface inherits from IInputStream that provides a single property Stream InputStream. The IResource interface adds descriptive information about the resource via a number of additional properties. Several implementations for common resource locations, i.e. file, assembly, uri, are provided and you may also register custom IResource implementations.

7.2. The IResource interface


The IResource interface is shown below
public interface IResource : IInputStreamSource { bool IsOpen { get; } Uri Uri { get; } FileInfo File { get; } string Description { get; } bool Exists { get; } IResource CreateRelative(string relativePath); }

Table 7.1. IResource Properties Property


InputStream

Explanation Inherited from IInputStream. Opens and returns a System.IO.Stream. It is expected that each invocation returns a fresh Stream. It is the responsibility of the caller to close the stream. returns a boolean indicating whether this resource actually exists in physical form. returns a boolean indicating whether this resource represents a handle with an open stream. If true, the InputStream cannot be read multiple times, and must be read once only and then closed to avoid resource leaks. Will be false for all usual resource implementations, with the exception of InputStreamResource. Returns a description of the resource, such as the fully qualified file name or the actual URL. The Uri representation of the resource. Returns a System.IO.FileInfo for this resource if it can be resolved to an absolute file path.

Exists

IsOpen

Description

Uri File

and the methods

Spring Framework (Version 1.3.2)

91

Resources Table 7.2. IResource Methods Method


IResource CreateRelative

Explanation Creates a resource relative to this resource using relative path like notation (./ and ../).

(string relativePath)

You can obtain an actual URL or File object representing the resource if the underlying implementation is compatible and supports that functionality. The Resource abstraction is used extensively in Spring itself, as an argument type in many method signatures when a resource is needed. Other methods in some Spring APIs (such as the constructors to various IApplicationContext implementations), take a String which is used to create a Resource appropriate to that context implementation While the Resource interface is used a lot with Spring and by Spring, it's actually very useful to use as a general utility class by itself in your own code, for access to resources, even when your code doesn't know or care about any other parts of Spring. While this couples your code to Spring, it really only couples it to this small set of utility classes and can be considered equivalent to any other library you would use for this purpose

7.3. Built-in IResource implementations


The resource implementations provided are AssemblyResource accesses data stored as .NET resources inside an assembly. Uri syntax is assembly://
<AssemblyName>/<NameSpace>/<ResourceName>

ConfigSectionResource accesses Spring.NET configuration data stored in a custom configuration section in the .NET application configuration file (i.e. App.config). Uri syntax is config://<path to section> FileSystemResource accesses file system data. Uri syntax is file://<filename> InputStreamResource a wrapper around a raw System.IO.Stream . Uri syntax is not supported. UriResource accesses data from the standard System.Uri protocols such as http and https. In .NET 2.0 you can use this also for the ftp protocol. Standard Uri syntax is supported. Refer to the MSDN documentation for more information on supported Uri scheme types.

7.3.1. Registering custom IResource implementations


The configuration section handler, ResourceHandlersSectionHandler, is used to register any custom IResource implementations you have created. In the configuration section you list the type of IResource implementation and the protocol prefix. Your custom IResource implementation must provide a constructor that takes a string as it's sole argument that represents the URI string. Refer to the SDK documentation for ResourceHandlersSectionHandler for more information. An example of the ResourceHandlersSectionHandler is shown below for a fictional IResource implementation that interfaces with a database.
<configuration> <configSections> <sectionGroup name="spring"> <section name='context' type='Spring.Context.Support.ContextHandler, Spring.Core'/> <section name="resourceHandlers" type="Spring.Context.Support.ResourceHandlersSectionHandler, Spring.Core"/> </sectionGroup>

Spring Framework (Version 1.3.2)

92

Resources
</configSections> <spring> <resourceHandlers> <handler protocol="db" type="MyCompany.MyApp.Resources.MyDbResource, MyAssembly"/> </resourceHandlers> <context> <resource uri="db://user:pass@dbName/MyDefinitionsTable"/> </context> </spring> </configuration>

7.4. The IResourceLoader


To load resources given their Uri syntax, an implementation of the IResourceLoader is used. The default implementation is ConfigurableResourceLoader. Typically you will not need to access this class directly since the IApplicationContext implements the IResourceLoader interface that contains the single method IResource GetResource(string location). The provided implementations of IApplicationContext delegate this method to an instance of ConfigurableResourceLoader which supports the Uri protocols/schemes listed previously. If you do not specify a protocol then the file protocol is used. The following shows some sample usage.
IResource resource = appContext.GetResource("http://www.springframework.net/license.html"); resource = appContext.GetResource("assembly://Spring.Core.Tests/Spring/TestResource.txt"); resource = appContext.GetResource("https://sourceforge.net/"); resource = appContext.GetResource("file:///C:/WINDOWS/ODBC.INI"); StreamReader reader = new StreamReader(resource.InputStream); Console.WriteLine(reader.ReadToEnd());

Other protocols can be registered along with a new implementations of an IResource that must correctly parse a Uri string in its constructor. An example of this can be seen in the Spring.Web namespace that uses Server.MapPath to resolve the filename of a resource. The CreateRelative method allows you to easily load resources based on a relative path name. In the case of relative assembly resources, the relative path navigates the namespace within an assembly. For example:
IResource res = new AssemblyResource("assembly://Spring.Core.Tests/Spring/TestResource.txt"); IResource res2 = res.CreateRelative("./IO/TestIOResource.txt");

This loads the resource TestResource.txt and then navigates to the Spring.Core.IO namespace and loads the resource TestIOResource.txt

7.5. The IResourceLoaderAware interface


The IResourceLoaderAware interface is a special marker interface, identifying objects that expect to be provided with a IResourceLoader reference.
public interface IResourceLoaderAware { IResourceLoader ResourceLoader { set; get; } }

When a class implements IResourceLoaderAware and is deployed into an application context (as a Springmanaged object), it is recognized as IResourceLoaderAware by the application context. The application context

Spring Framework (Version 1.3.2)

93

Resources will then invoke the ResourceLoader property, supplying itself as the argument (remember, all application contexts in Spring implement the IResourceLoader interface). Of course, since an IApplicationContext is a IResourceLoader, the object could also implement the IApplicationContextAware interface and use the supplied application context directly to load resources, but in general, it's better to use the specialized IResourceLoader interface if that's all that's needed. The code would just be coupled to the resource loading interface, which can be considered a utility interface, and not the whole Spring IApplicationContext interface.

7.6. Application contexts and IResource paths


An application context constructor (for a specific application context type) generally takes a string or array of strings as the location path(s) of the resource(s) such as XML files that make up the definition of the context. For example, you can create an XmlApplicationContext from two resources as follows:
IApplicationContext context = new XmlApplicationContext( "file://objects.xml", "assembly://MyAssembly/MyProject/objects-dal-layer.xml");

Spring Framework (Version 1.3.2)

94

Chapter 8. Threading and Concurrency Support


8.1. Introduction
The purpose of the Spring.Threading namespace is to provide a place to keep useful concurrency abstractions that augment those in the BCL. Since Doug Lea has provided a wealth of mature public domain concurrency abstractions in his Java based 'EDU.oswego.cs.dl.util.concurrent' libraries we decided to port a few of his abstractions to .NET. So far, we've only ported three classes, the minimum necessary to provide basic object pooling functionality to support an AOP based pooling aspect and to provide a Semaphore class that was mistakenly not included in .NET 1.0/1.1. There is also an important abstraction, IThreadStorage, for performing thread local storage.

8.2. Thread Local Storage


Depending on your runtime environment there are different strategies to use for storing objects in thread local storage. If you are in web applications a single Request may be executed on different threads. As such, the location to store thread local objects is in HttpContext.Current. For other environments System.Runtime.Remoting.Messaging.CallContext is used. For more background information on the motivation behind these choices, say as compared to the attribute [ThreadStatic] refer to "Piers7"'s blog and this forum post. The interface IThreadStorage serves as the basis for the thread local storage abstraction and various implementations can be selected from depending on your runtime requirements. Configuring the implementation of IThreadStorage makes it easier to have more portability across runtime environments. The API is quite simple and shown below
public interface IThreadStorage { object GetData(string name) void SetData(string name, object value) void FreeNamedDataSlot(string name) }

The methods GetData and SetData are responsible for retrieving and setting the object that is to be bound to thread local storage and associating it with a name. Clearing the thread local storage is done via the method FreeNamedDataSlot. In Spring.Core is the implementation, CallContextStorage, that directly uses CallContext and also the implementation LogicalThreadContext which by default uses CallContextStorage but can be configured via the static method SetStorage(IThreadStorage). The methods on CallContextStorage and LogicalThreadContext are static. In Spring.Web is the implementation HttpContextStorage which uses the HttpContext to store thread local data and HybridContextStorage that uses HttpContext if within a web environment, i.e. HttpContext.Current ! = null, and CallContext otherwise.

Spring Framework (Version 1.3.2)

95

Threading and Concurrency Support Spring internally uses LogicalThreadContext as this doesn't require a coupling to the System.Web namespace. In the case of Spring based web applications, Spring's WebSupportModule sets the storage strategy of LogicalThreadContext to be HybridContextStorage.

8.3. Synchronization Primitives


When you take a look at these synchronization classes, you'll wonder why it's even necessary when System.Threading provides plenty of synchronization options. Although System.Threading provides great synchronization classes, it doesn't provide well-factored abstractions and interfaces for us. Without these abstractions, we will tend to code at a low-level. With enough experience, you'll eventually come up with some abstractions that work well. Doug Lea has already done a lot of that research and has a class library that we can take advantage of.

8.3.1. ISync
is the central interface for all classes that control access to resources from multiple threads. It's a simple interface which has two basic use cases. The first case is to block indefinitely until a condition is met:
ISync
void ConcurrentRun(ISync lock) { lock.Acquire(); // block until condition met try { // ... access shared resources } finally { lock.Release(); } }

The other case is to specify a maximum amount of time to block before the condition is met:
void ImpatientConcurrentRun(ISync lock) { // block for at most 10 milliseconds for condition if ( lock.Attempt(10) ) { try { // ... access shared resources } finally { lock.Release(); } } else { // complain of time out } }

8.3.2. SyncHolder
The SyncHolder class implements the System.IDisposable interface and so provides a way to use an ISync with the using C# keyword: the ISync will be automatically Acquired and then Released on exiting from the block. This should simplify the programming model for code using (!) an ISync:
ISync sync = ... ... using (new SyncHolder(sync)) { // ... code to be executed // holding the ISync lock }

There is also the timed version, a little more cumbersome as you must deal with timeouts:

Spring Framework (Version 1.3.2)

96

Threading and Concurrency Support

ISync sync = ... long msecs = 100; ... // try to acquire the ISync for msecs milliseconds try { using (new SyncHolder(sync, msecs)) { // ... code to be executed // holding the ISync lock } } catch (TimeoutException) { // deal with failed lock acquisition }

8.3.3. Latch
The Latch class implements the ISync interface and provides an implementation of a latch. A latch is a boolean condition that is set at most once, ever. Once a single release is issued, all acquires will pass. It is similar to a ManualResetEvent initialized unsignalled (Reset) and can only be Set(). A typical use is to act as a start signal for a group of worker threads.
class Boss { Latch _startPermit; void Worker() { // very slow worker initialization ... // ... attach to messaging system // ... connect to database _startPermit.Acquire(); // ... use resources initialized in Mush // ... do real work } void Mush() { _startPermit = new Latch(); for (int i=0; i<10; ++i) { new Thread(new ThreadStart(Worker)).Start(); } // very slow main initialization ... // ... parse configuration // ... initialize other resources used by workers _startPermit.Release(); } }

8.3.4. Semaphore
The Semaphore class implements the ISync interface and provides an implementation of a semaphore. Conceptually, a semaphore maintains a set of permits. Each Acquire() blocks if necessary until a permit is available, and then takes it. Each Release() adds a permit. However, no actual permit objects are used; the Semaphore just keeps a count of the number available and acts accordingly. A typical use is to control access to a pool of shared objects.
class LimitedConcurrentUploader { // ensure we don't exceed maxUpload simultaneous uploads Semaphore _available; public LimitedConcurrentUploader(maxUploads) { _available = new Semaphore(maxUploads); } // no matter how many threads call this method no more

Spring Framework (Version 1.3.2)

97

Threading and Concurrency Support


// than maxUploads concurrent uploads will occur. public Upload(IDataTransfer upload) { _available.Acquire(); try { upload.TransferData(); } finally { _available.Release(); } } }

Spring Framework (Version 1.3.2)

98

Chapter 9. Object Pooling


9.1. Introduction
The Spring.Pool namespace contains a generic API for implementing pools of objects. Object pooling is a well known technique to minimize the creation of objects that can take a significant amount of time. Common examples are to create a pool of database connections such that each request to the database can reuse an existing connection instead of creating one per client request. Threads are also another common candidate for pooling in order to increase responsiveness of an application to multiple concurrent client requests. .NET contains support for object pooling in these common scenarios. Support for database connection pools is directly supported by ADO.NET data providers as a configuration option. Similarly, thread pooling is supported via the System.ThreadPool class. Support for pooling of other objects can be done using the CLR managed API to COM+ found in the System.EnterpriseServices namespace. Despite this built-in support there are scenarios where you would like to use alternative pool implementations. This may be because the default implementations, such as System.ThreadPool, do not meet your requirements. (For a discussion on advanced ThreadPool usage see Smart Thread Pool by Ami Bar.) Alternatively, you may want to pool classes that do not inherit from System.EnterpriseServices.ServicedComponent. Instead of making changes to the object model to meet this inheritance requirement, Spring .NET provides similar support for pooling, but for any object, by using AOP proxies and a generic pool API for managing object instances. Note, that if you are concerned only with applying pooling to an existing object, the pooling APIs discussed here are not very important. Instead the use and configuration of Spring.Aop.Target.SimplePoolTargetSource is more relevant. Pooling of objects can either be done Programatically or through the XML configuration of the Spring .NET container. Attribute support for pooling, similar to the ServicedComponent approach, will be available in a future release of Spring.NET. Chapter 37, IoC Quickstarts contains an example that shows the use of the pooling API independent of AOP functionality.

9.2. Interfaces and Implementations


The Spring.Pool namespace provides two simple interfaces to manage pools of objects. The first interface, IObjectPool describes how to take and put back an object from the pool. The second interface IPoolableObjectFactory is meant to be used in conjunction with implementations of the IObjectPool to provide guidance in calling various lifecycle events on the objects managed by the pool. These interfaces are based on the Jakarta Commons Pool API. Spring.Pool.Support.SimplePool is a default implementation of IObjectPool and Spring.Aop.Target.SimplePoolTargetSource is the implementation of IPoolableObjectFactory for use with AOP. The current goal of the Spring.Pool namespace is not to provide a one-for-one replacement of the Jakarta Commons Pool API, but rather to support basic object pooling needs for common AOP scenarios. Consequently, other interfaces and base classes available in the Jakarta package are not available.

Spring Framework (Version 1.3.2)

99

Chapter 10. Spring.NET miscellanea


10.1. Introduction
This chapter contains miscellanea information on features, goodies, caveats that does not belong to any paricular area.

10.2. PathMatcher
Spring.Util.PathMatcher

provides Ant/NAnt-like path name matching features.

To do the match, you use the method:


static bool Match(string pattern, string path)

If you want to decide if case is important or not use the method:


static bool Match(string pattern, string path, bool ignoreCase)

10.2.1. General rules


To build your pattern, you use the *, ? and ** building blocks: *: matches any number of non slash characters; ?: matches exactly 1 (one) non slash/dot character; **: matches any subdirectory, without taking care of the depth;

10.2.2. Matching filenames


A file name can be matched using the following notation:
foo?bar.*

matches:
fooAbar.txt foo1bar.txt foo_bar.txt foo-bar.txt

does not match:


foo.bar.txt foo/bar.txt foo\bar.txt

The classical all files pattern:


*.*

matches:
foo.db .db foo foo.bar.db foo.db.db db.db.db

Spring Framework (Version 1.3.2)

100

Spring.NET miscellanea does not match:


c:/ c:/foo.db c:/foo c:/.db c:/foo.foo.db //server/foo

10.2.3. Matching subdirectories


A directory name can be matched at any depth level using the following notation:
**/db/**

That pattern matches the following paths:


/db //server/db c:/db c:/spring/app/db/foo.db //Program Files/App/spaced dir/db/foo.db /home/spring/spaced dir/db/v1/foo.db

but does not match these:


c:/spring/app/db-v1/foo.db /home/spring/spaced dir/db-v1/foo.db

You can compose subdirectories to match like this:


**/bin/**/tmp/**

That pattern matches the following paths:


c:/spring/foo/bin/bar/tmp/a c:/spring/foo/bin/tmp/a/b.c

but does not match these:


c:/spring/foo/bin/bar/temp/a c:/tmp/foo/bin/bar/a/b.c

You can use more advanced patterns:


**/.spring-assemblies*/**

matches:
c:/.spring-assemblies c:/.spring-assembliesabcd73xs c:/app/.spring-assembliesabcd73xs c:/app/.spring-assembliesabcd73xs/foo.dll //server/app/.spring-assembliesabcd73xs

does not match:


c:/app/.spring-assemblie

10.2.4. Case does matter, slashes don't


.NET is expected to be a cross-platform development ... platform. So, PathMatcher will match taking care of the case of the pattern and the case of the path. For example:

Spring Framework (Version 1.3.2)

101

Spring.NET miscellanea
**/db/**/*.DB

matches:
c:/spring/service/deploy/app/db/foo.DB

but does not match:


c:/spring/service/deploy/app/DB/foo.DB c:spring/service/deploy/app/spaced dir/DB/foo.DB //server/share/service/deploy/app/DB/backup/foo.db

If you do not matter about case, you should explicitly tell the Pathmatcher. Back and forward slashes, in the very same cross-platform spirit, are not important:
spring/foo.bar

matches all the following paths:


c:\spring\foo.bar c:/spring\foo.bar c:/spring/foo.bar /spring/foo.bar \spring\foo.bar

Spring Framework (Version 1.3.2)

102

Chapter 11. Expression Evaluation


11.1. Introduction
The Spring.Expressions namespace provides a powerful expression language for querying and manipulating an object graph at runtime. The language supports setting and getting of property values, property assignment, method invocation, accessing the context of arrays, collections and indexers, logical and arithmetic operators, named variables, and retrieval of objects by name from Spring's IoC container. It also supports list projection and selection, as well as common list aggregators. The functionality provided in this namespace serves as the foundation for a variety of other features in Spring.NET such as enhanced property evaluation in the XML based configuration of the IoC container, a Data Validation framework, and a Data Binding framework for ASP.NET. You will likely find other cool uses for this library in your own work where run-time evaluation of criteria based on an object's state is required. For those with a Java background, the Spring.Expressions namespace provides functionality similar to the Java based Object Graph Navigation Language, OGNL. This chapter covers the features of the expression language using an Inventor and Inventor's Society class as the target objects for expression evaluation. The class declarations and the data used to populate them are listed at the end of the chapter in section Section 11.4, Classes used in the examples. These classes are blatantly taken from the NUnit tests for the Expressions namespace which you can refer to for additional example usage.

11.2. Evaluating Expressions


The simplest, but not the most efficient way to perform expression evaluation is by using one of the static convenience methods of the ExpressionEvaluator class:
public static object GetValue(object root, string expression); public static object GetValue(object root, string expression, IDictionary variables) public static void SetValue(object root, string expression, object newValue) public static void SetValue(object root, string expression, IDictionary variables, object newValue)

The first argument is the 'root' object that the expression string (2nd argument) will be evaluated against. The third argument is used to support variables in the expression and will be discussed later. Simple usage to get the value of an object property is shown below using the Inventor class. You can find the class listing in section Section 11.4, Classes used in the examples.
Inventor tesla = new Inventor("Nikola Tesla", new DateTime(1856, 7, 9), "Serbian"); tesla.PlaceOfBirth.City = "Smiljan"; string evaluatedName = (string) ExpressionEvaluator.GetValue(tesla, "Name"); string evaluatedCity = (string) ExpressionEvaluator.GetValue(tesla, "PlaceOfBirth.City"));

The value of 'evaluatedName' is 'Nikola Tesla' and that of 'evaluatedCity' is 'Smiljan'. A period is used to navigate the nested properties of the object. Similarly to set the property of an object, say we want to rewrite history and change Tesla's city of birth, we would simply add the following line
ExpressionEvaluator.SetValue(tesla, "PlaceOfBirth.City", "Novi Sad");

Spring Framework (Version 1.3.2)

103

Expression Evaluation A much better way to evaluate expressions is to parse them once and then evaluate as many times as you want usingExpressionclass. Unlike ExpressionEvaluator, which parses expression every time you invoke one of its methods, Expression class will cache the parsed expression for increased performance. The methods of this class are listed below:
public static IExpression Parse(string expression) public override object Get(object context, IDictionary variables) public override void Set(object context, IDictionary variables, object newValue)

The retrieval of the Name property in the previous example using the Expression class is shown below
IExpression exp = Expression.Parse("Name"); string evaluatedName = (string) exp.GetValue(tesla, null);

The difference in performance between the two approaches, when evaluating the same expression many times, is several orders of magnitude, so you should only use convenience methods of the ExpressionEvaluator class when you are doing one-off expression evaluations. In all other cases you should parse the expression first and then evaluate it as many times as you need. There are a few exception classes to be aware of when using the ExpressionEvaluator. These are InvalidPropertyException, when you refer to a property that doesn't exist, NullValueInNestedPathException, when a null value is encountered when traversing through the nested property list, and ArgumentException and NotSupportedException when you pass in values that are in error in some other manner. The expression language is based on a grammar and uses ANTLR to construct the lexer and parser. Errors relating to bad syntax of the language will be caught at this level of the language implementation. For those interested in the digging deeper into the implementation, the grammar file is named Expression.g and is located in the src directory of the namespace. As a side note, the release version of the ANTLR DLL included with Spring.NET was signed with the Spring.NET key, which means that you should always use the included version of antlr.runtime.dll within your application. Upcoming releases of ANTLR will provide strongly signed assemblies, which will remove this requirement.

11.3. Language Reference


11.3.1. Literal expressions
The types of literal expressions supported are strings, dates, numeric values (int, real, and hex), boolean and null. String are delimited by single quotes. To put a single quote itself in a string use the backslash character. The following listing shows simple usage of literals. Typically they would not be used in isolation like this, but as part of a more complex expression, for example using a literal on one side of a logical comparison operator.
string helloWorld = (string) ExpressionEvaluator.GetValue(null, "'Hello World'"); // evals to "Hello World" string tonyPizza Pizza" = (string) ExpressionEvaluator.GetValue(null, "'Tony\\'s Pizza'"); // evals to "Tony's

double avogadrosNumber = (double) ExpressionEvaluator.GetValue(null, "6.0221415E+23"); int maxValue = (int) ExpressionEvaluator.GetValue(null, "0x7FFFFFFF"); // evals to 2147483647

DateTime birthday = (DateTime) ExpressionEvaluator.GetValue(null, "date('1974/08/24')"); DateTime exactBirthday = (DateTime) ExpressionEvaluator.GetValue(null, " date('19740824T131030', 'yyyyMMddTHHmmss')"); bool trueValue = (bool) ExpressionEvaluator.GetValue(null, "true");

Spring Framework (Version 1.3.2)

104

Expression Evaluation

object nullValue = ExpressionEvaluator.GetValue(null, "null");

Note that the extra backslash character in Tony's Pizza is to satisfy C# escape syntax. Numbers support the use of the negative sign, exponential notation, and decimal points. By default real numbers are parsed using Double.Parse unless the format character "M" or "F" is supplied, in which case Decimal.Parse and Single.Parse would be used respectfully. As shown above, if two arguments are given to the date literal then DateTime.ParseExact will be used. Note that all parse methods of classes that are used internally reference the CultureInfo.InvariantCulture.

11.3.2. Properties, Arrays, Lists, Dictionaries, Indexers


As shown in the previous example in Section 11.2, Evaluating Expressions, navigating through properties is easy, just use a period to indicate a nested property value. The instances of Inventor class, pupin and tesla, were populated with data listed in section Section 11.4, Classes used in the examples. To navigate "down" and get Tesla's year of birth and Pupin's city of birth the following expressions are used
int year = (int) ExpressionEvaluator.GetValue(tesla, "DOB.Year")); // 1856 // "Idvor"

string city = (string) ExpressionEvaluator.GetValue(pupin, "PlaCeOfBirTh.CiTy");

For the sharp-eyed, that isn't a typo in the property name for place of birth. The expression uses mixed cases to demonstrate that the evaluation is case insensitive. The contents of arrays and lists are obtained using square bracket notation.
// Inventions Array string invention = (string) ExpressionEvaluator.GetValue(tesla, "Inventions[3]"); // "Induction motor" // Members List string name = (string) ExpressionEvaluator.GetValue(ieee, "Members[0].Name"); // "Nikola Tesla" // List and Array navigation string invention = (string) ExpressionEvaluator.GetValue(ieee, "Members[0].Inventions[6]") // "Wireless communication"

The contents of dictionaries are obtained by specifying the literal key value within the brackets. In this case, because keys for the Officers dictionary are strings, we can specify string literal.
// Officer's Dictionary Inventor pupin = (Inventor) ExpressionEvaluator.GetValue(ieee, "Officers['president']"; string city = (string) ExpressionEvaluator.GetValue(ieee, "Officers['president'].PlaceOfBirth.City"); // "Idvor" ExpressionEvaluator.SetValue(ieee, "Officers['advisors'][0].PlaceOfBirth.Country", "Croatia");

You may also specify non literal values in place of the quoted literal values by using another expression inside the square brackets such as variable names or static properties/methods on other types. These features are discussed in other sections. Indexers are similarly referenced using square brackets. The following is a small example that shows the use of indexers. Multidimensional indexers are also supported.
public class Bar { private int[] numbers = new int[] {1, 2, 3}; public int this[int index] { get { return numbers[index];} set { numbers[index] = value; }

Spring Framework (Version 1.3.2)

105

Expression Evaluation
} } Bar b = new Bar(); int val = (int) ExpressionEvaluator.GetValue(bar, "[1]") // evaluated to 2 ExpressionEvaluator.SetValue(bar, "[1]", 3); // set value to 3

11.3.2.1. Defining Arrays, Lists and Dictionaries Inline In addition to accessing arrays, lists and dictionaries by navigating the graph for the context object, Spring.NET Expression Language allows you to define them inline, within the expression. Inline lists are defined by simply enclosing a comma separated list of items with curly brackets:
{1, 2, 3, 4, 5} {'abc', 'xyz'}

If you want to ensure that a strongly typed array is initialized instead of a weakly typed list, you can use array initializer instead:
new int[] {1, 2, 3, 4, 5} new string[] {'abc', 'xyz'}

Dictionary definition syntax is a bit different: you need to use a # prefix to tell expression parser to expect key/ value pairs within the brackets and to specify a comma separated list of key/value pairs within the brackets:
#{'key1' : 'Value 1', 'today' : DateTime.Today} #{1 : 'January', 2 : 'February', 3 : 'March', ...}

Arrays, lists and dictionaries created this way can be used anywhere where arrays, lists and dictionaries obtained from the object graph can be used, which we will see later in the examples. Keep in mind that even though examples above use literals as array/list elements and dictionary keys and values, that's only to simplify the examples -- you can use any valid expression wherever literals are used.

11.3.3. Methods
Methods are invoked using typical C# programming syntax. You may also invoke methods on literals.
//string literal char[] chars = (char[]) ExpressionEvaluator.GetValue(null, "'test'.ToCharArray(1, 2)")) // 't','e'

//date literal int year = (int) ExpressionEvaluator.GetValue(null, "date('1974/08/24').AddYears(31).Year") // 2005 // object usage, calculate age of tesla navigating from the IEEE society. ExpressionEvaluator.GetValue(ieee, "Members[0].GetAge(date('2005-01-01')") // 149 (eww..a big anniversary is coming up ;)

11.3.4. Operators
11.3.4.1. Relational operators The relational operators; equal, not equal, less than, less than or equal, greater than, and greater than or equal are supported using standard operator notation. These operators take into account if the object implements the IComparable interface. Enumerations are also supported but you will need to register the enumeration type, as described in Section Section 11.3.8, Type Registration, in order to use an enumeration value in an expression if it is not contained in the mscorlib.

Spring Framework (Version 1.3.2)

106

Expression Evaluation
ExpressionEvaluator.GetValue(null, "2 == 2") // true // true

ExpressionEvaluator.GetValue(null, "date('1974-08-24') != DateTime.Today") ExpressionEvaluator.GetValue(null, "2 < -5.0") // false

ExpressionEvaluator.GetValue(null, "DateTime.Today <= date('1974-08-24')") // false ExpressionEvaluator.GetValue(null, "'Test' >= 'test'") // true

Enumerations can be evaluated as shown below


FooColor fColor = new FooColor(); ExpressionEvaluator.SetValue(fColor, "Color", KnownColor.Blue); bool trueValue = (bool) ExpressionEvaluator.GetValue(fColor, "Color == KnownColor.Blue"); //true

Where FooColor is the following class.


public class FooColor { private KnownColor knownColor; public KnownColor Color { get { return knownColor;} set { knownColor = value; } } }

In addition to standard relational operators, Spring.NET Expression Language supports some additional, very useful operators that were "borrowed" from SQL, such as in, like and between, as well as is and matches operators, which allow you to test if object is of a specific type or if the value matches a regular expression.
ExpressionEvaluator.GetValue(null, "3 in {1, 2, 3, 4, 5}") ExpressionEvaluator.GetValue(null, "'Abc' like '[A-Z]b*'") ExpressionEvaluator.GetValue(null, "'Abc' like '?'") ExpressionEvaluator.GetValue(null, "1 between {1, 5}") // true // true

// false // true // true

ExpressionEvaluator.GetValue(null, "'efg' between {'abc', 'xyz'}") ExpressionEvaluator.GetValue(null, "'xyz' is int") // false

ExpressionEvaluator.GetValue(null, "{1, 2, 3, 4, 5} is IList")

// true // false

ExpressionEvaluator.GetValue(null, "'5.0067' matches '^-?\\d+(\\.\\d{2})?$'")) ExpressionEvaluator.GetValue(null, @"'5.00' matches '^-?\d+(\.\d{2})?$'")

// true

Note that the Visual Basic and not SQL syntax is used for the like operator pattern string. 11.3.4.2. Logical operators The logical operators that are supported are and, or, and not. Their use is demonstrated below
// AND bool falseValue = (bool) ExpressionEvaluator.GetValue(null, "true and false"); //false string expression = @"IsMember('Nikola Tesla') and IsMember('Mihajlo Pupin')"; bool trueValue = (bool) ExpressionEvaluator.GetValue(ieee, expression); //true // OR bool trueValue = (bool) ExpressionEvaluator.GetValue(null, "true or false");

//true

string expression = @"IsMember('Nikola Tesla') or IsMember('Albert Einstien')";

Spring Framework (Version 1.3.2)

107

Expression Evaluation
bool trueValue = (bool) ExpressionEvaluator.GetValue(ieee, expression); // true // NOT bool falseValue = (bool) ExpressionEvaluator.GetValue(null, "!true"); // AND and NOT string expression = @"IsMember('Nikola Tesla') and !IsMember('Mihajlo Pupin')"; bool falseValue = (bool) ExpressionEvaluator.GetValue(ieee, expression);

11.3.4.3. Bitwise operators The bitwise operators that are supported are and, or, xor and not. Their use is demonstrated below. Note, that the logical and bitwise operators are the same and their interpretation depends if you pass in integral values or boolean values.
// AND int result = (int) ExpressionEvaluator.GetValue(null, "1 and 3"); // 1 & 3 // OR int result = (int) ExpressionEvaluator.GetValue(null, "1 or 3"); // XOR int result = (int) ExpressionEvaluator.GetValue(null, "1 xor 3"); // NOT int result = (int) ExpressionEvaluator.GetValue(null, "!1"); // ~1

// 1 | 3

// 1 ^ 3

11.3.4.4. Mathematical operators The addition operator can be used on numbers, strings and dates. Subtraction can be used on numbers and dates. Multiplication and division can be used only on numbers. Other mathematical operators supported are modulus (%) and exponential power (^). Standard operator precedence is enforced. These operators are demonstrated below
// Addition int two = (int)ExpressionEvaluator.GetValue(null, "1 + 1"); // 2 String testString = (String)ExpressionEvaluator.GetValue(null, "'test' + ' ' + 'string'"); //'test string' DateTime dt = (DateTime)ExpressionEvaluator.GetValue(null, "date('1974-08-24') + 5"); // 8/29/1974 // Subtraction int four = (int) ExpressionEvaluator.GetValue(null, "1 - -3"); //4 Decimal dec = (Decimal) ExpressionEvaluator.GetValue(null, "1000.00m - 1e4"); // 9000.00 TimeSpan ts = (TimeSpan) ExpressionEvaluator.GetValue(null, "date('2004-08-14') date('1974-08-24')"); //10948.00:00:00 // Multiplication int six = (int) ExpressionEvaluator.GetValue(null, "-2 * -3"); // 6 int twentyFour = (int) ExpressionEvaluator.GetValue(null, "2.0 * 3e0 * 4"); // 24 // Division int minusTwo = (int) ExpressionEvaluator.GetValue(null, "6 / -3"); // -2 int one = (int) ExpressionEvaluator.GetValue(null, "8.0 / 4e0 / 2"); // 1 // Modulus int three = (int) ExpressionEvaluator.GetValue(null, "7 % 4"); // 3 int one = (int) ExpressionEvaluator.GetValue(null, "8.0 % 5e0 % 2"); // 1 // Exponent

Spring Framework (Version 1.3.2)

108

Expression Evaluation
int sixteen = (int) ExpressionEvaluator.GetValue(null, "-2 ^ 4"); // 16 // Operator precedence int minusFortyFive = (int) ExpressionEvaluator.GetValue(null, "1+2-3*8^2/2/2"); // -45

11.3.5. Assignment
Setting of a property is done by using the assignment operator. This would typically be done within a call to GetValue since in the simple case SetValue offers the same functionality. Assignment in this manner is useful when combining multiple operators in an expression list, discussed in the next section. Some examples of assignment are shown below
Inventor inventor = new Inventor(); String aleks = (String) ExpressionEvaluator.GetValue(inventor, "Name = 'Aleksandar Seovic'"); DateTime dt = (DateTime) ExpressionEvaluator.GetValue(inventor, "DOB = date('1974-08-24')"); //Set the vice president of the society Inventor tesla = (Inventor) ExpressionEvaluator.GetValue(ieee, "Officers['vp'] = Members[0]");

11.3.6. Expression lists


Multiple expressions can be evaluated against the same context object by separating them with a semicolon and enclosing the entire expression within parentheses. The value returned is the value of the last expression in the list. Examples of this are shown below
//Perform property assignments and then return Name property. String pupin = (String) ExpressionEvaluator.GetValue(ieee.Members, "( [1].PlaceOfBirth.City = 'Beograd'; [1].PlaceOfBirth.Country = 'Serbia'; [1].Name )")); // pupin = "Mihajlo Pupin"

11.3.7. Types
In many cases, you can reference types by simply specifying type name:
ExpressionEvaluator.GetValue(null, "1 is int") ExpressionEvaluator.GetValue(null, "DateTime.Today") ExpressionEvaluator.GetValue(null, "new string[] {'abc', 'efg'}")

This is possible for all standard types from mscorlib, as well as for any other type that is registered with the TypeRegistry as described in the next section. For all other types, you need to use special T(typeName) expression:
Type dateType = (Type) ExpressionEvaluator.GetValue(null, "T(System.DateTime)") Type evalType = (Type) ExpressionEvaluator.GetValue(null, "T(Spring.Expressions.ExpressionEvaluator, Spring.Core)") bool trueValue = (bool) ExpressionEvaluator.GetValue(tesla, "T(System.DateTime) == DOB.GetType()")

Note
The implementation delegates to Spring's ObjectUtils.ResolveType method for the actual type resolution, which means that the types used within expressions are resolved in the exactly the same way as the types specified in Spring configuration files.

Spring Framework (Version 1.3.2)

109

Expression Evaluation

11.3.8. Type Registration


To refer to a type within an expression that is not in the mscorlib you need to register it with the TypeRegistry. This will allow you to refer to a shorthand name of the type within your expressions. This is commonly used in expression that use the new operator or refer to a static properties of an object. Example usage is shown below.
TypeRegistry.RegisterType("Society", typeof(Society)); Inventor pupin = (Inventor) ExpressionEvaluator.GetValue(ieee, "Officers[Society.President]");

Alternatively, you can register types using typeAliases configuration section.

11.3.9. Constructors
Constructors can be invoked using the new operator. For classes outside mscorlib you will need to register your types so they can be resolved. Examples of using constructors are shown below:
// simple ctor DateTime dt = (DateTime) ExpressionEvaluator.GetValue(null, "new DateTime(1974, 8, 24)"); // Register Inventor type then create new inventor instance within Add method inside an expression list. // Then return the new count of the Members collection. TypeRegistry.RegisterType(typeof(Inventor)); int three = (int) ExpressionEvaluator.GetValue(ieee.Members, "{ Add(new Inventor('Aleksandar Seovic', date('1974-08-24'), 'Serbian')); Count}"));

As a convenience, Spring.NET also allows you to define named constructor arguments, which are used to set object's properties after instantiation, similar to the way standard .NET attributes work. For example, you could create an instance of the Inventor class and set its Inventions property in a single statement:
Inventor aleks = (Inventor) ExpressionEvaluator.GetValue(null, "new Inventor('Aleksandar Seovic', date('1974-08-24'), 'Serbian', Inventions = {'SPELL'})");

The only rule you have to follow is that named arguments should be specified after standard constructor arguments, just like in the .NET attributes. While we are on the subject, Spring.NET Expression Language also provides a convenient syntax for .NET attribute instance creation. Instead of using standard constructor syntax, you can use a somewhat shorter and more familiar syntax to create an instance of a .NET attribute class:
WebMethodAttribute webMethod = (WebMethodAttribute) ExpressionEvaluator.GetValue(null, "@[WebMethod(true, CacheDuration = 60, Description = 'My Web Method')]");

As you can see, with the exception of the @ prefix, syntax is exactly the same as in C#. Slightly different syntax is not the only thing that differentiates an attribute expression from a standard constructor invocation expression. In addition to that, attribute expression uses slightly different type resolution mechanism and will attempt to load both the specified type name and the specified type name with an Attribute suffix, just like the C# compiler.

11.3.10. Variables
Variables can referenced in the expression using the syntax #variableName. The variables are passed in and out of the expression using the dictionary parameter in ExpressionEvaluator's GetValue or SetValue methods.
public static object GetValue(object root, string expression, IDictionary variables)

Spring Framework (Version 1.3.2)

110

Expression Evaluation

public static void SetValue(object root, string expression, IDictionary variables, object newValue)

The variable name is the key value of the dictionary. Example usage is shown below;
IDictionary vars = new Hashtable(); vars["newName"] = "Mike Tesla"; ExpressionEvaluator.GetValue(tesla, "Name = #newName", vars));

You can also use the dictionary as a place to store values of the object as they are evaluated inside the expression. For example to change Tesla's first name back again and keep the old value;
ExpressionEvaluator.GetValue(tesla, "{ #oldName = Name; Name = 'Nikola Tesla' }", vars); String oldName = (String)vars["oldName"]; // Mike Tesla

Variable names can also be used inside indexers or maps instead of literal values. For example;
vars["prez"] = "president"; Inventor pupin = (Inventor) ExpressionEvaluator.GetValue(ieee, "Officers[#prez]", vars);

11.3.10.1. The '#this' and '#root' variables There are two special variables that are always defined and can be references within the expression: #this and #root. The #this variable can be used to explicitly refer to the context for the node that is currently being evaluated:
// sets the name of the president and returns its instance ExpressionEvaluator.GetValue(ieee, "Officers['president'].( #this.Name = 'Nikola Tesla'; #this )")

Similarly, the #root variable allows you to refer to the root context for the expression:
// removes president from the Officers dictionary and returns removed instance ExpressionEvaluator.GetValue(ieee, "Officers['president'].( #root.Officers.Remove('president'); #this )")

11.3.11. Ternary Operator (If-Then-Else)


You can use the ternary operator for performing if-then-else conditional logic inside the expression. A minimal example is;
String aTrueString = (String) ExpressionEvaluator.GetValue(null, "false ? 'trueExp' : 'falseExp'") // trueExp

In this case, the boolean false results in returning the string value 'trueExp'. A less artificial example is shown below
ExpressionEvaluator.SetValue(ieee, "Name", "IEEE"); IDictionary vars = new Hashtable(); vars["queryName"] = "Nikola Tesla"; string expression = @"IsMember(#queryName) ? #queryName + ' is a member of the ' + Name + ' Society' : #queryName + ' is not a member of the ' + Name + ' Society'"; String queryResultString = (String) ExpressionEvaluator.GetValue(ieee, expression, vars)); // queryResultString = "Nikola Tesla is a member of the IEEE Society"

11.3.12. List Projection and Selection


List projection and selection are very powerful expression language features that allow you to transform the source list into another list by either projecting across its "columns", or selecting from its "rows". In other words, projection can be thought of as a column selector in a SQL SELECT statement, while selection would be comparable to the WHERE clause.

Spring Framework (Version 1.3.2)

111

Expression Evaluation For example, let's say that we need a list of the cities where our inventors were born. This could be easily obtained by projecting on the PlaceOfBirth.City property:
IList placesOfBirth = (IList) ExpressionEvaluator.GetValue(ieee, "Members.!{PlaceOfBirth.City}") { 'Smiljan', 'Idvor' } //

Or we can get the list of officers' names:


IList officersNames = (IList) ExpressionEvaluator.GetValue(ieee, "Officers.Values.!{Name}") Tesla', 'Mihajlo Pupin' } // { 'Nikola

As you can see from the examples, projection uses !{projectionExpression} syntax and will return a new list of the same length as the original list but typically with the elements of a different type. On the other hand, selection, which uses ?{projectionExpression} syntax, will filter the list and return a new list containing a subset of the original element list. For example, selection would allow us to easily get a list of Serbian inventors:
IList serbianInventors = (IList) ExpressionEvaluator.GetValue(ieee, "Members.?{Nationality == 'Serbian'}") { tesla, pupin } //

Or to get a list of inventors that invented sonar:


IList sonarInventors = (IList) ExpressionEvaluator.GetValue(ieee, "Members.?{'Sonar' in Inventions}") { pupin } //

Or we can combine selection and projection to get a list of sonar inventors' names:
IList sonarInventorsNames = (IList) ExpressionEvaluator.GetValue(ieee, "Members.?{'Sonar' in Inventions}.! {Name}") // { 'Mihajlo Pupin' }

As a convenience, Spring.NET Expression Language also supports a special syntax for selecting the first or last match. Unlike regular selection, which will return an empty list if no matches are found, first or last match selection expression will either return an instance of the matched element, or null if no matching elements were found. In order to return a first match you should prefix your selection expression with ^{ instead of ?{, and to return last match you should use ${ prefix:
ExpressionEvaluator.GetValue(ieee, "Members.^{Nationality == 'Serbian'}.Name") ExpressionEvaluator.GetValue(ieee, "Members.${Nationality == 'Serbian'}.Name") // 'Nikola Tesla' // 'Mihajlo Pupin'

Notice that we access the Name property directly on the selection result, because an actual matched instance is returned by the first and last match expression instead of a filtered list.

11.3.13. Collection Processors and Aggregators


In addition to list projection and selection, Spring.NET Expression Language also supports several collection processors, such as distinct, nonNull and sort, as well as a number of commonly used aggregators, such as max, min, count, sum and average. The difference between processors and aggregators is that processors return a new or transformed collection, while aggregators return a single value. Other than that, they are very similar -- both processors and aggregators are invoked on a collection node using standard method invocation expression syntax, which makes them very simple to use and allows easy chaining of multiple processors. 11.3.13.1. Count Aggregator The count aggregator is a safe way to obtain a number of items in a collection. It can be applied to a collection of any type, including arrays, which helps eliminate the decision on whether to use Count or Length property depending on the context. Unlike its standard .NET counterparts, count aggregator can also be invoked on the

Spring Framework (Version 1.3.2)

112

Expression Evaluation context without throwing a NullReferenceException. It will simply return zero in this case, which makes it much safer than standard .NET properties within larger expression.
null
ExpressionEvaluator.GetValue(null, "{1, 5, -3}.count()") ExpressionEvaluator.GetValue(null, "count()") // 0 // 3

11.3.13.2. Sum Aggregator The sum aggregator can be used to calculate a total for the list of numeric values. If numbers within the list are not of the same type or precision, it will automatically perform necessary conversion and the result will be the highest precision type. If any of the collection elements is not a number, this aggregator will throw an InvalidArgumentException.
ExpressionEvaluator.GetValue(null, "{1, 5, -3, 10}.sum()") // 13 (int) ExpressionEvaluator.GetValue(null, "{5, 5.8, 12.2, 1}.sum()") // 24.0 (double)

11.3.13.3. Average Aggregator The average aggregator will return the average for the collection of numbers. It will use the same type coercion rules, as the sum aggregator in order to be as precise as possible. Just like the sum aggregator, if any of the collection elements is not a number, it will throw an InvalidArgumentException.
ExpressionEvaluator.GetValue(null, "{1, 5, -4, 10}.average()") ExpressionEvaluator.GetValue(null, "{1, 5, -2, 10}.average()") // 3 // 3.5

11.3.13.4. Minimum Aggregator The minimum aggregator will return the smallest item in the list. In order to determine what "the smallest" actually means, this aggregator relies on the assumption that the collection items are of the uniform type and that they implement the IComparable interface. If that is not the case, this aggregator will throw an InvalidArgumentException.
ExpressionEvaluator.GetValue(null, "{1, 5, -3, 10}.min()") // -3 ExpressionEvaluator.GetValue(null, "{'abc', 'efg', 'xyz'}.min()") // 'abc'

11.3.13.5. Maximum Aggregator The maximum aggregator will return the largest item in the list. In order to determine what "the largest" actually means, this aggregator relies on the assumption that the collection items are of the uniform type and that they implement IComparable interface. If that is not the case, this aggregator will throw an InvalidArgumentException.
ExpressionEvaluator.GetValue(null, "{1, 5, -3, 10}.max()") // 10 ExpressionEvaluator.GetValue(null, "{'abc', 'efg', 'xyz'}.max()") // 'xyz'

11.3.13.6. Non-null Processor A non-null processor is a very simple collection processor that eliminates all null values from the collection.
ExpressionEvaluator.GetValue(null, "{ 'abc', 'xyz', null, 'abc', 'def', null}.nonNull()") // { 'abc', 'xyz', 'abc', 'def' } ExpressionEvaluator.GetValue(null, "{ 'abc', 'xyz', null, 'abc', 'def', null}.nonNull().distinct().sort()") // { 'abc', 'def', 'xyz' }

11.3.13.7. Distinct Processor A distinct processor is very useful when you want to ensure that you don't have duplicate items in the collection. It can also accept an optional Boolean argument that will determine whether null values should be included in the results. The default is false, which means that they will not be included.

Spring Framework (Version 1.3.2)

113

Expression Evaluation
ExpressionEvaluator.GetValue(null, "{ 'abc', 'xyz', 'abc', 'def', null, 'def' }.distinct(true).sort()") // { null, 'abc', 'def', 'xyz' } ExpressionEvaluator.GetValue(null, "{ 'abc', 'xyz', 'abc', 'def', null, 'def' }.distinct(false).sort()") // { 'abc', 'def', 'xyz' }

11.3.13.8. Sort Processor The sort processor can be used to sort uniform collections of elements that implement IComparable.
ExpressionEvaluator.GetValue(null, "{1.2, 5.5, -3.3}.sort()") // { -3.3, 1.2, 5.5 } ExpressionEvaluator.GetValue(null, "{ 'abc', 'xyz', 'abc', 'def', null, 'def' }.sort()") 'abc', 'def', 'def', 'xyz' } // { null, 'abc',

The sort processor also accepts a boolean value as an argument to determine sort order, sort(false) will sort the collection in decending order. 11.3.13.9. Type Conversion Processor The convert processor can be used to convert a collection of elements to a given Type.
object[] arr = new object[] { "0", 1, 1.1m, "1.1", 1.1f }; decimal[] result = (decimal[]) ExpressionEvaluator.GetValue(arr, "convert(decimal)");

11.3.13.10. Reverse Processor The reverse processor returns the reverse order of elements in the list
object[] arr = new object[] { "0", 1, 2.1m, "3", 4.1f }; object[] result = new ArrayList( (ICollection) ExpressionEvaluator.GetValue(arr, "reverse()") ).ToArray(); // { 4.1f, "3", 2.1m, 1, "0" }

11.3.13.11. OrderBy Processor Collections can be ordered in three ways, an expression, a SpEL lamda expreression, or a delegate.
// orderBy expression IExpression exp = Expression.Parse("orderBy('ToString()')"); object[] input = new object[] { 'b', 1, 2.0, "a" }; object[] ordered = exp.GetValue(input); // { 1, 2.0, "a", 'b' }

// SpEL lambda expressions IExpression exp = Expression.Parse("orderBy({|a,b| $a.ToString().CompareTo($b.ToString())})"); object[] input = new object[] { 'b', 1, 2.0, "a" }; object[] ordered = exp.GetValue(input); // { 1, 2.0, "a", 'b' } Hashtable vars = new Hashtable(); Expression.RegisterFunction( "compare", "{|a,b| $a.ToString().CompareTo($b.ToString())}", vars); exp = Expression.Parse("orderBy(#compare)"); ordered = exp.GetValue(input, vars); // { 1, 2.0, "a", 'b' } // .NET delegate private delegate int CompareCallback(object x, object y); private int CompareObjects(object x, object y) { if (x == y) return 0; return x.ToString().CompareTo(""+y); } Hashtable vars = new Hashtable(); vars["compare"] = new CompareCallback(CompareObjects); IExpression exp = Expression.Parse("orderBy(#compare)"); object[] input = new object[] { 'b', 1, 2.0, "a" }; object[] ordered = exp.GetValue(input); // { 1, 2.0, "a", 'b' }

Spring Framework (Version 1.3.2)

114

Expression Evaluation 11.3.13.12. User Defined Collection Processor You can register your own collection processor for use in evaluation a collection. Here is an example of a ICollectionProcessor implementation that sums only the even numbers of an integer list
public class IntEvenSumCollectionProcessor : ICollectionProcessor { public object Process(ICollection source, object[] args) { object total = 0d; foreach (object item in source) { if (item != null) { if (NumberUtils.IsInteger(item)) { if ((int)item % 2 == 0) { total = NumberUtils.Add(total, item); } } else { throw new ArgumentException("Sum can only be calculated for a collection of numeric values."); } } } return total; } }

public void DoWork() { Hashtable vars = new Hashtable(); vars["EvenSum"] = new IntEvenSumCollectionProcessor(); int result = (int)ExpressionEvaluator.GetValue(null, "{1, 2, 3, 4}.EvenSum()", vars)); }

// 6

11.3.14. Spring Object References


Expressions can refer to objects that are declared in Spring's application context using the syntax @(contextName:objectName). If no contextName is specified the default root context name (Spring.RootContext) is used. Using the application context defined in the MovieFinder example from Chapter 37, IoC Quickstarts, the following expression returns the number of movies directed by Roberto Benigni.
public static void Main() { . . . // Retrieve context defined in the spring/context section of // the standard .NET configuration file. IApplicationContext ctx = ContextRegistry.GetContext(); int numMovies = (int) ExpressionEvaluator.GetValue(null, "@(MyMovieLister).MoviesDirectedBy('Roberto Benigni').Length"); . . . }

The variable numMovies is evaluated to 2 in this example.

Spring Framework (Version 1.3.2)

115

Expression Evaluation

11.3.15. Lambda Expressions


A somewhat advanced, but a very powerful feature of Spring.NET Expression Language are lambda expressions. Lambda expressions allow you to define inline functions, which can then be used within your expressions just like any other function or method. You may also use .NET delegates as described in the next section. The syntax for defining lambda expressions is:
#functionName = {|argList|

functionBody }

For example, you could define a max function and call it like this:
ExpressionEvaluator.GetValue(null, "(#max = {|x,y| $x > $y ? $x : $y }; #max(5,25))", new Hashtable()) // 25

As you can see, any arguments defined for the expression can be referenced within the function body using a local variable syntax, $varName. Invocation of the function defined using lambda expression is as simple as specifying the comma-separated list of function arguments in parentheses, after the function name. Lambda expressions can be recursive, which means that you can invoke the function within its own body:
ExpressionEvaluator.GetValue(null, "(#fact = {|n| $n <= 1 ? 1 : $n * #fact($n-1) }; #fact(5))", new Hashtable()) // 120

Notice that in both examples above we had to specify a variables parameter for the GetValue method. This is because lambda expressions are actually nothing more than parameterized variables and we need variables dictionary in order to store them. If you don't specify a valid IDictionary instance for the variables parameter, you will get a runtime exception. Also, in both examples above we used an expression list in order to define and invoke a function in a single expression. However, more likely than not, you will want to define your functions once and then use them within as many expressions as you need. Spring.NET provides an easy way to pre-register your lambda expressions by exposing a static Expression.RegisterFunction method, which takes function name, lambda expression and variables dictionary to register function in as parameters:
IDictionary vars = new Hashtable(); Expression.RegisterFunction("sqrt", "{|n| Math.Sqrt($n)}", vars); Expression.RegisterFunction("fact", "{|n| $n <= 1 ? 1 : $n * #fact($n-1)}", vars);

Once the function registration is done, you can simply evaluate an expression that uses these functions, making sure that the vars dictionary is passed as a parameter to expression evaluation engine:
ExpressionEvaluator.GetValue(null, "#fact(5)", vars) ExpressionEvaluator.GetValue(null, "#sqrt(9)", vars) // 120 // 3

Finally, because lambda expressions are treated as variables, they can be assigned to other variables or passed as parameters to other lambda expressions. In the following example we are defining a delegate function that accepts function f as the first argument and parameter n that will be passed to function f as the second. Then we invoke the functions registered in the previous example, as well as the lambda expression defined inline, through our delegate:
Expression.RegisterFunction("delegate", "{|f, n| $f($n) }", vars); ExpressionEvaluator.GetValue(null, "#delegate(#sqrt, 4)", vars) // 2 ExpressionEvaluator.GetValue(null, "#delegate(#fact, 5)", vars) // 120 ExpressionEvaluator.GetValue(null, "#delegate({|n| $n ^ 2 }, 5)", vars)

// 25

While this particular example is not particularly useful, it does demonstrate that lambda expressions are indeed treated as nothing more than parameterized variables, which is important to remember.

Spring Framework (Version 1.3.2)

116

Expression Evaluation

11.3.16. Delegate Expressions


Delegate expressions allow you to refer to .NET delegates which can then be used within your expressions just like any other function or method. For example, you can define a max delegate and call it like this
private delegate double DoubleFunctionTwoArgs(double arg1, double arg2); private double Max(double arg1, double arg2) { return Math.Max(arg1, arg2); }

public void DoWork() { Hashtable vars = new Hashtable(); vars["max"] = new DoubleFunctionTwoArgs(Max); double result = (double) ExpressionEvaluator.GetValue(null, "#max(5,25)", vars); }

// 25

11.3.17. Null Context


If you do not specify a root object, i.e. pass in null, then the expressions evaluated either have to be literal values, i.e. ExpressionEvaluator.GetValue(null, "2 + 3.14"), refer to classes that have static methods or properties, i.e. ExpressionEvaluator.GetValue(null, "DateTime.Today"), create new instances of objects, i.e. ExpressionEvaluator.GetValue(null, "new DateTime(2004, 8, 14)") or refer to other objects such as those in the variable dictionary or in the IoC container. The latter two usages will be discussed later.

11.4. Classes used in the examples


The following simple classes are used to demonstrate the functionality of the expression language.
public class Inventor { public string Name; public string Nationality; public string[] Inventions; private DateTime dob; private Place pob; public Inventor() : this(null, DateTime.MinValue, null) {} public Inventor(string name, DateTime dateOfBirth, string nationality) { this.Name = name; this.dob = dateOfBirth; this.Nationality = nationality; this.pob = new Place(); } public DateTime DOB { get { return dob; } set { dob = value; } } public Place PlaceOfBirth { get { return pob; } } public int GetAge(DateTime on) {

Spring Framework (Version 1.3.2)

117

Expression Evaluation
// not very accurate, but it will do the job ;-) return on.Year - dob.Year; } } public class Place { public string City; public string Country; } public class Society { public string Name; public static string Advisors = "advisors"; public static string President = "president"; private IList members = new ArrayList(); private IDictionary officers = new Hashtable(); public IList Members { get { return members; } } public IDictionary Officers { get { return officers; } } public bool IsMember(string name) { bool found = false; foreach (Inventor inventor in members) { if (inventor.Name == name) { found = true; break; } } return found; } }

The code listings in this chapter use instances of the data populated with the following information.
Inventor tesla = new Inventor("Nikola Tesla", new DateTime(1856, 7, 9), "Serbian"); tesla.Inventions = new string[] { "Telephone repeater", "Rotating magnetic field principle", "Polyphase alternating-current system", "Induction motor", "Alternating-current power transmission", "Tesla coil transformer", "Wireless communication", "Radio", "Fluorescent lights" }; tesla.PlaceOfBirth.City = "Smiljan"; Inventor pupin = new Inventor("Mihajlo Pupin", new DateTime(1854, 10, 9), "Serbian"); pupin.Inventions = new string[] {"Long distance telephony & telegraphy", "Secondary X-Ray radiation", "Sonar"}; pupin.PlaceOfBirth.City = "Idvor"; pupin.PlaceOfBirth.Country = "Serbia"; Society ieee = new Society(); ieee.Members.Add(tesla); ieee.Members.Add(pupin); ieee.Officers["president"] = pupin; ieee.Officers["advisors"] = new Inventor[] {tesla, pupin};

Spring Framework (Version 1.3.2)

118

Chapter 12. Validation Framework


12.1. Introduction
Data validation is a very important part of any enterprise application. ASP.NET has a validation framework but it is very limited in scope and starts falling apart as soon as you need to perform more complex validations. Problems with the out of the box ASP.NET validation framework are well documented by Peter Blum on his web site, so we are not going to repeat them here. Peter has also built a nice replacement for the standard ASP.NET validation framework, which is worth looking into if you prefer the standard ASP.NET validation mechanism to the one offered by Spring.NET for some reason. Both frameworks will allow you to perform very complex validations but we designed the Spring.NET validation framework differently for the reasons described below. On the Windows Forms side the situation is even worse. Out of the box data validation features are completely inadequate as pointed out by Ian Griffiths in this article. One of the major problems we saw in most validation frameworks available today, both open source and commercial, is that they are tied to a specific presentation technology. The ASP.NET validation framework uses ASP.NET controls to define validation rules, so these rules end up in the HTML markup of your pages. Peter Blum's framework uses the same approach. In our opinion, validation is not applicable only to the presentation layer so there is no reason to tie it to any particular technology. As such, the Spring.NET Validation Framework is designed in a way that enables data validation in different application layers using the same validation rules. The goals of the validation framework are the following: 1. Allow for the validation of any object, whether it is a UI control or a domain object. 2. Allow the same validation framework to be used in both Windows Forms and ASP.NET applications, as well as in the service layer (to validate parameters passed to the service, for example). 3. Allow composition of the validation rules so arbitrarily complex validation rule sets can be constructed. 4. Allow validators to be conditional so they only execute if a specific condition is met. The following sections will describe in more detail how these goals were achieved and show you how to use the Spring.NET Validation Framework in your applications.

12.2. Example Usage


Decoupling validation from presentation was the major goal that significantly influenced design of the validation framework. We wanted to be able to define a set of validation rules that are completely independent from the presentation so we can reuse them (or at least have the ability to reuse them) in different application layers. This meant that the approach taken by Microsoft ASP.NET team would not work and custom validation controls were not an option. The approach taken was to configure validation rules just like any other object managed by Spring - within the application context. However, due to possible complexity of the validation rules we decided not to use the standard Spring.NET configuration schema for validator definitions but to instead provide a more specific and easier to use custom configuration schema for validation. Note that the validation framework is not tied to the use of XML, you can use its API Programatically. The following example shows validation rules defined for the Trip object in the SpringAir sample application:
<objects xmlns="http://www.springframework.net" xmlns:v="http://www.springframework.net/validation">

Spring Framework (Version 1.3.2)

119

Validation Framework

<object type="TripForm.aspx" parent="standardPage"> <property name="TripValidator" ref="tripValidator" /> </object> <v:group id="tripValidator"> <v:required id="departureAirportValidator" test="StartingFrom.AirportCode"> <v:message id="error.departureAirport.required" providers="departureAirportErrors, validationSummary"/ > </v:required> <v:group id="destinationAirportValidator"> <v:required test="ReturningFrom.AirportCode"> <v:message id="error.destinationAirport.required" providers="destinationAirportErrors, validationSummary"/> </v:required> <v:condition test="ReturningFrom.AirportCode != StartingFrom.AirportCode" when="ReturningFrom.AirportCode != ''"> <v:message id="error.destinationAirport.sameAsDeparture" providers="destinationAirportErrors, validationSummary"/> </v:condition> </v:group> <v:group id="departureDateValidator"> <v:required test="StartingFrom.Date"> <v:message id="error.departureDate.required" providers="departureDateErrors, validationSummary"/> </v:required> <v:condition test="StartingFrom.Date >= DateTime.Today" when="StartingFrom.Date != DateTime.MinValue"> <v:message id="error.departureDate.inThePast" providers="departureDateErrors, validationSummary"/> </v:condition> </v:group> <v:group id="returnDateValidator" when="Mode == 'RoundTrip'"> <v:required test="ReturningFrom.Date"> <v:message id="error.returnDate.required" providers="returnDateErrors, validationSummary"/> </v:required> <v:condition test="ReturningFrom.Date >= StartingFrom.Date" when="ReturningFrom.Date != DateTime.MinValue"> <v:message id="error.returnDate.beforeDeparture" providers="returnDateErrors, validationSummary"/> </v:condition> </v:group> </v:group> </objects>

There are a few things to note in the example above: You need to reference the validation schema by adding a xmlns:v="http://www.springframework.net/ validation" namespace declaration to the root element. You can mix standard object definitions and validator definitions in the same configuration file as long as both schemas are referenced. The Validator defined in the configuration file is identified by and id attribute and can be referenced in the standard Spring way, i.e. the injection of tripValidator into TripForm.aspx page definition in the first <object> tag above. The validation framework uses Spring's powerful expression evaluation engine to evaluate both validation rules and applicability conditions for the validator. As such, any valid Spring expression can be specified within the test and when attributes of any validator. The example above shows many of the features of the framework, so let's discuss them one by one in the following sections.

Spring Framework (Version 1.3.2)

120

Validation Framework

12.3. Validator Groups


Validators can be grouped together. This is important for many reasons but the most typical usage scenario is to group multiple validation rules that apply to the same value. In the example above there is a validator group for almost every property of the Trip instance. There is also a top-level group for the Trip object itself that groups all other validators. There are three types of validator groups each with a different behavior: While the first type (AND) is definitely the most useful, the other two allow you to implement some specific validation scenarios in a very simple way, so you should keep them in mind when designing your validation rules. Table 12.1. Validator Groups Type XML Tag AND group Behavior Returns true only if all contained validators return true. This is the most commonly used validator group. Returns true if one or more of the contained validators return true. Returns true if only one of the contained validators return true.

OR any XOR exclusive

One thing to remember is that a validator group is a validator like any other and can be used anywhere validator is expected. You can nest groups within other groups and reference them using validator reference syntax (described later), so they really allow you to structure your validation rules in the most reusable way.

12.4. Validators
Ultimately, you will have one or more validator definitions for each piece of data that you want to validate. Spring.NET has several built-in validators that are sufficient for most validations, even fairly complex ones. The framework is extensible so you can write your own custom validators and use them in the same way as the builtin ones.

12.4.1. Condition Validator


The condition validator evaluates any logical expression that is supported by Spring's evaluation engine. The syntax is
<v:condition id="id" test="testCondition" when="applicabilityCondition" parent="parentValidator"> actions </v:condition>

An example is shown below


<v:condition test="StartingFrom.Date >= DateTime.Today" when="StartingFrom.Date != DateTime.MinValue"> <v:message id="error.departureDate.inThePast" providers="departureDateErrors, validationSummary"/> </v:condition>

In this example the StartingFrom property of the Trip object is compared to see if it is later than the current date, i.e. DateTime but only when the date has been set (the initial value of StartingFrom.Date was set to DateTime.MinValue). The condition validator could be considered "the mother of all validators". You can use it to achieve almost anything that can be achieved by using other validator types, but in some cases the test expression might be very

Spring Framework (Version 1.3.2)

121

Validation Framework complex, which is why you should use more specific validator type if possible. However, condition validator is still your best bet if you need to check whether particular value belongs to a particular range, or perform a similar test, as those conditions are fairly easy to write.

Note
Keep in mind that Spring.NET Validation Framework typically works with domain objects. This is after data binding from the controls has been performed so that the object being validated is strongly typed. This means that you can easily compare numbers and dates without having to worry if the string representation is comparable.

12.4.2. Required Validator


This validator ensures that the specified test value is not empty. The syntax is
<v:required id="id" test="requiredValue" when="applicabilityCondition" parent="parentValidator"> actions </v:required>

An example is shown below


<v:required test="ReturningFrom.AirportCode"> <v:message id="error.destinationAirport.required" providers="destinationAirportErrors, validationSummary"/> </v:required>

The specific tests done to determine if the required value is set is listed below Table 12.2. Rules to determine if required value is valid System.Type System.Type System.String system.DateTime One of the number types. System.Char Any reference type other than System.String Test Type exists not null or an empty string

Not System.DateTime.MinValue and not system.DateTime.MaxV not zero Not System.Char.MinValue or whitespace. not null

Required validator is also one of the most commonly used ones, and it is much more powerful than the ASP.NET Required validator, because it works with many other data types other than strings. For example, it will allow you to validate DateTime instances (both MinValue and MaxValue return false), integer and decimal numbers, as well as any reference type, in which case it returns true for a non-null value and false for {{null}}s. The test attribute for the required validator will typically specify an expression that resolves to a property of a domain object, but it could be any valid expression that returns a value, including a method call.

12.4.3. Regular Expression Validator


The syntax is

Spring Framework (Version 1.3.2)

122

Validation Framework

<v:regex id="id" test="valueToEvaluate" expression="regularExpressionToMatch" when="applicabilityCondition" parent="parentVal <v:property name="Options" value="regexOptions"/> actions </v:regex>

An example is shown below


<v:regex test="ReturningFrom.AirportCode" expression="[A-Z][A-Z][A-Z]"> <v:message id="error.destinationAirport.threeCharacters" providers="destinationAirportErrors, validationSummary"/> </v:regex>

Regular expression validator is very useful when validating values that need to conform to some predefined format, such as telephone numbers, email addresses, URLs, etc.

Note
Note that current behavior limits the Regular Expression Validator to expressions to being full matches, i.e., ^(expression)$, thus limiting functionality. To not change this behavior in a point release, a property AllowPartialMatching has been added in 1.3.1 to support the correct behavior. This property will be removed for next major/minor version and implementation will be fixed to get the intented behavior.

12.4.4. Generic Validator


The syntax is
<v:validator id="id" test="requiredValue" when="applicabilityCondition" type="validatorType" parent="parentValidator"> actions </v:validator>

An example is shown below


<v:validator test="ReturningFrom.AirportCode" type="MyNamespace.MyAirportCodeValidator, MyAssembly"> <v:message id="error.destinationAirport.invalid" providers="destinationAirportErrors, validationSummary"/> </v:required>

Generic validator allows you to plug in your custom validator by specifying its type name. Custom validators are very simple to implement, because all you need to do is extend BaseValidator class and implement abstract bool Validate(object objectToValidate) method. Your implementation simply needs to return true if it determines that object is valid, or false otherwise

12.4.5. Conditional Validator Execution


As you can see from the examples above, each validator (and validator group) allows you to define its applicability condition by specifying a logical expression as the value of the when attribute. This feature is very useful and is one of the major deficiencies in the standard ASP.NET validation framework, because in many cases specific validators need to be turned on or off based on the values of the object being validated. For example, when validating a Trip object we need to validate return date only if the Trip.Mode property is set to the TripMode.RoundTrip enum value. In order to achieve that we created following validator definition:
<v:group id="returnDateValidator" when="Mode == 'RoundTrip'"> // nested validators </v:group>

Validators within this group will only be evaluated for round trips.

Spring Framework (Version 1.3.2)

123

Validation Framework

Note
You should also note that you can compare enums using the string value of the enumeration. You can also use fully qualified enum name, such as:
Mode == TripMode.RoundTrip

However, in this case you need to make sure that alias for the TripMode enum type is registered using Spring's standard type aliasing mechanism.

12.5. Validator Actions


Validation actions are executed every time the containing validator is executed. They allow you to do anything you want based on the result of the validation. By far the most common use of the validation action is to add validation error message to the errors collection, but theoretically you could do anything you want. Because adding validation error messages to the errors collection is such a common scenario, Spring.NET validation schema defines a separate XML tag for this type of validation action.

12.5.1. Error Message Action


The syntax is
<v:message id="messageId" providers="errorProviderList" when="messageApplicabilityCondition"> <v:param value="paramExpression"/> </v:message>

An example is shown below


<v:message id="error.departureDate.inThePast" providers="departureDateErrors, validationSummary"> <v:param value="StartingFrom.Date.ToString('D')"/> <v:param value="DateTime.Today.ToString('D')"/> </v:message>

There are several things that you have to be aware of when dealing with error messages: id is used to look up the error message in the appropriate Spring.NET message source. providers specifies a comma separated list of "error buckets" particular error message should be added to. These "buckets" will later be used by the particular presentation technology in order to display error messages as necessary. a message can have zero or more parameters. Each parameter is an expression that will be resolved using current validation context and the resolved values will be passed as parameters to IMessageSource.GetMessage method, which will return the fully resolved message.

12.5.2. Exception Action


If you would like an exception to be thrown when validation fails use the exception action.
<v:exception/>

This will throw an exception of the type ValidationException and you can access error information via its ValidationErrors property. To throw your own custom exception, provide a SpEL fragment that instantiates the custom exception.

Spring Framework (Version 1.3.2)

124

Validation Framework
<v:exception throw='new System.InvalidOperationException("invalid")'/>

12.5.3. Generic Actions


The syntax is
<v:action type="actionType" when="actionApplicabilityCondition"> properties </v:action>

An example is shown below


<v:action type="Spring.Validation.Actions.ExpressionAction, Spring.Core" when="#page != null"> <v:property name="Valid" value="#page.myPanel.Visible = true"/> <v:property name="Invalid" value="#page.myPanel.Visible = false"/> </v:action>

Generic actions can be used to perform all kinds of validation actions. In simple cases, such as in the example above where we turn control's visibility on or off depending on the validation result, you can use the built-in ExpressionAction class and simply specify expressions to be evaluated based on the validator result. In other situations you may want to create your own action implementation, which is fairly simple thing to do all you need to do is implement IValidationAction interface:
public interface IValidationAction { /// <summary> /// Executes the action. /// </summary> /// <param name="isValid">Whether associated validator is valid or not.</param> /// <param name="validationContext">Validation context.</param> /// <param name="contextParams">Additional context parameters.</param> /// <param name="errors">Validation errors container.</param> void Execute(bool isValid, object validationContext, IDictionary contextParams, ValidationErrors errors); }

12.6. Validator References


Sometimes it is not possible (or desirable) to nest all the validation rules within a single top-level validator group. For example, if you have an object graph where both ObjectA and ObjectB have a reference to ObjectC, you might want to set up validation rules for ObjectC only once and reference them from the validation rules for both ObjectA and ObjectB, instead of duplicating them within both definitions. The syntax is shown below
<v:ref name="referencedValidatorId" context="validationContextForTheReferencedValidator"/>

An example is shown below


<v:group id="objectA.validator"> <v:ref name="objectC.validator" context="MyObjectC"/> // other validators for ObjectA </v:group> <v:group id="objectB.validator"> <v:ref name="objectC.validator" context="ObjectCProperty"/> // other validators for ObjectB </v:group> <v:group id="objectC.Validator"> // validators for ObjectC </v:group>

Spring Framework (Version 1.3.2)

125

Validation Framework It is as simple as that you define validation rules for ObjectC separately and reference them from within other validation groups. Important thing to realize that in most cases you will also want to "narrow" the context for the referenced validator, typically by specifying the name of the property that holds referenced object. In the example above, ObjectA.MyObjectC and ObjectB.ObjectCProperty are both of type ObjectC, which objectC.validator expects to receive as the validation context.

12.7. Progammatic usage


You can also create Validators programmatically using the API. An example is shown below
UserInfo userInfo = new UserInfo(); // has Name and Password props

ValidatorGroup userInfoValidator = new ValidatorGroup(); userInfoValidator.Validators .Add(new RequiredValidator("Name", null)); userInfoValidator.Validators .Add(new RequiredValidator("Password", null)); ValidationErrors errors = new ValidationErrors(); bool userInfoIsValid = userInfoValidator.Validate(userInfo, errors);

No matter if you create your validators programmatically or declaratively, you can invoke them in service side code via the 'Validate' method shown above and then handle error conditions. Spring provides AOP parameter validation advice as part of ithe aspect library which may also be useful for performing server-side validation.

12.8. Usage tips within ASP.NET


Now that you know how to configure validation rules, let's see what it takes to evaluate those rules within your typical ASP.NET application and to display error messages. The first thing you need to do is inject validators you want to use into your ASP.NET page, as shown in the example below:
<objects xmlns="http://www.springframework.net" xmlns:v="http://www.springframework.net/validation"> <object type="TripForm.aspx" parent="standardPage"> <property name="TripValidator" ref="tripValidator" /> </object> <v:group id="tripValidator"> <v:required id="departureAirportValidator" test="StartingFrom.AirportCode"> <!-- write error message to 2 providers --> <v:message id="error.departureAirport.required" providers="departureAirportErrors, errorSummary"/> </v:required> <v:group id="destinationAirportValidator"> <v:required test="ReturningFrom.AirportCode"> <!-- write error message to 2 providers --> <v:message id="error.destinationAirport.required" providers="destinationAirportErrors, errorSummary"/> </v:required> </v:group> </v:group> </objects>

Once that's done, you need to perform validation in one or more of the page event handlers, which typically looks similar to this:
public void SearchForFlights(object sender, EventArgs e) {

Spring Framework (Version 1.3.2)

126

Validation Framework
if (Validate(Controller.Trip, tripValidator)) { Process.SetView(Controller.SearchForFlights()); } }

Note
Keep in mind that your ASP.NET page needs to extend Spring.Web.UI.Page in order for the code above to work. Finally, you need to define where validation errors should be displayed by adding one or more <spring:validationError/> and <spring:validationSummary/> controls to the ASP.NET form:
<!-- code snippet taken from the SpringAir sample application --> <%@ Page Language="c#" MasterPageFile="~/Web/ StandardTemplate.master" Inherits="TripForm" CodeFile="TripForm.aspx.cs" %> <!-- render all error messages sent to 'errorSummary' provider --> <spring:ValidationSummary ID="summary" Provider="errorSummary" runat="server" /> <table> <tr> <td> <asp:Label ID="leavingFrom" runat="server" /></td> <td> <asp:DropDownList ID="leavingFromAirportCode" AutoCallBack="true" runat="server" /> <!-- render error messages sent to 'departureAirportErrors' provider --> <spring:ValidationError ID="leavingFromError" Provider="departureAirportErrors" runat="server" /> </td> <td> <asp:Label ID="goingTo" runat="server" /></td> <td> <asp:DropDownList ID="goingToAirportCode" AutoCallBack="true" runat="server" /> <!-- render error messages sent to 'destinationAirportErrors' provider --> <spring:ValidationError ID="goingToError" Provider="destinationAirportErrors" runat="server" /> </td> </tr> </table>

12.8.1. Rendering Validation Errors


Spring.NET allows you to render validation errors within the page in several different ways, and if none of them suits your needs you can implement your own validation errors renderer. Implementations of the Spring.Web.Validation.IValidationErrorsRenderer that ship with the framework are: Table 12.3. Validation Renderers Name Class Description

Block Spring.Web.Validation.DivValidationErrorsRenderer as list items within a <div> tag. Default Renders validation errors renderer for <spring:validationSummary> control. Inline Spring.Web.Validation.SpanValidationErrorsRenderer within a <span> tag. Default renderer for Renders validation errors <spring:validationError> control. Icon
Spring.Web.Validation.IconValidationErrorsRenderer as error icon, with error messages displayed Renders validation errors

in a tooltip. Best option when saving screen real estate is important. These three error renderers should be sufficient for most applications, but in case you want to display errors in some other way you can write your own renderer by implementing Spring.Web.Validation.IValidationErrorsRenderer interface:

Spring Framework (Version 1.3.2)

127

Validation Framework
namespace Spring.Web.Validation { /// <summary> /// This interface should be implemented by all validation errors renderers. /// </summary> /// <remarks> /// <para> /// Validation errors renderers are used to decouple rendering behavior from the /// validation errors controls such as <see cref="ValidationError"/> and /// <see cref="ValidationSummary"/>. /// </para> /// <para> /// This allows users to change how validation errors are rendered by simply plugging in /// appropriate renderer implementation into the validation errors controls using /// Spring.NET dependency injection. /// </para> /// </remarks> public interface IValidationErrorsRenderer { /// <summary> /// Renders validation errors using specified <see cref="HtmlTextWriter"/>. /// </summary> /// <param name="page">Web form instance.</param> /// <param name="writer">An HTML writer to use.</param> /// <param name="errors">The list of validation errors.</param> void RenderErrors(Page page, HtmlTextWriter writer, IList errors); } }

12.8.1.1. Configuring which Error Renderer to use. The best part of the errors renderer mechanism is that you can easily change it across the application by modifying configuration templates for <spring:validationSummary> and <spring:validationError> controls:
<!-- Validation errors renderer configuration --> <object id="Spring.Web.UI.Controls.ValidationError" abstract="true"> <property name="Renderer"> <object type="Spring.Web.Validation.IconValidationErrorsRenderer, Spring.Web"> <property name="IconSrc" value="validation-error.gif"/> </object> </property> </object> <object id="Spring.Web.UI.Controls.ValidationSummary" abstract="true"> <property name="Renderer"> <object type="Spring.Web.Validation.DivValidationErrorsRenderer, Spring.Web"> <property name="CssClass" value="validationError"/> </object> </property> </object>

It's as simple as that!

12.8.2. How Validate() and Validation Controls play together


Validation Controls (ValidationSummary, ValidationError) need to somehow get the list of errors collected during validation. Both, Spring.Web.UI.Page and Spring.Web.UI.UserControl come with a ValidationErrors property and implement IValidationContainer. ValidationControls will automatically pick the IValidationContainer control they are placed on:
// ASPX / ASCX Template Code <%@ Control Language="c#"%> <!-- render all error messages sent to 'errorSummary' provider --> <spring:ValidationSummary ID="summary" Provider="errorSummary" runat="server" /> <asp:DropDownList ID="leavingFromAirportCode" AutoCallBack="true" runat="server" /> <!-- render error messages sent to 'departureAirportErrors' provider -->

Spring Framework (Version 1.3.2)

128

Validation Framework
<spring:ValidationError ID="leavingFromError" Provider="departureAirportErrors" runat="server" />

<script language="C#" runat="server"> public void SearchForFlights(object sender, EventArgs e) { if (Validate(Controller.Trip, tripValidator)) { Process.SetView(Controller.SearchForFlights()); } } </script>

If you need to render errors from a UserControl not in the hierarchy of your Validation control, you can specify the name of the target validation container control:
// ASPX / ASCX Template Code <%@ Page Language="c#" %> <%@ Register TagPrefix="user" TagName="EmployeeInfoEditor" Src="EmployeeInfoEditor.ascx" %> <spring:ValidationSummary ID="summary" Provider="summary" ValidationContainerName="editor" runat="server" /> <user:EmployeeInfoEditor ID="editor" runat="server" />

Spring Framework (Version 1.3.2)

129

Chapter 13. Aspect Oriented Programming with Spring.NET


13.1. Introduction
Aspect-Oriented Programming (AOP) complements OOP by providing another way of thinking about program structure. Whereas OO decomposes applications into a hierarchy of objects, AOP decomposes programs into aspects or concerns. This enables the modularization of concerns such as transaction management that would otherwise cut across multiple objects (such concerns are often termed crosscutting concerns). One of the key components of Spring.NET is the AOP framework. While the Spring.NET IoC container does not depend on AOP, meaning you don't need to use AOP if you don't want to, AOP complements Spring.NET IoC to provide a very capable middleware solution. AOP is used in Spring.NET: To provide declarative enterprise services, especially as a replacement for COM+ declarative services. The most important such service is declarative transaction management, which builds on Spring.NET's transaction abstraction. This functionality is planed for an upcoming release of Spring.NET To allow users to implement custom aspects, complementing their use of OOP with AOP. Thus you can view Spring.NET AOP as either an enabling technology that allows Spring.NET to provide declarative transaction management without COM+; or use the full power of the Spring.NET AOP framework to implement custom aspects. For those who would like to hit the ground running and start exploring how to use Spring's AOP functionality, head on over to Chapter 38, AOP QuickStart.

13.1.1. AOP concepts


Let us begin by defining some central AOP concepts. These terms are not Spring.NET-specific. Unfortunately, AOP terminology is not particularly intuitive. However, it would be even more confusing if Spring.NET used its own terminology. Aspect: A modularization of a concern for which the implementation might otherwise cut across multiple objects. Transaction management is a good example of a crosscutting concern in enterprise applications. Aspects are implemented using Spring.NET as Advisors or interceptors. Joinpoint: Point during the execution of a program, such as a method invocation or a particular exception being thrown. Advice: Action taken by the AOP framework at a particular joinpoint. Different types of advice include "around," "before" and "throws" advice. Advice types are discussed below. Many AOP frameworks, including Spring.NET, model an advice as an interceptor, maintaining a chain of interceptors "around" the joinpoint. Pointcut: A set of joinpoints specifying when an advice should fire. An AOP framework must allow developers to specify pointcuts: for example, using regular expressions. Introduction: Adding methods or fields to an advised class. Spring.NET allows you to introduce new interfaces to any advised object. For example, you could use an introduction to make any object implement an IAuditable interface, to simplify the tracking of changes to an object's state.

Spring Framework (Version 1.3.2)

130

Aspect Oriented Programming with Spring.NET Target object: Object containing the joinpoint. Also referred to as advised or proxied object. AOP proxy: Object created by the AOP framework, including advice. In Spring.NET, an AOP proxy is a dynamic proxy that uses IL code generated at runtime. Weaving: Assembling aspects to create an advised object. This can be done at compile time (using the GripperLoom.NET compiler, for example), or at runtime. Spring.NET performs weaving at runtime. Different advice types include: Around advice: Advice that surrounds a joinpoint such as a method invocation. This is the most powerful kind of advice. Around advice will perform custom behaviour before and after the method invocation. They are responsible for choosing whether to proceed to the joinpoint or to shortcut executing by returning their own return value or throwing an exception. Before advice: Advice that executes before a joinpoint, but which does not have the ability to prevent execution flow proceeding to the joinpoint (unless it throws an exception). Throws advice: Advice to be executed if a method throws an exception. Spring.NET provides strongly typed throws advice, so you can write code that catches the exception (and subclasses) you're interested in, without needing to cast from Exception. After returning advice: Advice to be executed after a joinpoint completes normally: for example, if a method returns without throwing an exception. Spring.NET provides a full range of advice types. We recommend that you use the least powerful advice type that can implement the required behaviour. For example, if you need only to update a cache with the return value of a method, you are better off implementing an after returning advice than an around advice, although an around advice can accomplish the same thing. Using the most specific advice type provides a simpler programming model with less potential for errors. For example, you don't need to invoke the proceed() method on the IMethodInvocation used for around advice, and hence can't fail to invoke it. The pointcut concept is the key to AOP, distinguishing AOP from older technologies offering interception. Pointcuts enable advice to be targeted independently of the OO hierarchy. For example, an around advice providing declarative transaction management can be applied to a set of methods spanning multiple objects. Thus pointcuts provide the structural element of AOP.

13.1.2. Spring.NET AOP capabilities


Spring.NET AOP is implemented in pure C#. There is no need for a special compilation process - all weaving is done at runtime. Spring.NET AOP does not need to control or modify the way in which assemblies are loaded, nor does it rely on unmanaged APIs, and is thus suitable for use in any CLR environment. Spring.NET currently supports interception of method invocations. Field interception is not implemented, although support for field interception could be added without breaking the core Spring.NET AOP APIs. Field interception arguably violates OO encapsulation. We don't believe it is wise in application development. Spring.NET provides classes to represent pointcuts and different advice types. Spring.NET uses the term advisor for an object representing an aspect, including both an advice and a pointcut targeting it to specific joinpoints. Different advice types are IMethodInterceptor (from the AOP Alliance interception API); and the advice interfaces defined in the Spring.Aop namespace. All advices must implement the AopAlliance.Aop.IAdvice

Spring Framework (Version 1.3.2)

131

Aspect Oriented Programming with Spring.NET tag interface. Advices supported out the box are IMethodInterceptor ; IThrowsAdvice; IBeforeAdvice; and IAfterReturningAdvice. We'll discuss advice types in detail below. Spring.NET provides a .NET translation of the Java interfaces defined by the AOP Alliance . Around advice must implement the AOP Alliance AopAlliance.Interceptr.IMethodInterceptor interface. Whilst there is wide support for the AOP Alliance in Java, Spring.NET is currently the only .NET AOP framework that makes use of these interfaces. In the short term, this will provide a consistent programming model for those doing development in both .NET and Java, and in the longer term, we hope to see more .NET projects adopt the AOP Alliance interfaces. The aim of Spring.NET AOP support is not to provide a comprehensive AOP implementation on par with the functionality available in AspectJ. However, Spring.NET AOP provides an excellent solution to most problems in .NET applications that are amenable to AOP. Thus, it is common to see Spring.NET's AOP functionality used in conjunction with a Spring.NET IoC container. AOP advice is specified using normal object definition syntax (although this allows powerful "autoproxying" capabilities); advice and pointcuts are themselves managed by Spring.NET IoC.

13.1.3. AOP Proxies in Spring.NET


Spring.NET generates AOP proxies at runtime using classes from the System.Reflection.Emit namespace to create necessary IL code for the proxy class. This results in proxies that are very efficient and do not impose any restrictions on the inheritance hierarchy. Another common approach to AOP proxy implementation in .NET is to use ContextBoundObject and the .NET remoting infrastructure as an interception mechanism. We are not very fond of ContextBoundObject approach because it requires classes that need to be proxied to inherit from the ContextBoundObject either directly or indirectly. In our opinion this an unnecessary restriction that influences how you should design your object model and also excludes applying AOP to "3rd party" classes that are not under your direct control. Context-bound proxies are also an order of magnitude slower than IL-generated proxies, due to the overhead of the context switching and .NET remoting infrastructure. Spring.NET AOP proxies are also "smart" - in that because proxy configuration is known during proxy generation, the generated proxy can be optimized to invoke target methods via reflection only when necessary (i.e. when there are advices applied to the target method). In all other cases the target method will be called directly, thus avoiding performance hit caused by the reflective invocation. Finally, Spring.NET AOP proxies will never return a raw reference to a target object. Whenever a target method returns a raw reference to a target object (i.e. "return this;"), AOP proxy will recognize what happened and will replace the return value with a reference to itself instead. The current implementation of the AOP proxy generator uses object composition to delegate calls from the proxy to a target object, similar to how you would implement a classic Decorator pattern. This means that classes that need to be proxied have to implement one or more interfaces, which is in our opinion not only a less-intruding requirement than ContextBoundObject inheritance requirements, but also a good practice that should be followed anyway for the service classes that are most common targets for AOP proxies. In a future release we will implement proxies using inheritance, which will allow you to proxy classes without interfaces as well and will remove some of the remaining raw reference issues that cannot be solved using composition-based proxies.

13.2. Pointcut API in Spring.NET


Let's look at how Spring.NET handles the crucial pointcut concept.

Spring Framework (Version 1.3.2)

132

Aspect Oriented Programming with Spring.NET

13.2.1. Concepts
Spring.NET's pointcut model enables pointcut reuse independent of advice types. It's possible to target different advice using the same pointcut. The Spring.Aop.IPointcut interface is the central interface, used to target advices to particular types and methods. The complete interface is shown below:
public interface IPointcut { ITypeFilter TypeFilter { get; } IMethodMatcher MethodMatcher { get; } }

Splitting the IPointcut interface into two parts allows reuse of type and method matching parts, and fine-grained composition operations (such as performing a "union" with another method matcher). The ITypeFilter interface is used to restrict the pointcut to a given set of target classes. If the Matches() method always returns true, all target types will be matched:
public interface ITypeFilter { bool Matches(Type type); }

The IMethodMatcher interface is normally more important. The complete interface is shown below:
public interface IMethodMatcher { bool IsRuntime { get; } bool Matches(MethodInfo method, Type targetType); bool Matches(MethodInfo method, Type targetType, object[] args); }

The Matches(MethodInfo, Type) method is used to test whether this pointcut will ever match a given method on a target type. This evaluation can be performed when an AOP proxy is created, to avoid the need for a test on every method invocation. If the 2-argument matches method returns true for a given method, and the IsRuntime property for the IMethodMatcher returns true, the 3-argument matches method will be invoked on every method invocation. This enables a pointcut to look at the arguments passed to the method invocation immediately before the target advice is to execute. Most IMethodMatchers are static, meaning that their IsRuntime property returns false. In this case, the 3-argument Matches method will never be invoked. Whenever possible, try to make pointcuts static... this allows the AOP framework to cache the results of pointcut evaluation when an AOP proxy is created.

13.2.2. Operations on pointcuts


Spring.NET supports operations on pointcuts: notably, union and intersection. Union means the methods that either pointcut matches. Intersection means the methods that both pointcuts match. Union is usually more useful.

Spring Framework (Version 1.3.2)

133

Aspect Oriented Programming with Spring.NET Pointcuts can be composed using the static methods in the Spring.Aop.Support.Pointcuts class, or using the ComposablePointcut class in the same namespace.

13.2.3. Convenience pointcut implementations


Spring.NET provides several convenient pointcut implementations. Some can be used out of the box; others are intended to be subclassed in application-specific pointcuts. 13.2.3.1. Static pointcuts Static pointcuts are based on method and target class, and cannot take into account the method's arguments. Static pointcuts are sufficient--and best--for most usages. It's possible for Spring.NET to evaluate a static pointcut only once, when a method is first invoked: after that, there is no need to evaluate the pointcut again with each method invocation. Let's consider some static pointcut implementations included with Spring.NET.

13.2.3.1.1. Regular expression pointcuts


One obvious way to specify static pointcuts is using regular expressions. Several AOP frameworks besides Spring.NET make this possible. The Spring.Aop.Support.SdkRegularExpressionMethodPointcut class is a generic regular expression pointcut, that uses the regular expression classes from the .NET BCL. Using this class, you can provide a list of pattern Strings. If any of these is a match, the pointcut will evaluate to true (so the result is effectively the union of these pointcuts.). The matching is done against the full class name so you can use this pointcut if you would like to apply advice to all the classes in a particular namespace. The usage is shown below:
<object id="settersAndAbsquatulatePointcut" type="Spring.Aop.Support.SdkRegularExpressionMethodPointcut, Spring.Aop"> <property name="patterns"> <list> <value>.*set.*</value> <value>.*absquatulate</value> </list> </property> </object>

As a convenience, Spring provides the RegularExpressionMethodPointcutAdvisor class that allows us to reference an IAdvice instance as well as defining the pointcut rules (remember that an IAdvice instance can be an interceptor, before advice, throws advice etc.) This simplifies wiring, as the one object serves as both pointcut and advisor, as shown below:
<object id="settersAndAbsquatulateAdvisor" type="Spring.Aop.Support.RegularExpressionMethodPointcutAdvisor, Spring.Aop"> <property name="advice"> <ref local="objectNameOfAopAllianceInterceptor"/> </property> <property name="patterns"> <list> <value>.*set.*</value> <value>.*absquatulate</value> </list> </property> </object>

The RegularExpressionMethodPointcutAdvisor class can be used with any Advice type. If you only have one pattern you can use the property name pattern and specify a single value instead of using the property name patterns and specifying a list.

Spring Framework (Version 1.3.2)

134

Aspect Oriented Programming with Spring.NET You may also specify a Regex object from the System.Text.RegularExpressions namespace. The built in RegexConverter class will perform the conversion. See Section 6.4, Built-in TypeConverters for more information on Spring's build in type converters. The Regex object is created as any other object within the IoC container. Using an inner-object definition for the Regex object is a handy way to keep the definition close to the PointcutAdvisor declaration. Note that the class SdkRegularExpressionMethodPointcut has a DefaultOptions property to set the regular expression options if they are not explicitly specified in the constructor.

13.2.3.1.2. Attribute pointcuts


Pointcuts can be specified by matching an attribute type that is associated with a method. Advice associated with this pointcut can then read the metadata associated with the attribute to configure itself. The class AttributeMatchMethodPointcut provides this functionality. Sample usage that will match all methods that have the attribute Spring.Attributes.CacheAttribute is shown below.
<object id="cachePointcut" type="Spring.Aop.Support.AttributeMatchMethodPointcut, Spring.Aop"> <property name="Attribute" value="Spring.Attributes.CacheAttribute, Spring.Core"/> </object>

This can be used with a DefaultPointcutAdvisor as shown below


<object id="cacheAspect" type="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop"> <property name="Pointcut"> <object type="Spring.Aop.Support.AttributeMatchMethodPointcut, Spring.Aop"> <property name="Attribute" value="Spring.Attributes.CacheAttribute, Spring.Core"/> </object> </property> <property name="Advice" ref="aspNetCacheAdvice"/> </object>

where aspNetCacheAdvice is an implementation of an IMethodInterceptor that caches method return values. See the SDK docs for Spring.Aop.Advice.CacheAdvice for more information on this particular advice. As a convenience the class AttributeMatchMethodPointcutAdvisor is provided to defining an attribute based Advisor as a somewhat shorter alternative to using the generic DefaultPointcutAdvisor. An example is shown below.
<object id="AspNetCacheAdvice" type="Spring.Aop.Support.AttributeMatchMethodPointcutAdvisor, Spring.Aop"> <property name="advice"> <object type="Aspect.AspNetCacheAdvice, Aspect"/> </property> <property name="attribute" value="Framework.AspNetCacheAttribute, Framework" /> </object>

13.2.3.2. Dynamic Pointcuts Dynamic pointcuts are costlier to evaluate than static pointcuts. They take into account method arguments, as well as static information. This means that they must be evaluated with every method invocation; the result cannot be cached, as arguments will vary. The main example is the control flow pointcut.

13.2.3.2.1. Control Flow Pointcuts


Spring.NET control flow pointcuts are conceptually similar to AspectJ cflow pointcuts, although less powerful. (There is currently no way to specify that a pointcut executes below another pointcut.). A control flow pointcut is dynamic because it is evaluated against the current call stack for each method invocation. For example, if method ClassA.A() calls ClassB.B() then the execution of ClassB.B() has occurred in ClassA.A()'s control flow. A control flow pointcut allows advice to be applied to the method ClassA.A() but only when called from ClassB.B()

Spring Framework (Version 1.3.2)

135

Aspect Oriented Programming with Spring.NET and not when ClassA.A() is executed from another call stack. Control flow pointcuts are specified using the Spring.Aop.Support.ControlFlowPointcut class.

Note
Control flow pointcuts are significantly more expensive to evaluate at runtime than even other dynamic pointcuts. When using control flow point cuts some attention should be paid to the fact that at runtime the JIT compiler can inline the methods, typically for increased performance, but with the consequence that the method no longer appears in the current call stack. This is because inlining takes the callee's IL code and inserts it into the caller's IL code effectively removing the method call. The information returned from System.Diagnostics.StackTrace, used in the implementation of ControlFlowPointcut is subject to these optimizations and therefore a control flow pointcut will not match if the method has been inlined. Generally speaking, a method will be a candidate for inlining when its code is 'small', just a few lines of code (less than 32 bytes of IL). For some interesting reading on this process read David Notario's blog entries (JIT Optimizations I and JIT Optimizations II). Additionally, when an assembly is compiled with a Release configuration the assembly metadata instructs the CLR to enable JIT optimizations. When compiled with a Debug configuration the CLR will disable (some?) these optimizations. Empirically, method inlining is turned off in a Debug configuration. The way to ensure that your control flow pointcut will not be overlooked because of method inlining is to apply the System.Runtime.CompilerServices.MethodImplAttribute attribute with the value MethodImplOptions.NoInlining. In this (somewhat artificial) simple example, if the code is compiled in release mode it will not match a control flow pointcut for the method "GetAge".
public int GetAge(IPerson person) { return person.GetAge(); }

However, applying the attributes as shown below will prevent the method from being inlined even in a release build.
[MethodImpl(MethodImplOptions.NoInlining)] public int GetAge(IPerson person) { return person.GetAge(); }

13.2.4. Custom pointcuts


Because pointcuts in Spring.NET are .NET types, rather than language features (as in AspectJ) it is possible to declare custom pointcuts, whether static or dynamic. However, there is no support out of the box for the sophisticated pointcut expressions that can be coded in the AspectJ syntax. However, custom pointcuts in Spring.NET can be as arbitrarily complex as any object model. Spring.NET provides useful pointcut superclasses to help you to implement your own pointcuts. Because static pointcuts are the most common and generally useful pointcut type, you'll probably subclass StaticMethodMatcherPointcut, as shown below. This requires you to implement just one abstract method (although it is possible to override other methods to customize behaviour):
public class TestStaticPointcut : StaticMethodMatcherPointcut {

Spring Framework (Version 1.3.2)

136

Aspect Oriented Programming with Spring.NET


public override bool Matches(MethodInfo method, Type targetType) { // return true if custom criteria match } }

13.3. Advice API in Spring.NET


Let's now look at how Spring.NET AOP handles advice.

13.3.1. Advice Lifecycle


Spring.NET advices can be shared across all advised objects, or unique to each advised object. This corresponds to per-class or per-instance advice. Per-class advice is used most often. It is appropriate for generic advice such as transaction advisors. These do not depend on the state of the proxied object or add new state; they merely act on the method and arguments. Per-instance advice is appropriate for introductions, to support mixins. In this case, the advice adds state to the proxied object. It's possible to use a mix of shared and per-instance advice in the same AOP proxy.

13.3.2. Advice types


Spring.NET provides several advice types out of the box, and is extensible to support arbitrary advice types. Let us look at the basic concepts and standard advice types. 13.3.2.1. Interception Around Advice The most fundamental advice type in Spring.NET is interception around advice. Spring.NET is compliant with the AOP Alliance interface for around advice using method interception. Around advice is implemented using the following interface:
public interface IMethodInterceptor : IInterceptor { object Invoke(IMethodInvocation invocation); }

The IMethodInvocation argument to the Invoke() method exposes the method being invoked; the target joinpoint; the AOP proxy; and the arguments to the method. The Invoke() method should return the invocation's result: the return value of the joinpoint. A simple IMethodInterceptor implementation looks as follows:
public class DebugInterceptor : IMethodInterceptor { public object Invoke(IMethodInvocation invocation) { Console.WriteLine("Before: invocation=[{0}]", invocation); object rval = invocation.Proceed(); Console.WriteLine("Invocation returned"); return rval; } }

Note the call to the IMethodInvocation's Proceed() method. This proceeds down the interceptor chain towards the joinpoint. Most interceptors will invoke this method, and return its return value. However, an IMethodInterceptor, like any around advice, can return a different value or throw an exception rather than invoke the Proceed() method. However, you don't want to do this without good reason!

Spring Framework (Version 1.3.2)

137

Aspect Oriented Programming with Spring.NET 13.3.2.2. Before advice A simpler advice type is a before advice. This does not need an IMethodInvocation object, since it will only be called before entering the method. The main advantage of a before advice is that there is no need to invoke the Proceed()method, and therefore no possibility of inadvertently failing to proceed down the interceptor chain. The IMethodBeforeAdvice interface is shown below.
public interface IMethodBeforeAdvice : IBeforeAdvice { void Before(MethodInfo method, object[] args, object target); }

Note the return type is void. Before advice can insert custom behaviour before the joinpoint executes, but cannot change the return value. If a before advice throws an exception, this will abort further execution of the interceptor chain. The exception will propagate back up the interceptor chain. If it is unchecked, or on the signature of the invoked method, it will be passed directly to the client; otherwise it will be wrapped in an unchecked exception by the AOP proxy. An example of a before advice in Spring.NET, which counts all methods that return normally:
public class CountingBeforeAdvice : IMethodBeforeAdvice { private int count; public void Before(MethodInfo method, object[] args, object target) { ++count; } public int Count { get { return count; } } }

Before advice can be used with any pointcut. 13.3.2.3. Throws advice Throws advice is invoked after the return of the joinpoint if the joinpoint threw an exception. The Spring.Aop.IThrowsAdvice interface does not contain any methods: it is a tag interface identifying that the implementing advice object implements one or more typed throws advice methods. These throws advice methods must be of the form:
AfterThrowing([MethodInfo method, Object[] args, Object target], Exception subclass)

Throws-advice methods must be named 'AfterThrowing'. The return value will be ignored by the Spring.NET AOP framework, so it is typically void. With regard to the method arguments, only the last argument is required. Thus there are exactly one or four arguments, depending on whether the advice method is interested in the method, method arguments and the target object. The following method snippets show examples of throws advice. This advice will be invoked if a RemotingException is thrown (including subclasses):
public class RemoteThrowsAdvice : IThrowsAdvice { public void AfterThrowing(RemotingException ex) { // Do something with remoting exception

Spring Framework (Version 1.3.2)

138

Aspect Oriented Programming with Spring.NET


} }

The following advice is invoked if a SqlException is thrown. Unlike the above advice, it declares 4 arguments, so that it has access to the invoked method, method arguments and target object:
public class SqlExceptionThrowsAdviceWithArguments : IThrowsAdvice { public void AfterThrowing(MethodInfo method, object[] args, object target, SqlException ex) { // Do something will all arguments } }

The final example illustrates how these two methods could be used in a single class, which handles both RemotingException and SqlException. Any number of throws advice methods can be combined in a single class, as can be seen in the following example.
public class CombinedThrowsAdvice : IThrowsAdvice { public void AfterThrowing(RemotingException ex) // Do something with remoting exception } {

public void AfterThrowing(MethodInfo method, object[] args, object target, SqlException ex) { // Do something will all arguments } }

Finally, it is worth stating that throws advice is only applied to the actual exception being thrown. What does this mean? Well, it means that if you have defined some throws advice that handles RemotingExceptions, the applicable AfterThrowing method will only be invoked if the type of the thrown exception is RemotingException... if a RemotingException has been thrown and subsequently wrapped inside another exception before the exception bubbles up to the throws advice interceptor, then the throws advice that handles RemotingExceptions will never be called. Consider a business method that is advised by throws advice that handles RemotingExceptions; if during the course of a method invocation said business method throws a RemoteException... and subsequently wraps said RemotingException inside a business-specific BadConnectionException (see the code snippet below) before throwing the exception, then the throws advice will never be able to respond to the RemotingException... because all the throws advice sees is a BadConnectionException. The fact that the RemotingException is wrapped up inside the BadConnectionException is immaterial.
public void BusinessMethod() { try { // do some business operation... } catch (RemotingException ex) { throw new BadConnectionException("Couldn't connect.", ex); } }

Note
Please note that throws advice can be used with any pointcut. 13.3.2.4. After Returning advice An after returning advice in Spring.NET must implement the Spring.Aop.IAfterReturningAdvice interface, shown below:

Spring Framework (Version 1.3.2)

139

Aspect Oriented Programming with Spring.NET


public interface IAfterReturningAdvice : IAdvice { void AfterReturning(object returnValue, MethodBase method, object[] args, object target); }

An after returning advice has access to the return value (which it cannot modify), invoked method, methods arguments and target. The following after returning advice counts all successful method invocations that have not thrown exceptions:
public class CountingAfterReturningAdvice : IAfterReturningAdvice { private int count; public void AfterReturning(object returnValue, MethodBase m, object[] args, object target) { ++count; } public int Count { get { return count; } } }

This advice doesn't change the execution path. If it throws an exception, this will be thrown up the interceptor chain instead of the return value.

Note
Please note that after-returning advice can be used with any pointcut. 13.3.2.5. Advice Ordering When multiple pieces of advice want to run on the same joinpoint the precedence is determined by having the advice implement the IOrdered interface or by specifying order information on an advisor. 13.3.2.6. Introduction advice Spring.NET allows you to add new methods and properties to an advised class. This would typically be done when the functionality you wish to add is a crosscutting concern and want to introduce this functionality as a change to the static structure of the class hierarchy. For example, you may want to cast objects to the introduction interface in your code. Introductions are also a means to emulate multiple inheritance. Introduction advice is defined by using a normal interface declaration that implements the tag interface IAdvice.

Note
The need for implementing this marker interface will likely be removed in future versions. As an example, consider the interface IAuditable that describes the last modified time of an object.
public interface IAuditable : IAdvice { DateTime LastModifiedDate { get; set; } }

where
public interface IAdvice { }

Spring Framework (Version 1.3.2)

140

Aspect Oriented Programming with Spring.NET Access to the advised object can be obtained by implementing the interface ITargetAware
public interface ITargetAware { IAopProxy TargetProxy { set; } }

with the IAopProxy reference providing a layer of indirection through which the advised object can be accessed.
public interface IAopProxy { object GetProxy(); }

A simple class that demonstrates this functionality is shown below.


public interface IAuditable : IAdvice, ITargetAware { DateTime LastModifiedDate { get; set; } }

A class that implements this interface is shown below.


public class AuditableMixin : IAuditable { private DateTime date; private IAopProxy targetProxy; public AuditableMixin() { date = new DateTime(); } public DateTime LastModifiedDate { get { return date; } set { date = value; } } public IAopProxy TargetProxy { set { targetProxy = value; } } }

Introduction advice is not associated with a pointcut, since it applies at the class and not the method level. As such, introductions use their own subclass of the interface IAdvisor, namely IIntroductionAdvisor, to specify the types that the introduction can be applied to.
public interface IIntroductionAdvisor : IAdvisor { ITypeFilter TypeFilter { get; } Type[] Interfaces { get; } void ValidateInterfaces(); }

The TypeFilter property returns the filter that determines which target classes this introduction should apply to. The Interfaces property returns the interfaces introduced by this advisor.

Spring Framework (Version 1.3.2)

141

Aspect Oriented Programming with Spring.NET The ValidateInterfaces() method is used internally to see if the introduced interfaces can be implemented by the introduction advice. Spring.NET provides a default implementation of this interface (the DefaultIntroductionAdvisor class) that should be sufficient for the majority of situations when you need to use introductions. The most simple implementation of an introduction advisor is a subclass that simply passes a new instance the base constructor. Passing a new instance is important since we want a new instance of the mixin classed used for each advised object.
public class AuditableAdvisor : DefaultIntroductionAdvisor { public AuditableAdvisor() : base(new AuditableMixin()) { } }

Other constructors let you explicitly specify the interfaces of the class that will be introduced. See the SDK documentation for more details. We can apply this advisor Programatically, using the IAdvised.AddIntroduction(), method, or (the recommended way) in XML configuration using the IntroductionNames property on ProxyFactoryObject, which will be discussed later. Unlike the AOP implementation in the Spring Framework for Java, introduction advice in Spring.NET is not implemented as a specialized type of interception advice. The advantage of this approach is that introductions are not kept in the interceptor chain, which allows some significant performance optimizations. When a method is called that has no interceptors, a direct call is used instead of reflection regardless of whether the target method is on the target object itself or one of the introductions. This means that introduced methods perform the same as target object methods, which could be useful for adding introductions to fine grained objects. The disadvantage is that if the mixin functionality would benefit from having access to the calling stack, it is not available. Introductions with this functionality will be addressed in a future version of Spring.NET AOP.

13.4. Advisor API in Spring.NET


In Spring.NET, an advisor is a modularization of an aspect. Advisors typically incorporate both an advice and a pointcut. Apart from the special case of introductions, any advisor can be used with any advice. The Spring.Aop.Support.DefaultPointcutAdvisor class is the most commonly used advisor implementation. For example, it can be used with a IMethodInterceptor, IBeforeAdvice or IThrowsAdvice and any pointcut definition. Other convenience implementations provided are: AttributeMatchMethodPointcutAdvisor shown in usage previously in Section 13.2.3.1.2, Attribute pointcuts for use with attribute based pointcuts. RegularExpressionMethodPointcutAdvisor that will apply pointcuts based on the matching a regular expression to method names. It is possible to mix advisor and advice types in Spring.NET in the same AOP proxy. For example, you could use a interception around advice, throws advice and before advice in one proxy configuration: Spring.NET will automatically create the necessary interceptor chain.

13.5. Using the ProxyFactoryObject to create AOP proxies


If you're using the Spring.NET IoC container for your business objects - generally a good idea - you will want to use one of Spring.NET's AOP-specific IFactoryObject implementations (remember that a factory object

Spring Framework (Version 1.3.2)

142

Aspect Oriented Programming with Spring.NET introduces a layer of indirection, enabling it to create objects of a different type - Section 5.3.9, Setting a reference using the members of other objects and classes.). The basic way to create an AOP proxy in Spring.NET is to use the Spring.Aop.Framework.ProxyFactoryObject class. This gives complete control over ordering and application of the pointcuts and advice that will apply to your business objects. However, there are simpler options that are preferable if you don't need such control.

13.5.1. Basics
The ProxyFactoryObject, like other Spring.NET IFactoryObject implementations, introduces a level of indirection. If you define a ProxyFactoryObject with name foo, what objects referencing foo see is not the ProxyFactoryObject instance itself, but an object created by the ProxyFactoryObject's implementation of the GetObject() method. This method will create an AOP proxy wrapping a target object. One of the most important benefits of using a ProxyFactoryObject or other IoC-aware classes that create AOP proxies, is that it means that advice and pointcuts can also be managed by IoC. This is a powerful feature, enabling certain approaches that are hard to achieve with other AOP frameworks. For example, an advice may itself reference application objects (besides the target, which should be available in any AOP framework), benefiting from all the pluggability provided by Dependency Injection.

13.5.2. ProxyFactoryObject Properties


Like most IFactoryObject implementations provided with Spring.NET, the ProxyFactoryObject is itself a Spring.NET configurable object. Its properties are used to: Specify the target object that is to be proxied. Specify the advice that is to be applied to the proxy. Some key properties are inherited from the Spring.Aop.Framework.ProxyConfig class: this class is the superclass for all AOP proxy factories in Spring.NET. Some of the key properties include: ProxyTargetType: a boolean value that should be set to true if the target class is to be proxied directly, as opposed to just proxying the interfaces exposed on the target class. Optimize: whether to apply aggressive optimization to created proxies. Don't use this setting unless you understand how the relevant AOP proxy handles optimization. The exact meaning of this flag will differ between proxy implementations and will generally result in a trade off between proxy creation time and runtime performance. Optimizations may be ignored by certain proxy implementations and may be disabled silently based on the value of other properties such as ExposeProxy. IsFrozen: whether advice changes should be disallowed once the proxy factory has been configured. The default is false. ExposeProxy: whether the current proxy should be exposed via the AopContext so that it can be accessed by the target. (It's available via the IMethodInvocation without the need for the AopContext.) If a target needs to obtain the proxy and ExposeProxy is true, the target can use the AopContext.CurrentProxy property. AopProxyFactory: the implementation of IAopProxyFactory to use when generating a proxy. Offers a way of customizing whether to use remoting proxies, IL generation or any other proxy strategy. The default implementation will use IL generation to create composition-based proxies. Other properties specific to the ProxyFactoryObject class include: ProxyInterfaces: the array of string interface names we're proxying.

Spring Framework (Version 1.3.2)

143

Aspect Oriented Programming with Spring.NET InterceptorNames: string array of IAdvisor, interceptor or other advice names to apply. Ordering is significant... first come, first served that is. The first interceptor in the list will be the first to be able to interceptor the invocation (assuming it concerns a regular MethodInterceptor or BeforeAdvice). The names are object names in the current container, including objectnames from container hierarchies. You can't mention object references here since doing so would result in the ProxyFactoryObject ignoring the singleton setting of the advise. IntroductionNames: The names of objects in the container that will be used as introductions to the target object. If the object referred to by name does not implement the IIntroductionAdvisor it will be passed to the default constructor of DefaultIntroductionAdvisor and all of the objects interfaces will be added to the target object. Objects that implement the IIntroductionAdvisor interface will be used as is, giving you a finer level of control over what interfaces you may want to expose and the types for which they will be matched against. IsSingleton: whether or not the factory should return a single proxy object, no matter how often the GetObject() method is called. Several IFactoryObject implementations offer such a method. The default value is true. If you would like to be able to apply advice on a per-proxy object basis, use a IsSingleton value of false and a IsFrozen value of false. If you want to use stateful advice--for example, for stateful mixins-use prototype advices along with a IsSingleton value of false.

13.5.3. Proxying Interfaces


Let's look at a simple example of ProxyFactoryObject in action. This example involves: A target object that will be proxied. This is the "personTarget" object definition in the example below. An IAdvisor and an IInterceptor used to provide advice. An AOP proxy object definition specifying the target object (the personTarget object) and the interfaces to proxy, along with the advices to apply.
<object id="personTarget" type="MyCompany.MyApp.Person, MyCompany"> <property name="name" value="Tony"/> <property name="age" value="51"/> </object> <object id="myCustomInterceptor" type="MyCompany.MyApp.MyCustomInterceptor, MyCompany"> <property name="customProperty" value="configuration string"/> </object> <object id="debugInterceptor" type="Spring.Aop.Advice.DebugAdvice, Spring.Aop"> </object> <object id="person" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop"> <property name="proxyInterfaces" value="MyCompany.MyApp.IPerson"/> <property name="target" ref="personTarget"/> <property name="interceptorNames"> <list> <value>debugInterceptor</value> <value>myCustomInterceptor</value> </list> </property> </object>

Note that the InterceptorNames property takes a list of strings: the object names of the interceptor or advisors in the current context. Advisors, interceptors, before, after returning and throws advice objects can be used. The ordering of advisors is significant.

Spring Framework (Version 1.3.2)

144

Aspect Oriented Programming with Spring.NET You might be wondering why the list doesn't hold object references. The reason for this is that if the ProxyFactoryObject's singleton property is set to false, it must be able to return independent proxy instances. If any of the advisors is itself a prototype, an independent instance would need to be returned, so it's necessary to be able to obtain an instance of the prototype from the context; holding a reference isn't sufficient. The "person" object definition above can be used in place of an IPerson implementation, as follows:
IPerson person = (IPerson) factory.GetObject("person");

Other objects in the same IoC context can express a strongly typed dependency on it, as with an ordinary .NET object:
<object id="personUser" type="MyCompany.MyApp.PersonUser, MyCompany"> <property name="person" ref="person"/> </object>

The PersonUser class in this example would expose a property of type IPerson. As far as it's concerned, the AOP proxy can be used transparently in place of a "real" person implementation. However, its type would be a proxy type. It would be possible to cast it to the IAdvised interface (discussed below). It's possible to conceal the distinction between target and proxy using an anonymous inline object, as follows. (for more information on inline objects see Section 5.3.2.3, Inner objects.) Only the ProxyFactoryObject definition is different; the advice is included only for completeness:
<object id="myCustomInterceptor" type="MyCompany.MyApp.MyCustomInterceptor, MyCompany"> <property name="customProperty" value="configuration string"/> </object> <object id="debugInterceptor" type="Spring.Aop.Advice.DebugAdvice, Spring.Aop"> </object> <object id="person" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop"> <property name="proxyInterfaces" value="MyCompany.MyApp.IPerson"/> <property name="target"> <!-- Instead of using a reference to target, just use an inline object --> <object type="MyCompany.MyApp.Person, MyCompany"> <property name="name" value="Tony"/> <property name="age" value="51"/> </object> </property> <property name="interceptorNames"> <list> <value>debugInterceptor</value> <value>myCustomInterceptor</value> </list> </property> </object>

This has the advantage that there's only one object of type Person: useful if we want to prevent users of the application context obtaining a reference to the un-advised object, or need to avoid any ambiguity with Spring IoC autowiring. There's also arguably an advantage in that the ProxyFactoryObject definition is self-contained. However, there are times when being able to obtain the un-advised target from the factory might actually be an advantage: for example, in certain test scenarios. 13.5.1. Applying advice on a per-proxy basis. Let's look at an example of configuring the proxy objects retrieved from ProxyFactoryObject.

Spring Framework (Version 1.3.2)

145

Aspect Oriented Programming with Spring.NET

<!-- create the object to reference --> <object id="RealObjectTarget" type="MyRealObject" singleton="false"/> <!-- create the proxied object for everyone to use--> <object id="MyObject" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop"> <property name="proxyInterfaces" value="MyInterface" /> <property name="isSingleton" value="false"/> <property name="targetName" value="RealObjectTarget" /> </object>

If you are using a prototype as the target you must set the TargetName property with the name/object id of your object and not use the property Target with a reference to that object. This will then allow a new proxy to be created around a new prototype target instance. Consider the above Spring.Net object configuration. Notice that the IsSingleton property of the ProxyFactoryObject instance is set to false. This means that each proxy object will be unique. Thus, you can configure each proxy object with its' own individual advice(s) using the following syntax
// Will return un-advised instance of proxy object MyInterface myProxyObject1 = (MyInterface)ctx.GetObject("MyObject"); // myProxyObject1 instance now has an advice attached to it. IAdvised advised = (IAdvised)myProxyObject1; advised.AddAdvice( new DebugAdvice() ); // Will return a new, un-advised instance of proxy object MyInterface myProxyObject2 = (MyInterface)ctx.GetObject("MyObject");

13.5.4. Proxying Classes


What if you need to proxy a class, rather than one or more interfaces? Imagine that in our example above, there was no IPerson interface, rather we needed to advise a class called Person that didn't implement any business interface. In this case the ProxyFactoryObject will proxy all public virtual methods and properties if no interfaces are explicitly specified or if no interfaces are found to be present on the target object. One can configure Spring.NET to force the use of class proxies, rather than interface proxies, by setting the ProxyTargetType property on the ProxyFactoryObject above to true. Class proxying works by generating a subclass of the target class at runtime. Spring.NET configures this generated subclass to delegate method calls to the original target: the subclass is used to implement the Decorator pattern, weaving in the advice. Class proxying should generally be transparent to users. However, there is an important issue to consider: Non-virtual methods can't be advised, as they can't be overridden. This may be a limiting factor when using existing code as it has been common practice not to declare methods as virtual by default.

13.5.5. Concise proxy definitions


Especially when defining transactional proxies, if you do not make use of the transaction namespace, you may end up with many similar proxy definitions. The use of parent and child object definitions, along with inner object definitions, can result in much cleaner and more concise proxy definitions. First a parent, template, object definition is created for the proxy:
<object id="txProxyTemplate" abstract="true" type="Spring.Transaction.Interceptor.TransactionProxyFactoryObject, Spring.Data">

Spring Framework (Version 1.3.2)

146

Aspect Oriented Programming with Spring.NET


<property name="PlatformTransactionManager" ref="adoTransactionManager"/> <property name="TransactionAttributes"> <name-values> <add key="*" value="PROPAGATION_REQUIRED"/> </name-values> </property> </object>

This will never be instantiated itself, so may actually be incomplete. Then each proxy which needs to be created is just a child object definition, which wraps the target of the proxy as an inner object definition, since the target will never be used on its own anyway.
<object name="testObjectManager" parent="txProxyTemplate"> <property name="Target"> <object type="Spring.Data.TestObjectManager, Spring.Data.Integration.Tests"> <property name="TestObjectDao" ref="testObjectDao"/> </object> </property> </object>

It is of course possible to override properties from the parent template, such as in this case, the transaction propagation settings:
<object name="testObjectManager" parent="txProxyTemplate"> <property name="Target"> <object type="Spring.Data.TestObjectManager, Spring.Data.Integration.Tests"> <property name="TestObjectDao" ref="testObjectDao"/> </object> </property> <property name="TransactionAttributes"> <name-values> <add key="Save*" value="PROPAGATION_REQUIRED"/> <add key="Delete*" value="PROPAGATION_REQUIRED"/> <add key="Find*" value="PROPAGATION_REQUIRED,readonly"/> </name-values> </property> </object>

Note that in the example above, we have explicitly marked the parent object definition as abstract by using the abstract attribute, as described previously, so that it may not actually ever be instantiated. Application contexts (but not simple object factories) will by default pre-instantiate all singletons. It is therefore important (at least for singleton object) that if you have a (parent) object definition which you intend to use only as a template, and this definition specifies a class, you must make sure to set the abstract attribute to true, otherwise the application context will actually try to pre-instantiate it.

13.6. Proxying mechanisms


Spring creates AOP proxies built at runtime through the use of the TypeBuilder API. Two types of proxies can be created, composition based or inheritance based. If the target object implements at least one interface then a composition based proxy will be created, otherwise an inheritance based proxy will be created. The composition based proxy is implemented by creating a type that implements all the interfaces specified on the target object. The actual class name of this dynamic type is 'GUID' like. A private field holds the target object and the dynamic type implementation will first execute any advice before or after making the target object method call on the target object. The inheritance based mechanism creates a dynamic type where that inherits from the target type. This lets you downcast to the target type if needed. Please note that in both cases a target method implementation that calls

Spring Framework (Version 1.3.2)

147

Aspect Oriented Programming with Spring.NET other methods on the target object will not be advised. To force inheritance based proxies you should either set the ProxyTargetType to true property of a ProxyFactory or set the XML namespace element proxy-target-type = true when using an AOP schema based configuration.

Note
An important alternative approach to inheritance based proxies is disucssed in the next section. In .NET 2.0 you can define the assembly level attribute, InternalsVisibleTo, to allow access of internal interfaces/classes to specified 'friend' assemblies. If you need to create an AOP proxy on an internal class/interface add the following code, [assembly: InternalsVisibleTo("Spring.Proxy")] and [assembly: InternalsVisibleTo("Spring.DynamicReflection")] to your to AssemblyInfo file.

13.6.1. InheritanceBasedAopConfigurer
There is an important limitation in the inheritance based proxy as described above, all methods that manipulate the state of the object should be declared as virtual. Otherwise some method invocations get directed to the private 'target' field member and others to the base class. Winform object are an example of case where this approach does not apply. To address this limitation, a new post-processing mechanism was introduced in version 1.2 that creates a proxy type without the private 'target' field. Interception advice is added directly in the method body before invoking the base class method. To use this new inheritance based proxy described in the note above, declare an instance of the InheritanceBasedAopConfigurer, and IObjectFactoryPostProcessor, in yoru configuraiton file. Here is an example.
<object type="Spring.Aop.Framework.AutoProxy.InheritanceBasedAopConfigurer, Spring.Aop"> <property name="ObjectNames"> <list> <value>Form*</value> <value>Control*</value> </list> </property> <property name="InterceptorNames"> <list> <value>debugInterceptor</value> </list> </property> </object> <object id="debugInterceptor" type="AopPlay.DebugInterceptor, AopPlay"/>

This configuraiton style is similar to the autoproxy by name approach described here and is particuarly appropriate when you want to apply advice to WinForm classes.

13.7. Creating AOP Proxies Programatically with the ProxyFactory


It's easy to create AOP proxies Programatically using Spring.NET. This enables you to use Spring.NET AOP without dependency on Spring.NET IoC. The following listing shows creation of a proxy for a target object, with one interceptor and one advisor. The interfaces implemented by the target object will automatically be proxied:
ProxyFactory factory = new ProxyFactory(myBusinessInterfaceImpl); factory.AddAdvice(myMethodInterceptor);

Spring Framework (Version 1.3.2)

148

Aspect Oriented Programming with Spring.NET


factory.AddAdvisor(myAdvisor); IBusinessInterface tb = (IBusinessInterface) factory.GetProxy();

The first step is to construct an object of type Spring.Aop.Framework.ProxyFactory. You can create this with a target object, as in the above example, or specify the interfaces to be proxied in an alternate constructor. You can add interceptors or advisors, and manipulate them for the life of the ProxyFactory. There are also convenience methods on ProxyFactory (inherited from AdvisedSupport) allowing you to add other advice types such as before and throws advice. AdvisedSupport is the superclass of both ProxyFactory and ProxyFactoryObject.

Note
Integrating AOP proxy creation with the IoC framework is best practice in most applications. We recommend that you externalize configuration from .NET code with AOP, as in general.

13.8. Manipulating Advised Objects


However you create AOP proxies, you can manipulate them using the Spring.Aop.Framework.IAdvised interface. Any AOP proxy can be cast to this interface, whatever other interfaces it implements. This interface includes the following methods and properties:
public interface IAdvised { IAdvisor[] Advisors { get; } IIntroductionAdvisor[] Introductions { get; } void void void void void void AddInterceptor(IInterceptor interceptor); AddInterceptor(int pos, IInterceptor interceptor); AddAdvisor(IAdvisor advisor); AddAdvisor(int pos, IAdvisor advisor); AddIntroduction(IIntroductionAdvisor advisor); AddIntroduction(int pos, IIntroductionAdvisor advisor);

int IndexOf(IAdvisor advisor); int IndexOf(IIntroductionAdvisor advisor); bool RemoveAdvisor(IAdvisor advisor); void RemoveAdvisor(int index); bool RemoveInterceptor(IInterceptor interceptor); bool RemoveIntroduction(IIntroductionAdvisor advisor); void RemoveIntroduction(int index); void ReplaceIntroduction(int index, IIntroductionAdvisor advisor); bool ReplaceAdvisor(IAdvisor a, IAdvisor b); }

The Advisors property will return an IAdvisor for every advisor, interceptor or other advice type that has been added to the factory. If you added an IAdvisor, the returned advisor at this index will be the object that you added. If you added an interceptor or other advice type, Spring.NET will have wrapped this in an advisor with a IPointcut that always returns true. Thus if you added an IMethodInterceptor, the advisor returned for this

Spring Framework (Version 1.3.2)

149

Aspect Oriented Programming with Spring.NET index will be a DefaultPointcutAdvisor returning your IMethodInterceptor and an IPointcut that matches all types and methods. The AddAdvisor() methods can be used to add any IAdvisor. Usually this will be the generic DefaultPointcutAdvisor, which can be used with any advice or pointcut (but not for introduction). By default, it's possible to add or remove advisors or interceptors even once a proxy has been created. The only restriction is that it's impossible to add or remove an introduction advisor, as existing proxies from the factory will not show the interface change. (You can obtain a new proxy from the factory to avoid this problem.) It's questionable whether it's advisable (no pun intended) to modify advice on a business object in production, although there are no doubt legitimate usage cases. However, it can be very useful in development: for example, in tests. I have sometimes found it very useful to be able to add test code in the form of an interceptor or other advice, getting inside a method invocation I want to test. (For example, the advice can get inside a transaction created for that method: for example, to run SQL to check that a database was correctly updated, before marking the transaction for roll back.) Depending on how you created the proxy, you can usually set a Frozen flag, in which case the IAdvised IsFrozen property will return true, and any attempts to modify advice through addition or removal will result in an AopConfigException. The ability to freeze the state of an advised object is useful in some cases: For example, to prevent calling code removing a security interceptor.

13.9. Using the "autoproxy" facility


So far we've considered explicit creation of AOP proxies using a ProxyFactoryObject or similar factory objects. For applications that would like create many AOP proxies, say across all the classes in a service layer, this approach can lead to a lengthy configuration file. To simplify the creation of many AOP proxies Spring provides "autoproxy" capabilities that will automatically proxy object definitions based on higher level criteria that will group together multiple objects as candidates to be proxied. This functionality is built on Spring "object post-processor" infrastructure, which enables modification of any object definition as the container loads. Refer to Section 5.9.1, Customizing objects with IObjectPostProcessors for general information on object post-processors. In this model, you set up some special object definitions in your XML object definition file configuring the auto proxy infrastructure. This allows you just to declare the targets eligible for autoproxying: you don't need to use ProxyFactoryObject. Using an autoproxy creator that refers to specific objects in the current context. A special case of autoproxy creation that deserves to be considered separately; autoproxy creation driven by source-level attributes. Autoproxying in general has the advantage of making it impossible for callers or dependencies to obtain an unadvised object. Calling GetObject("MyBusinessObject1") on an ApplicationContext will return an AOP proxy, not the target business object. The "inline object" idiom shown earlier in Section 13.5.3, Proxying Interfaces also offers this benefit.)

13.9.1. Autoproxy object definitions


The namespace Spring.Aop.Framework.AutoProxy provides generic autoproxy infrastructure, should you choose to write your own autoproxy implementations, as well as several out-of-the-box implementations. Two implementations are provided, ObjectNameAutoProxyCreator and DefaultAdvisorAutoProxyCreator. These are discussed in the following sections.

Spring Framework (Version 1.3.2)

150

Aspect Oriented Programming with Spring.NET 13.9.1.1. ObjectNameAutoProxyCreator The ObjectNameAutoProxyCreator automatically creates AOP proxies for object with names matching literal values or wildcards. The pattern matching expressions supported are of the form "*name", "name*", and "*name*" and exact name matching, i.e. "name". The following simple classes are used to demonstrate this autoproxy functionality.
public enum Language { English = 1, Portuguese = 2, Italian = 3 }

public interface IHelloWorldSpeaker { void SayHello(); }

public class HelloWorldSpeaker : IHelloWorldSpeaker { private Language language; public Language Language { set { language = value; } get { return language; } } public void SayHello() { switch (language) { case Language.English: Console.WriteLine("Hello World!"); break; case Language.Portuguese: Console.WriteLine("Oi Mundo!"); break; case Language.Italian: Console.WriteLine("Ciao Mondo!"); break; } } }

public class DebugInterceptor : IMethodInterceptor { public object Invoke(IMethodInvocation invocation) { Console.WriteLine("Before: " + invocation.Method.ToString()); object rval = invocation.Proceed(); Console.WriteLine("After: " + invocation.Method.ToString()); return rval; } }

The following XML is used to automatically create an AOP proxy and apply a Debug interceptor to object definitions whose names match "English*" and "PortugueseSpeaker".
<object id="ProxyCreator" type="Spring.Aop.Framework.AutoProxy.ObjectNameAutoProxyCreator, Spring.Aop"> <property name="ObjectNames"> <list> <value>English*</value> <value>PortugeseSpeaker</value> </list> </property>

Spring Framework (Version 1.3.2)

151

Aspect Oriented Programming with Spring.NET


<property name="InterceptorNames"> <list> <value>debugInterceptor</value> </list> </property> </object> <object id="debugInterceptor" type="AopPlay.DebugInterceptor, AopPlay"/> <object id="EnglishSpeakerOne" type="AopPlay.HelloWorldSpeaker, AopPlay"> <property name="Language" value="English"/> </object> <object id="EnglishSpeakerTwo" type="AopPlay.HelloWorldSpeaker, AopPlay"> <property name="Language" value="English"/> </object> <object id="PortugeseSpeaker" type="AopPlay.HelloWorldSpeaker, AopPlay"> <property name="Language" value="Portuguese"/> </object> <object id="ItalianSpeakerOne" type="AopPlay.HelloWorldSpeaker, AopPlay"> <property name="Language" value="Italian"/> </object>

As with ProxyFactoryObject, there is an InterceptorNames property rather than a list of interceptors, to allow correct behavior for prototype advisors. Named "interceptors" can be advisors or any advice type. The same advice will be applied to all matching objects. Note that if advisors are used (rather than the interceptor in the above example), the pointcuts may apply differently to different objects. Running the following simple program demonstrates the application of the AOP interceptor.
IApplicationContext ctx = ContextRegistry.GetContext(); IDictionary speakerDictionary = ctx.GetObjectsOfType(typeof(IHelloWorldSpeaker)); foreach (DictionaryEntry entry in speakerDictionary) { string name = (string)entry.Key; IHelloWorldSpeaker worldSpeaker = (IHelloWorldSpeaker)entry.Value; Console.Write(name + " says; "); worldSpeaker.SayHello(); }

The output is shown below


ItalianSpeakerOne says; Ciao Mondo! EnglishSpeakerTwo says; Before: Void SayHello() Hello World! After: Void SayHello() PortugeseSpeaker says; Before: Void SayHello() Oi Mundo! After: Void SayHello() EnglishSpeakerOne says; Before: Void SayHello() Hello World! After: Void SayHello()

13.9.1.2. DefaultAdvisorAutoProxyCreator A more general and extremely powerful auto proxy creator is DefaultAdvisorAutoProxyCreator. This will automatically apply eligible advisors in the current application context, without the need to include specific object names in the autoproxy advisor's object definition. It offers the same merit of consistent configuration and avoidance of duplication as ObjectNameAutoProxyCreator. Using this mechanism involves: Specifying a DefaultAdvisorAutoProxyCreator object definition

Spring Framework (Version 1.3.2)

152

Aspect Oriented Programming with Spring.NET Specifying any number of Advisors in the same or related contexts. Note that these must be Advisors, not just interceptors or other advices. This is necessary because there must be a pointcut to evaluate, to check the eligibility of each advice to candidate object definitions. The DefaultAdvisorAutoProxyCreator will automatically evaluate the pointcut contained in each advisor, to see what (if any) advice it should apply to each object defined in the application context. This means that any number of advisors can be applied automatically to each business object. If no pointcut in any of the advisors matches any method in a business object, the object will not be proxied. The DefaultAdvisorAutoProxyCreator is very useful if you want to apply the same advice consistently to many business objects. Once the infrastructure definitions are in place, you can simply add new business objects without including specific proxy configuration. You can also drop in additional aspects very easily--for example, tracing or performance monitoring aspects--with minimal change to configuration. The following example demonstrates the use of DefaultAdvisorAutoProxyCreator. Expanding on the previous example code used to demonstrate ObjectNameAutoProxyCreator we will add a new class, SpeakerDao, that acts as a Data Access Object to find and store IHelloWorldSpeaker objects.
public interface ISpeakerDao { IList FindAll(); IHelloWorldSpeaker Save(IHelloWorldSpeaker speaker); } public class SpeakerDao : ISpeakerDao { public System.Collections.IList FindAll() { Console.WriteLine("Finding speakers..."); // just a demo...fake the retrieval. Thread.Sleep(10000); HelloWorldSpeaker speaker = new HelloWorldSpeaker(); speaker.Language = Language.Portuguese; IList list = new ArrayList(); list.Add(speaker); return list; } public IHelloWorldSpeaker Save(IHelloWorldSpeaker speaker) { Console.WriteLine("Saving speaker..."); // just a demo...not really saving... return speaker; } }

The XML configuration specifies two Advisors, that is, the combination of advice (the behavior to add) and a pointcut (where the behavior should be applied). A RegularExpressionMethodPointcutAdvisor is used as a convenience to specify the pointcut as a regular expression that matches methods names. Other pointcuts of your own creation could be used, in which case a DefaultPointcutAdvisor would be used to define the Advisor. The object definitions for these advisors, advice, and SpeakerDao object are shown below
<object id="SpeachAdvisor" type="Spring.Aop.Support.RegularExpressionMethodPointcutAdvisor, Spring.Aop"> <property name="advice" ref="debugInterceptor"/> <property name="patterns"> <list> <value>.*Say.*</value> </list> </property>

Spring Framework (Version 1.3.2)

153

Aspect Oriented Programming with Spring.NET

</object> <object id="AdoAdvisor" type="Spring.Aop.Support.RegularExpressionMethodPointcutAdvisor, Spring.Aop"> <property name="advice" ref="timingInterceptor"/> <property name="patterns"> <list> <value>.*Find.*</value> </list> </property> </object> // Advice <object id="debugInterceptor" type="AopPlay.DebugInterceptor, AopPlay"/> <object id="timingInterceptor" type="AopPlay.TimingInterceptor, AopPlay"/> // Speaker DAO Object - has 'FindAll' Method. <object id="speakerDao" type="AopPlay.SpeakerDao, AopPlay"/> // HelloWorldSpeaker objects as previously listed.

Adding an instance of DefaultAdvisorAutoProxyCreator to the configuration file


<object id="ProxyCreator" type="Spring.Aop.Framework.AutoProxy.DefaultAdvisorAutoProxyCreator, Spring.Aop"/>

will apply the debug interceptor on all objects in the context that have a method that contains the text "Say" and apply the timing interceptor on objects in the context that have a method that contains the text "Find". Running the following code demonstrates this behavior. Note that the "Save" method of SpeakerDao does not have any advice applied to it.
IApplicationContext ctx = ContextRegistry.GetContext(); IDictionary speakerDictionary = ctx.GetObjectsOfType(typeof(IHelloWorldSpeaker)); foreach (DictionaryEntry entry in speakerDictionary) { string name = (string)entry.Key; IHelloWorldSpeaker worldSpeaker = (IHelloWorldSpeaker)entry.Value; Console.Write(name + " says; "); worldSpeaker.SayHello(); } ISpeakerDao dao = (ISpeakerDao)ctx.GetObject("speakerDao"); IList speakerList = dao.FindAll(); IHelloWorldSpeaker speaker = dao.Save(new HelloWorldSpeaker());

This produces the following output


ItalianSpeakerOne says; Before: Void SayHello() Ciao Mondo! After: Void SayHello() EnglishSpeakerTwo says; Before: Void SayHello() Hello World! After: Void SayHello() PortugeseSpeaker says; Before: Void SayHello() Oi Mundo! After: Void SayHello() EnglishSpeakerOne says; Before: Void SayHello() Hello World! After: Void SayHello() Finding speakers... Elapsed time = 00:00:10.0154745 Saving speaker...

The DefaultAdvisorAutoProxyCreator offers support for filtering (using a naming convention so that only certain advisors are evaluated, allowing use of multiple, differently configured, AdvisorAutoProxyCreators in the same

Spring Framework (Version 1.3.2)

154

Aspect Oriented Programming with Spring.NET factory) and ordering. Advisors can implement the Spring.Core.IOrdered interface to ensure correct ordering if this is an issue. The default is unordered. 13.9.1.3. PointcutFilteringAutoProxyCreator An AutoProxyCreator that identified objects to proxy by matching a specified IPointcut. 13.9.1.4. TypeNameAutoProxyCreator An AutoProxyCreator that identifies objects to proxy by matching their Type.FullName against a list of patterns. 13.9.1.5. AttributeAutoProxyCreator An AutoProxyCreator, that identifies objects to be proxied by checking any System.Attribute defined on a given type and that types interfaces. 13.9.1.6. AbstractFilteringAutoProxyCreator The base class for AutoProxyCreator implementations that mark objects eligible for proxying based on arbitrary criteria. 13.9.1.7. AbstractAutoProxyCreator This is the superclass of DefaultAdvisorAutoProxyCreator. You can create your own autoproxy creators by subclassing this class, in the unlikely event that advisor definitions offer insufficient customization to the behavior of the framework DefaultAdvisorAutoProxyCreator.

13.9.2. Using attribute-driven auto-proxying


A particularly important type of autoproxying is driven by attributes. The programming model is similar to using Enterprise Services with ServicedComponents. In this case, you use the DefaultAdvisorAutoProxyCreator, in combination with Advisors that understand attributes. The Advisor pointcut is identified by the presence of .NET attribute in the source code and it is configured via the data and/or methods of the attribute. This is a powerful alternative to identifying the advisor pointcut and advice configuration through traditional property configuration, either programmatic or through XML based configuration. Several of the aspect provided with Spring use attribute driven autoproxying. The most prominent example is Transaction support.

13.10. Using AOP Namespace


The AOP namespace allows you to define an advisor, i.e pointcut + 1 piece of advice, in a more declarative manner. Under the covers the DefaultAdvisorAutoProxyCreator is being used. Here is an example,
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.net/aop"> <aop:config> <aop:advisor id="getDescriptionAdvisor" pointcut-ref="getDescriptionCalls" adviceref="getDescriptionCounter"/> </aop:config> <object id="getDescriptionCalls"

Spring Framework (Version 1.3.2)

155

Aspect Oriented Programming with Spring.NET


type="Spring.Aop.Support.SdkRegularExpressionMethodPointcut, Spring.Aop"> <property name="patterns"> <list> <value>.*GetDescription.*</value> </list> </property> </object>

<object id="getDescriptionCounter" type="Spring.Aop.Framework.CountingBeforeAdvice, Spring.Aop.Tests"/> <object name="testObject" type="Spring.Objects.TestObject, Spring.Core.Tests"/>

</objects>

In this example, the TestObject, which implements the interface ITestObject, is having AOP advice applied to it. The method GetDescription() is specified as a regular expression pointcut. The aop:config tag and subsequent child tag, aop:advisor, brings together the pointcut with the advice. In order to have Spring.NET recognise the aop namespace, you need to declare the namespace parser in the main Spring.NET configuration section. For convenience this is shown below. Please refer to the section titled context configuration for more extensive information..
<configuration> <configSections> <sectionGroup name="spring"> <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/> <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /> <section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core"/> </sectionGroup> </configSections> <spring> <parsers> <parser type="Spring.Aop.Config.AopNamespaceParser, Spring.Aop" /> </parsers>

<context> <resource uri="config://spring/objects"/> </context> <objects xmlns="http://www.springframework.net"> ... </objects> </spring> </configuration>

13.11. Using TargetSources


Spring.NET offers the concept of a TargetSource, expressed in the Spring.Aop.ITargetSource interface. This interface is responsible for returning the "target object" implementing the joinpoint. The TargetSource implementation is asked for a target instance each time the AOP proxy handles a method invocation. Developers using Spring.NET AOP don't normally need to work directly with TargetSources, but this provides a powerful means of supporting pooling, hot swappable and other sophisticated targets. For example, a pooling TargetSource can return a different target instance for each invocation, using a pool to manage instances.

Spring Framework (Version 1.3.2)

156

Aspect Oriented Programming with Spring.NET If you do not specify a TargetSource, a default implementation is used that wraps a local object. The same target is returned for each invocation (as you would expect). Let's look at the standard target sources provided with Spring.NET, and how you can use them. When using a custom target source, your target will usually need to be a prototype rather than a singleton object definition. This allows Spring.NET to create a new target instance when required.

13.11.1. Hot swappable target sources


The org.Spring.NETframework.aop.target.HotSwappableTargetSource exists to allow the target of an AOP proxy to be switched while allowing callers to keep their references to it. Changing the target source's target takes effect immediately. The HotSwappableTargetSource is thread safe. You can change the target via the swap() method on HotSwappableTargetSource as follows:
HotSwappableTargetSource swapper = (HotSwappableTargetSource) objectFactory.GetObject("swapper"); object oldTarget = swapper.swap(newTarget);

The XML definitions required look as follows:


<object id="initialTarget" type="MyCompany.OldTarget, MyCompany"> </object> <object id="swapper" type="Spring.Aop.Target.HotSwappableTargetSource, Spring.Aop"> <constructor-arg><ref local="initialTarget"/></constructor-arg> </object> <object id="swappable" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop" > <property name="targetSource"> <ref local="swapper"/> </property> </object>

The above swap() call changes the target of the swappable object. Clients who hold a reference to that object will be unaware of the change, but will immediately start hitting the new target. Although this example doesn't add any advice--and it's not necessary to add advice to use a TargetSource--of course any TargetSource can be used in conjunction with arbitrary advice.

13.11.2. Pooling target sources


Using a pooling target source provides a programming model in which a pool of identical instances is maintained, with method invocations going to free objects in the pool. A crucial difference between Spring.NET pooling and pooling in .NET Enterprise Services pooling is that Spring.NET pooling can be applied to any POCO. (Plain old CLR object). As with Spring.NET in general, this service can be applied in a non-invasive way. Spring.NET provides out-of-the-box support using a pooling implementation based on Jakarta Commons Pool 1.1, which provides a fairly efficient pooling implementation. It's also possible to subclass Spring.Aop.Target.AbstractPoolingTargetSource to support any other pooling API. Sample configuration is shown below:

Spring Framework (Version 1.3.2)

157

Aspect Oriented Programming with Spring.NET


<object id="businessObjectTarget" type="MyCompany.MyBusinessObject, MyCompany" singleton="false"> ... properties omitted </object> <object id="poolTargetSource" type="Spring.Aop.Target.SimplePoolTargetSource, Spring.Aop"> <property name="targetObjectName" value="businessObjectTarget"/> <property name="maxSize" value="25"/> </object> <object id="businessObject" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop"> <property name="targetSource" ref="poolTargetSource"/> <property name="interceptorNames" value="myInterceptor"/> </object>

Note that the target object--"businessObjectTarget" in the example--must be a prototype. This allows the PoolingTargetSource implementation to create new instances of the target to grow the pool as necessary. See the SDK documentation for AbstractPoolingTargetSource and the concrete subclass you wish to use for information about it's properties: maxSize is the most basic, and always guaranteed to be present. In this case, "myInterceptor" is the name of an interceptor that would need to be defined in the same IoC context. However, it isn't necessary to specify interceptors to use pooling. If you want only pooling, and no other advice, don't set the interceptorNames property at all. It's possible to configure Spring.NET so as to be able to cast any pooled object to the Spring.Aop.Target.PoolingConfig interface, which exposes information about the configuration and current size of the pool through an introduction. You'll need to define an advisor like this:
<object id="poolConfigAdvisor" type="Spring.Object.Factory.Config.MethodInvokingFactoryObject, Spring.Aop"> <property name="target" ref="poolTargetSource" /> <property name="targetMethod" value="getPoolingConfigMixin" /> </object>

This advisor is obtained by calling a convenience method on the AbstractPoolingTargetSource class, hence the use of MethodInvokingFactoryObject. This advisor's name ('poolConfigAdvisor' here) must be in the list of interceptor names in the ProxyFactoryObject exposing the pooled object. The cast will look as follows:
PoolingConfig conf = (PoolingConfig) objectFactory.GetObject("businessObject"); Console.WriteLine("Max pool size is " + conf.getMaxSize());

Pooling stateless service objects is not usually necessary. We don't believe it should be the default choice, as most stateless objects are naturally threadsafe, and instance pooling is problematic if resources are cached. Simpler pooling is available using autoproxying. It's possible to set the TargetSources used by any autoproxy creator.

13.11.3. Prototype target sources


Setting up a "prototype" target source is similar to a pooling TargetSource. In this case, a new instance of the target will be created on every method invocation. Although the cost of creating a new object may not be high, the cost of wiring up the new object (satisfying its IoC dependencies) may be more expensive. Thus you shouldn't use this approach without very good reason. To do this, you could modify the poolTargetSource definition shown above as follows. (the name of the definition has also been changed, for clarity.)
<object id="prototypeTargetSource"

Spring Framework (Version 1.3.2)

158

Aspect Oriented Programming with Spring.NET


type="Spring.Aop.Target.PrototypeTargetSource, Spring.Aop"> <property name="targetObjectName" value="businessObject" /> </object>

There is only one property: the name of the target object. Inheritance is used in the TargetSource implementations to ensure consistent naming. As with the pooling target source, the target object must be a prototype object definition, the singleton property of the target should be set to false.

13.11.4. ThreadLocal target sources


ThreadLocal target sources are useful if you need an object to be created for each incoming request (per thread that is). The concept of a ThreadLocal provides a facility to transparently store resource alongside a thread. Setting up a ThreadLocalTargetSource is pretty much the same as was explained for the other types of target source:
<object id="threadlocalTargetSource" type="Spring.Aop.Target.ThreadLocalTargetSource, Spring.Aop"> <property name="targetObjectName" value="businessObject" /> </object>

13.12. Defining new Advice types


Spring.NET AOP is designed to be extensible. While the interception implementation strategy is presently used internally, it is possible to support arbitrary advice types in addition to interception around, before, throws, and after returning advice, which are supported out of the box. The Spring.Aop.Framework.Adapter package is an SPI (Service Provider Interface) package allowing support for new custom advice types to be added without changing the core framework. The only constraint on a custom Advice type is that it must implement the AopAlliance.Aop.IAdvice tag interface. Please refer to the Spring.Aop.Framework.Adapter namespace documentation for further information.

13.13. Further reading and resources


The Spring.NET team recommends the excellent AspectJ in Action by Ramnivas Laddad (Manning, 2003) for an introduction to AOP. If you are interested in more advanced capabilities of Spring.NET AOP, take a look at the test suite as it illustrates advanced features not discussed in this document.

Spring Framework (Version 1.3.2)

159

Chapter 14. Aspect Library


14.1. Introduction
Spring provides several aspects in the distribution. The most popular of which is transactional advice, located in the Spring.Data module. However, the aspects that are documented in this section are those contained within the Spring.Aop module itself. The aspects in within Spring.Aop.dll are Caching, Exception Handling, Logging, Retry, and Parameter Validation. Other traditional advice types such as validation, security, and thread management, will be included in a future release.

14.2. Caching
Caching the return value of a method or the value of a method parameter is a common approach to increase application performance. Application performance is increased with effective use of caching since layers in the application that are closer to the user can return information within their own layer as compared to making more expensive calls to retrieve that information from a lower, and more slow, layer such as a database or a web service. Caching also can help in terms of application scalability, which is generally the more important concern. The caching support in Spring.NET consists of base cache interfaces that can be used to specify a specific storage implementation of the cache and also an aspect that determines where to apply the caching functionality and its configuration. The base cache interface that any cache implementation should implement is Spring.Caching.ICache located in Spring.Core. Two implementations are provided, Spring.Caching.AspNetCache located in Spring.Web which stores cache entries within an ASP.NET cache and a simple implementation, Spring.Caching.NonExpiringCache that stores cache entries in memory and never expires these entries. Custom implementations based on 3rd party implementations, such as Oracle Coherence, or memcached, can be used by implementing the ICache interface. The cache aspect is Spring.Aspects.Cache.CacheAspect located in Spring.Aop. It consists of three pieces of functionality, the ability to cache return values, method parameters, and explicit eviction of an item from the cache. The aspect currently relies on using attributes to specify the pointcut as well as the behavior, much like the transactional aspect. Future versions will allow for external configuration of the behavior so you can apply caching to a code base without needing to use attributes in the code. The following attributes are available CacheResult - used to cache the return value CacheResultItems - used when returning a collection as a return value CacheParameter - used to cache a method parameter InvalidateCache - used to indicate one or more cache items should be invalidated. Each CacheResult, CacheResultItems, and CacheParameter attributes define the following properties. CacheName - the name of the cache implementation to use Key - a string representing a Spring Expression Language (SpEL) expression used as the key in the cache.

Spring Framework (Version 1.3.2)

160

Aspect Library Condition - a SpEL expression that should be evaluated in order to determine whether the item should be cached. TimeToLive - The amount of time an object should remain in the cache (in seconds). The InvalidateCache attribute has properties for the CacheName, the Key as well as the Condition, with the same meanings as listed previously. Each ICache implementation will have properties that are specific to a caching technology. In the case of AspNetCache, the two important properties to configure are: SlidingExperation - If this property value is set to true, every time the marked object is accessed it's TimeToLive value is reset to its original value Priority - the cache item priority controlling how likely an object is to be removed from an associated cache when the cache is being purged. TimeToLive - The amount of time an object should remain in the cache (in seconds). The values of the Priority enumeration are Low - low likelihood of deletion when cache is purged. Normal - default priority for deletion when cache is purged. High - high likelihood of deletion when cache is purged. NotRemovable - cache item not deleted when cache is purged. An important element of the applying these attributes is the use of the expression language that allows for calling context information to drive the caching actions. Here is an example taken from the Spring Air sample application of the AirportDao implementation that implements an interface with the method GetAirport(long id).
[CacheResult("AspNetCache", "'Airport.Id=' + #id", TimeToLive = "0:1:0")] public Airport GetAirport(long id) { // implementation not shown... }

The first parameter is the cache name. The second string parameter is the cache key and is a string expression that incorporates the argument passed into the method, the id. The cache key value cannot be null or an empty string (""). The method parameter names are exposed as variables to the key expression. The expression may also call out to other objects in the Spring container allowing for a more complex key algorithm to be encapsulated. The end result is that the Airport object is cached by id for 60 seconds in a cache named AspNetCache. The TimetoLive property could also have been specified on the configuration of the AspNetCache object. The configuration to enable the caching aspect is shown below
<object" id="CacheAspect" type="Spring.Aspects.Cache.CacheAspect, Spring.Aop"/> <object id="AspNetCache" type="Spring.Caching.AspNetCache, Spring.Web"> <property name="SlidingExpiration" value="true"/> <property name="Priority" value="Low"/> <property name="TimeToLive" value="00:02:00"/> </object> <!-- Apply aspects to DAOs --> <object type="Spring.Aop.Framework.AutoProxy.ObjectNameAutoProxyCreator, Spring.Aop">

Spring Framework (Version 1.3.2)

161

Aspect Library
<property name="ObjectNames"> <list> <value>*Dao</value> </list> </property> <property name="InterceptorNames"> <list> <value>CacheAspect</value> </list> </property> </object>

in this example an ObjectNameAutoProxyCreator was used to apply the cache aspect to objects that have Dao in their name. The AspNetCache setting for TimeToLive will override the TimeToLive value set at the method level via the attribute.

14.3. Exception Handling


In some cases existing code can be easily adopted to a simple error handling strategy that can perform one of the following actions translations - either wrap the thrown exception inside a new one or replace it with a new exception type (no inner exception is set). return value - the exception is ignored and a return value for the method is provided instead swallow - the exception is ignored. execute - Execute an abritrary Spring Expression Language (SpEL expression) The applicability of general exception handling advice depends greatly on how tangled the code is regarding access to local variables that may form part of the exception. Once you get familiar with the feature set of Spring declarative exception handling advice you should evaluate where it may be effectively applied in your code base. It is worth noting that you can still chain together multiple pieces of exception handling advice allowing you to mix the declarative approach shown in this section with the traditional inheritance based approach, i.e. implementing IThrowsAdvice or IMethodInterceptor. Declarative exception handling is expressed in the form of a mini-language relevant to the domain at hand, exception handling. This could be referred to as a Domain Specific Language (DSL). Here is a simple example, which should hopefully be self explanatory.
<object name="exceptionHandlingAdvice" type="Spring.Aspects.Exceptions.ExceptionHandlerAdvice, Spring.Aop"> <property name="exceptionHandlers"> <list> <value>on exception name ArithmeticException wrap System.InvalidOperationException</value> </list> </property> </object>

What this is instructing the advice to do is the following bit of code when an ArithmeticException is thrown, throw new System.InvalidOperationException("Wrapped ArithmeticException", e), where e is the original ArithmeticException. The default message, "Wrapped ArithmethicException" is automatically appended. You may however specify the message used in the newly thrown exception as shown below
on exception name ArithmeticException wrap System.InvalidOperationException 'My Message'

Similarly, if you would rather replace the exception, that is do not nest one inside the other, you can use the following syntax

Spring Framework (Version 1.3.2)

162

Aspect Library
on exception name ArithmeticException replace System.InvalidOperationException or on exception name ArithmeticException replace System.InvalidOperationException 'My Message'

Both wrap and replace are special cases of the more general translate action. An example of a translate expression is shown below
on exception name ArithmeticException translate new System.InvalidOperationException('My Message, Method Name ' + #method.Name, #e)

What we see here after the translate keyword is text that will be passed into Spring's expression language (SpEL) for evaluation. Refer to the chapter on the expression language for more details. One important feature of the expression evaluation is the availability of variables relating to the calling context when the exception was thrown. These are method - the MethodInfo object corresponding to the method that threw the exception args - the argument array to the method that threw the exception, signature is object[] target - the AOP target object instance. e - the thrown exception You can invoke methods on these variables, prefixed by a '#' in the expression. This gives you the flexibility to call special purpose constructors that can have any piece of information accessible via the above variables, or even other external data through the use of SpEL's ability to reference objects within the Spring container. You may also choose to 'swallow' the exception or to return a specific return value, for example
on exception name ArithmeticException swallow

or

on exception name ArithmeticException return 12

You may also simply log the exception


on exception name ArithmeticException,ArgumentException log 'My Message, Method Name ' + #method.Name

Here we see that a comma delimited list of exception names can be specified. The logging is performed using the Commons.Logging library that provides an abstraction over the underlying logging implementation. Logging is currently at the debug level with a logger name of "LogExceptionHandler" The ability to specify these values will be a future enhancement and likely via a syntax resembling a constructor for the action, i.e. log(Debug,"LoggerName"). Multiple exception handling statements can be specified within the list shown above. The processing flow is on exception, the name of the exception listed in the statement is compared to the thrown exception to see if there is a match. A comma separated list of exceptions can be used to group together the same action taken for different exception names. If the action to take is logging, then the logging action is performed and the search for other matching exception names continues. For all other actions, namely translate, wrap, replace, swallow, return, once an exception handler is matched, those in the chain are no longer evaluated. Note, do not confuse this handler chain with the general advice AOP advice chain. For translate, wrap, and replace actions a SpEL

Spring Framework (Version 1.3.2)

163

Aspect Library expression is created and used to instantiate a new exception (in addition to any other processing that may occur when evaluating the expression) which is then thrown. The exception handling DSL also supports the ability to provide a SpEL boolean expression to determine if the advice will apply instead of just filtering by the expression name. For example, the following is the equivalent to the first example based on exception names but compares the specific type of the exception thrown
on exception (#e is T(System.ArithmeticException)) wrap System.InvalidOperationException

The syntax use is 'on exception (SpEL boolean expression)' and inside the expression you have access to the variables of the calling context listed before, i.e. method, args, target, and e. This can be useful to implement a small amount of conditional logic, such as checking for a specific error number in an exception, i.e. (#e is T(System.Data.SqlException) && #e.Errors[0].Number in {156,170,207,208}), to catch and translate bad grammar codes in a SqlException. While the examples given above are toy examples, they could just as easily be changed to convert your application specific exceptions. If you find yourself pushing the limits of using SpEL expressions, you will likely be better off creating your own custom aspect class instead of a scripting approach. You can also configure the each of the Handlers individually based on the action keyword. For example, to configure the logging properties on the LogExceptionHandler.
<object name="logExceptionHandler" type="Spring.Aspects.Exceptions.LogExceptionHandler, Spring.Aop"> <property name="LogName" value="Cms.Session.ExceptionHandler" /> <property name="LogLevel" value="Debug"/> <property name="LogMessageOnly" value="true"/> </object> <object name="exceptionHandlingAdvice" type="Spring.Aspects.Exceptions.ExceptionHandlerAdvice, Spring.Aop"> <property name="ExceptionHandlerDictionary"> <dictionary> <entry key="log" ref="logExceptionHandler"/> </dictionary> </property> <property name="ExceptionHandlers"> <list> <value>on exception name ArithmeticException,ArgumentException log 'My Message, Method Name ' + #method.Name</value> </list> </property> </object>

You can also configure ExceptionHandlerAdvice to use an instance of IExceptionHandler by specifing it as an entry in the ExceptionHandlers list. This gives you complete control over all properties of the handler but you must set ConstraintExpressionText and ActionExpressionText which are normally parsed for you from the string. To use the case of configuring the LogExceptionHandler, this approach also lets you specify advanced logging functionality, but at a cost of some additional complexity. For example setting the logging level and pass the exception into the logging subsystem
<object name="exceptionHandlingAdvice" type="Spring.Aspects.Exceptions.ExceptionHandlerAdvice, Spring.Aop"> <property name="exceptionHandlers"> <list> <object type="Spring.Aspects.Exceptions.LogExceptionHandler"> <property name="LogName" value="Cms.Session.ExceptionHandler" /> <property name="ConstraintExpressionText" value="#e is T(System.Threading.ThreadAbortException)" /> <property name="ActionExpressionText" value="#log.Fatal('Request Timeout occured', #e)" /> </object> </list> </property> </object>

Spring Framework (Version 1.3.2)

164

Aspect Library The configuration of the logger name, level, and weather or not to pass the thrown exception as the second argument to the log method will be supported in the DSL style in a future release.

14.3.1. Language Reference


The general syntax of the language is
on exception name [ExceptionName1,ExceptionName2,...] [action] [SpEL expression]

or
on exception (SpEL boolean expression) [action] [SpEL expression]

The exception names are required as well as the action. The valid actions are log translate wrap replace return swallow execute The form of the expression depends on the action. For logging, the entire string is taken as the SpEL expression to log. Translate expects an exception to be returned from evaluation the SpEL expression. Wrap and replace are shorthand for the translate action. For wrap and replace you specify the exception name and the message to pass into the standard exception constructors (string, exception) and (string). The exception name can be a partial or fully qualified name. Spring will attempt to resolve the typename across all referenced assemblies. You may also register type aliases for use with SpEL in the standard manner with Spring.NET and those will be accessible from within the exception handling expression.

14.4. Logging
The logging advice lets you log the information on method entry, exit and thrown exception (if any). The implementation is based on the logging library, Common.Logging, that provides portability across different logging libraries. There are a number of configuration options available, listed below LogUniqueIdentifier LogExecutionTime LogMethodArguments LogReturnValue Separator LogLevel

Spring Framework (Version 1.3.2)

165

Aspect Library You declare the logging advice in IoC container with the following XML fragment. Alternatively, you can use the class SimpleLoggingAdvice programatically.
<object name="loggingAdvice" type="Spring.Aspects.Logging.SimpleLoggingAdvice, Spring.Aop"> <property name="LogUniqueIdentifier" value="true"/> <property name="LogExecutionTime" value="true"/> <property name="LogMethodArguments" value="true"/> <property name="LogReturnValue" value="true"/> <property name="Separator" <property name="LogLevel" value=";"/> value="Info"/>

<property name="HideProxyTypeNames" <property name="UseDynamicLogger" </object>

value="true"/> value="true"/>

The default values for LogUniqueIdentifier, LogExecutionTime, LogMethodArguments and LogReturnValue are false. The default separator value is ", " and the default log level is Common.Logging's LogLevel.Trace. You can set the name of the logger with the property LoggerName, for example "DataAccessLayer" for a logging advice that would be applied across the all the classes in the data access layer. That works well when using a 'category' style of logging. If you do not set the LoggerName property, then the type name of the logging advice is used as the logging name. Another approach to logging is to log based on the type of the object being called, the target type. Since often this is a proxy class with a relatively meaningless name, the property HideProxyTypeNames can be set to true to show the true target type and not the proxy type. The UseDynamicLogger property determines which ILog instance should be used to write log messages for a particular method invocation: a dynamic one for the Type getting called, or a static one for the Type of the trace interceptor. The default is to use a static logger. To further extend the functionality of the SimpleLoggingAdvice you can subclass SimpleLoggingAdvice and override the methods string GetEntryMessage(IMethodInvocation invocation, string idString) string
GetExceptionMessage(IMethodInvocation invocation, Exception e, TimeSpan

executionTimeSpan, string idString)

string

GetExitMessage(IMethodInvocation

invocation,

object

returnValue,

TimeSpan

executionTimeSpan, string idString)

The default implementation to calculate a unique identifier is to use a GUID. You can alter this behavior by overriding the method string CreateUniqueIdentifier(). The SimpleLoggingAdvice class inherits from AbstractLoggingAdvice, which has the abstract method object InvokeUnderLog(IMethodInvocation invocation, ILog log) and you can also override the method ILog GetLoggerForInvocation(IMethodInvocation invocation) to customize the logger instance used for logging. Refer to the SDK documentation for more details on subclassing AbstractLoggingAdvice. As an example of the Logging advice's output, adding the advice to the method
public int Bark(string message, int[] luckyNumbers) { return 4; }

And calling Bark("hello", new int[]{1, 2, 3} ), results in the following output


Entering Bark, 5d2bad47-62cd-435b-8de7-91f12b7f433e, message=hello; luckyNumbers=System.Int32[]

Spring Framework (Version 1.3.2)

166

Aspect Library
Exiting Bark, 5d2bad47-62cd-435b-8de7-91f12b7f433e, 30453.125 ms, return=4

The method parameters values are obtained using the ToString() method. If you would like to have an alternate implementation, say to view some values in an array, override the method string GetMethodArgumentAsString(IMethodInvocation invocation).

14.5. Retry
When making a distributed call it is often a common requirement to be able to retry the method invocation if there was an exception. Typically the exception will be due to a communication issue that is intermittent and retrying over a period of time will likely result in a successful invocation. When applying retry advice it is important to know if making two calls to the remote service will cause side effects. Generally speaking, the method being invoked should be idempotent, that is, it is safe to call multiple times. The retry advice is specified using a little language, i.e a DSL. A simple example is shown below
on exception name ArithmeticException retry 3x delay 1s

The meaning is: when an exception that has 'ArithmeticException' in its type name is thrown, retry the invocation up to 3 times and delay for 1 second between each retry event. You can also provide a SpEL (Spring Expression Language) expression that calculates the time interval to sleep between each retry event. The syntax for this is shown below
on exception name ArithmeticException retry 3x rate (1*#n + 0.5)

As with the exception handling advice, you may also specify a boolean SpEL that must evaluate to true in order for the advice to apply. For example
on exception (#e is T(System.ArithmeticException)) retry 3x delay 1s

on exception (#e is T(System.ArithmeticException)) retry 3x rate (1*#n + 0.5)

The time specified after the delay keyword is converted to a TimeSpan object using Spring's TimeSpanConverter. This supports setting the time as an integer + time unit. Time units are (d, h, m, s, ms) representing (days, hours, minutes, seconds, and milliseconds). For example; 1d = 1day, 5h = 5 hours etc. You can not specify a string such as '1d 5h'. The value that is calculated from the expression after the rate keyword is interpreted as a number of seconds. The power of using SpEL for the rate expression is that you can easily specify some exponential retry rate (a bigger delay for each retry attempt) or call out to a custom function developed for this purpose. When using a SpEL expression for the filter condition or for the rate expression, the following variable are available method - the MethodInfo object corresponding to the method that threw the exception args - the argument array to the method that threw the exception, signature is object[] target - the AOP target object instance. e - the thrown exception You declare the advice in IoC container with the following XML fragment. Alternatively, you can use the RetryAdvice class programatically.
<object name="exceptionHandlingAdvice" type="Spring.Aspects.RetryAdvice, Spring.Aop">

Spring Framework (Version 1.3.2)

167

Aspect Library
<property name="retryExpression" value="on exception name ArithmeticException retry 3x delay 1s"/> </object>

14.5.1. Language Reference


The general syntax of the language is
on exception name [ExceptionName1,ExceptionName2,...] retry [number of times]x [delay|rate] [delay time|SpEL rate expression]

or
on exception (SpEL boolean expression) retry [number of times]x [delay|rate] [delay time| SpELrate expression]

14.6. Transactions
The transaction aspect is more fully described in the section on transaction management.

14.7. Parameter Validation


Spring provides a UI-agnostic validation framework in which you can declare validation rules, both progammatically and declaratively, and have those rules evaluated against an arbitrary .NET object. Spring provides additional support for the rendering of validation errors within Spring's ASP.NET framework. (See the section on ASP.NET usage tips for more information.) However, validation is not confined to the UI tier. It is a common task that occurs across most, if not all, applications layers. Validation that is performed in the UI layer is often repeated in the service layer, in order to be proactive in case non UI-based clients invoke the service layer. Validation rules completely different from those used in the UI layer may also be used on the server side. To address some of the common needs for validation on the server side, Spring provides parameter validation advice so that applies Spring's validation rules to the method parameters. The class ParameterValidationAdvice is used in conjunction with the Validated attribute to specify which validation rules are applied to method parameters. For example, to apply parameter validation to the method SuggestFlights in the BookingAgent class used in the SpringAir sample application, you would apply the Validated attribute to the method parameters as shown below.
public FlightSuggestions SuggestFlights( [Validated("tripValidator")] Trip trip) { // unmodified implementation goes here }

The Validated attribute takes a string name that specifies the name of the validation rule, i.e. the name of the IValidator object in the Spring application context. The Validated attribute is located in the namespace Spring.Validation of the Spring.Core assembly. The configuration of the advice is to simply define the an instance of the ParameterValidationAdvice class and apply the advice, for example based on object names using an ObjectNameAutoProxyCreator, as shown below,
<object id="validationAdvice" type="Spring.Aspects.Validation.ParameterValidationAdvice, Spring.Aop"/> <object type="Spring.Aop.Framework.AutoProxy.ObjectNameAutoProxyCreator, Spring.Aop"> <property name="ObjectNames"> <list> <value>bookingAgent</value> </list> </property>

Spring Framework (Version 1.3.2)

168

Aspect Library
<property name="InterceptorNames"> <list> <value>validationAdvice</value> </list> </property> </object>

When the advised method is invoked first the validation of each method parameter is performed. If all validation succeeds, then the method body is executed. If validation fails an exception of the type ValidationException is thrown and you can retrieve errors information from its property ValidationErrors. See the SDK documentation for details.

Spring Framework (Version 1.3.2)

169

Chapter 15. Common Logging


15.1. Introduction
Spring uses a simple logging abstraction in order to provide a layer of indirection between logging calls made by Spring and the specific logging library used in your application (log4net, EntLib logging, NLog). The library is available for .NET 1.0, 1.1, and 2.0 with both debug and strongly signed assemblies. Since this need is not specific to Spring, the logging library was moved out of the Spring project and into a more general open source project called Common Infrastructure Libraries for .NET. The logging abstraction within the project is known as Common.Logging. Note that it is not the intention of this library to be a replacement for the many fine logging libraries that are out there. The API is incredibly minimal and will very likely stay that way. Please note that this library is intended only for use where the paramount requirement is portability and you will generally be better served by using a specific logging implementation so that you can leverage its advanced features and extended APIs to your advantage. You can find online documentation on how to configure Common.Logging is available in HTML , PDF, and HTML Help formats.

Spring Framework (Version 1.3.2)

170

Chapter 16. Testing


16.1. Introduction
The Spring team considers developer testing to be an absolutely integral part of enterprise software development. A thorough treatment of testing in the enterprise is beyond the scope of this chapter; rather, the focus here is on the value add that the adoption of the IoC principle can bring to unit testing; and on the benefits that the Spring Framework provides in integration testing.

16.2. Unit testing


One of the main benefits of Dependency Injection is that your code is much less likely to have any hidden dependencies on the runtime environment or other configuration subsystems. This allows for unit tests to be written in a manner such that the object under test can be simply instantiated with the new operator and have its dependences set in the unit test code. You can use mock objects (in conjunction with many other valuable testing techniques) to test your code in isolation. If you follow the architecture recommendations around Spring you will find that the resulting clean layering and componentization of your codebase will naturally faciliate easier unit testing. For example, you will be able to test service layer objects by stubbing or mocking DAO interfaces, without any need to access persistent data while running unit tests. True unit tests typically will run extremely quickly, as there is no runtime infrastructure to set up, i.e., database, ORM tool, or whatever. Thus emphasizing true unit tests as part of your development methodology will boost your productivity. The upshot of this is that you do not need this section of the testing chapter to help you write effective unit tests for your IoC-based applications.

16.3. Integration testing


However, it is also important to be able to perform some integration testing enabling you to test things such as: The correct wiring of your Spring IoC container contexts. Data access using ADO.NET or an ORM tool. This would include such things such as the correctness of SQL statements / or NHibernate XML mapping files. The Spring Framework provides support for integration testing when using NUnit and Microsoft's Testing framework 'MSTest'. The NUnit classses are located in the assembly Spring.Testing.NUnit.dll and the MSTest is located in Spring.Testing.Microsoft.dll.

Note
The Spring.Testing.NUnit.dll library is compiled against NUnit 2.5.1. Note that test runners integrated inside VS.NET may or may not support this version. At the time of this writing Reshaper 4.5.0 did not properly support NUnit 2.5.1. To use Resharper with NUnit 2.5.1 you need to download 4.5.1 RC2 or later. These namespaces provides NUnit and MSTest superclasses for integration testing using a Spring container. These superclasses provide the following functionality: Spring IoC container caching between test case execution.

Spring Framework (Version 1.3.2)

171

Testing The pretty-much-transparent Dependency Injection of test fixture instances (this is nice). Transaction management appropriate to integration testing (this is even nicer). A number of Spring-specific inherited instance variables that are really useful when integration testing.

16.3.1. Context management and caching


The Spring.Testing.NUnit and Spring.Testing.Microsoft namespace provides support for consistent loading of Spring contexts, and caching of loaded contexts. Similarly Spring.TestingSupport for the caching of loaded contexts is important, because if you are working on a large project, startup time may become an issue - not because of the overhead of Spring itself, but because the objects instantiated by the Spring container will themselves take time to instantiate. For example, a project with 50-100 NHibernate mapping files might take 10-20 seconds to load the mapping files, and incurring that cost before running every single test case in every single test fixture will lead to slower overall test runs that could reduce productivity. To address this issue, the AbstractDependencyInjectionSpringContextTests has an protected property that subclasses must implement to provide the location of context definition files:
protected abstract string[] ConfigLocations { get; }

Implementations of this method must provide an array containing the IResource locations of XML configuration metadata used to configure the application. This will be the same, or nearly the same, as the list of configuration locations specified in App.config/Web.config or other deployment configuration. By default, once loaded, the configuration file set will be reused for each test case. Thus the setup cost will be incurred only once (per test fixture), and subsequent test execution will be much faster. In the unlikely case that a test may 'dirty' the config location, requiring reloading - for example, by changing an object definition or the state of an application object - you can call the SetDirty() method on AbstractDependencyInjectionSpringContextTests to cause the test fixture to reload the configurations and rebuild the application context before executing the next test case.

16.3.2. Dependency Injection of test fixtures


When AbstractDependencyInjectionSpringContextTests (and subclasses) load your application context, they can optionally configure instances of your test classes by Setter Injection. All you need to do is to define instance variables and the corresponding setters. AbstractDependencyInjectionSpringContextTests will automatically locate the corresponding object in the set of configuration files specified in the ConfigLocations property. Consider the scenario where we have a class, HibernateTitleDao, that performs data access logic for say, the Title domain object. We want to write integration tests that test all of the following areas: The Spring configuration; basically, is everything related to the configuration of the HibernateTitleDao object correct and present? The Hibernate mapping file configuration; is everything mapped correctly and are the correct lazy-loading settings in place? The logic of the HibernateTitleDao; does the configured instance of this class perform as anticipated? Let's look at the NUnit test class itself (we will look at the configuration immediately afterwards).
/// Using NUnit

Spring Framework (Version 1.3.2)

172

Testing

[TestFixture] public class HibernateTitleDaoTests : AbstractDependencyInjectionSpringContextTests // this instance will be (automatically) dependency injected private HibernateTitleDao titleDao; // a setter method to enable DI of the 'titleDao' instance variable public HibernateTitleDao HibernateTitleDao { set { titleDao = value; } } [Test] public void LoadTitle() { Title title = this.titleDao.LoadTitle(10); Assert.IsNotNull(title); } // specifies the Spring configuration to load for this test fixture protected override string[] ConfigLocations { return new String[] { "assembly://MyAssembly/MyNamespace/daos.xml" }; } }

The file referenced by the ConfigLocations method ('classpath:com/foo/daos.xml') looks like this:
<?xml version="1.0" encoding="utf-8" ?> <objects xmlns="http://www.springframework.net"> <!-- this object will be injected into the HibernateTitleDaoTests class --> <object id="titleDao" type="Spring.Samples.HibernateTitleDao, Spring.Samples"> <property name="sessionFactory" ref="sessionFactory"/> </object> <object id="sessionFactory" type="Spring.Data.NHibernate.LocalSessionFactoryObject, Spring.Data.NHibernate"> <!-- dependencies elided for clarity --> </object> </objects>

The AbstractDependencyInjectionSpringContextTests classes uses autowire by type. Thus if you have multiple object definitions of the same type, you cannot rely on this approach for those particular object. In that case, you can use the inherited applicationContext instance variable, and explicit lookup using (for example) an explicit call to applicationContext.GetObject("titleDao"). Using AbstractDependencyInjectionSpringContextTests with MSTest is very similar.
/// Using Microsoft's Testing Framework [TestClass] public class HibernateTitleDaoTests : AbstractDependencyInjectionSpringContextTests // this instance will be (automatically) dependency injected private HibernateTitleDao titleDao; // a setter method to enable DI of the 'titleDao' instance variable public HibernateTitleDao HibernateTitleDao { set { titleDao = value; } } [Test] public void LoadTitle() { Title title = this.titleDao.LoadTitle(10); Assert.IsNotNull(title); } // specifies the Spring configuration to load for this test fixture protected override string[] ConfigLocations { return new String[] { "assembly://MyAssembly/MyNamespace/daos.xml" };

Spring Framework (Version 1.3.2)

173

Testing
} }

If you don't want dependency injection applied to your test cases, simply don't declare any set properties. Alternatively, you can extend the AbstractSpringContextTests - the root of the class hierarchy in the Spring.Testing.NUnit and Spring.Testing.Microsoft namespaces. It merely contains convenience methods to load Spring contexts, and performs no Dependency Injection of the test fixture. 16.3.2.1. Field level injection If, for whatever reason, you don't fancy having setter properties in your test fixtures, Spring can (in this one case) inject dependencies into protected fields. Find below a reworking of the previous example to use field level injection (the Spring XML configuration does not need to change, merely the test fixture).
[TestFixture] public class HibernateTitleDaoTests : AbstractDependencyInjectionSpringContextTests{ public HibernateTitleDaoTests() { // switch on field level injection PopulateProtectedVariables = true; } // this instance will be (automatically) dependency injected protected HibernateTitleDao titleDao; [TestMethod] public void LoadTitle() { Title title = this.titleDao.LoadTitle(10); Assert.IsNotNull(title); } // specifies the Spring configuration to load for this test fixture protected override string[] ConfigLocations { return new String[] { "assembly://MyAssembly/MyNamespace/daos.xml" }; } }

In the case of field injection, there is no autowiring going on: the name of your protected instances variable(s) are used as the lookup object name in the configured Spring container.

16.3.3. Transaction management


One common issue in tests that access a real database is their effect on the state of the persistence store. Even when you're using a development database, changes to the state may affect future tests. Also, many operations such as inserting to or modifying persistent data - cannot be done (or verified) outside a transaction. The AbstractTransactionalDbProviderSpringContextTests superclass (and subclasses) exist to meet this need. By default, they create and roll back a transaction for each test. You simply write code that can assume the existence of a transaction. If you call transactionally proxied objects in your tests, they will behave correctly, according to their transactional semantics. depends on a IPlatformTransactionManager object being defined in the application context. The name doesn't matter, due to the use of autowire by type.
AbstractTransactionalSpringContextTests

Typically you will extend the subclass, AbstractTransactionalDbProviderSpringContextTests. This also requires that a DbProvider object definition - again, with any name - be present in the configurations. It creates an AdoTemplate instance variable that is useful for convenient querying, and provides handy methods to delete the contents of selected tables (remember that the transaction will roll back by default, so this is safe to do).

Spring Framework (Version 1.3.2)

174

Testing If you want a transaction to commit - unusual, but occasionally useful when you want a particular test to populate the database - you can call the SetComplete() method inherited from AbstractTransactionalSpringContextTests. This will cause the transaction to commit instead of roll back. There is also convenient ability to end a transaction before the test case ends, through calling the EndTransaction() method. This will roll back the transaction by default, and commit it only if SetComplete() had previously been called. This functionality is useful if you want to test the behavior of 'disconnected' data objects, such as Hibernate-mapped objects that will be used in a web or remoting tier outside a transaction. Often, lazy loading errors are discovered only through UI testing; if you call EndTransaction() you can ensure correct operation of the UI through your NUnit test suite.

16.3.4. Convenience variables


When you extend the AbstractTransactionalDbProviderSpringContextTests class you will have access to the following protected instance variables: applicationContext inherited from the AbstractDependencyInjectionSpringContextTests superclass. Use this to perform explicit object lookup, or test the state of the context as a whole. (a
IConfigurableApplicationContext):

adoTemplate: inherited from AbstractTransactionalDbProviderSpringContextTests. Useful for querying to confirm state. For example, you might query before and after testing application code that creates an object and persists it using an ORM tool, to verify that the data appears in the database. (Spring will ensure that the query runs in the scope of the same transaction.) You will need to tell your ORM tool to 'flush' its changes for this to work correctly, for example using the Flush() method on NHibernate's ISession interface. Often you will provide an application-wide superclass for integration tests that provides further useful instance variables used in many tests.

Spring Framework (Version 1.3.2)

175

Part II. Middle Tier Data Access


This part of the reference documentation is concerned with othe middle tier, and specifically the data access responsibilities of said tier. Spring's comprehensive transaction management support is covered in some detail, followed by thorough coverage of the various middle tier data access frameworks and technologies that the Spring Framework integrates with. Chapter 17, Transaction management Chapter 18, DAO support Chapter 19, DbProvider Chapter 20, Data access using ADO.NET Chapter 21, Object Relational Mapping (ORM) data access

Spring Framework (Version 1.3.2)

176

Chapter 17. Transaction management


17.1. Introduction
Spring.NET provides a consistent abstraction for transaction management that provides the following benefits Provides a consistent programming model across different transaction APIs such as ADO.NET, Enterprise Services, System.Transactions, and NHibernate. Support for declarative transaction management with any of the above data access technologies Provides a simple API for programmatic transaction management Integrates with Spring's high level persistence integration APIs such as AdoTemplate. This chapter is divided up into a number of sections, each detailing one of the value-adds or technologies of the Spring Framework's transaction support. The chapter closes with some discussion of best practices surrounding transaction management. The first section, entitled Motivations describes why one would want to use the Spring Framework's transaction abstraction as opposed to using System.Transactions or a specific data access technology transaction API. The second section, entitled Key Abstractions outline the core classes as well as how to configure them. Th third section, entitled Declarative transaction management, covers support for declarative transaction management. The fourth section, entitled Programmatic transaction management, covers support for programmatic transaction management.

17.2. Motivations
The data access technology landscape is a broad one, within the .NET BCL there are three APIs for performing transaction management, namely ADO.NET, Enterprise Services, and System.Transactions. Other data access technologies such as object relational mappers and result-set mapping libraries are also gaining in popularity and each come with their own APIs for transaction management. As such, code is often directly tied to a particular transaction API which means you must make an up-front decision which API to use in your application. Furthermore, if the need arises to change your approach, it quite often will not be a simple refactoring. Using Spring's transaction API you can keep the same API across different data access technologies. Changing the underlying transaction implementation that is used is a simple matter of configuration or a centralized programmatic change as compared to a major overhauling. Hand in hand with the variety of options available is the establishment generally agreed upon best practices for data access. Martin Fowler's book, Patterns of Enterprise Application Architecture, is an excellent source of approaches to data access that have been successful in the real world. One approach that is quite common is to introduce a data access layer into your architecture. The data access layer is concerned not only with providing some portability between different data access technologies and databases but its scope is strictly related to data access. A simple data access layer would be not much more than data access objects (DAOs) with 'Create/Retrieve/ Update/Delete' (CRUD) methods devoid of any business logic. Business logic resides in another application layer, the business service layer, in which business logic will call one or more DAOs to fulfill a higher level end-user function.

Spring Framework (Version 1.3.2)

177

Transaction management In order to perform this end-user function with all-or-nothing transactional semantics, the transaction context is controlled by the business service layer (or other 'higher' layers). In such a common scenario, an important implementation detail is how to make the DAO objects aware of the 'outer' transaction started in another layer. A simplistic implementation of a DAO would perform its own connection and transaction management, but this would not allow grouping of DAO operations with the same transaction as the DAO is doing its own transaction/ resource management. As such there needs to be a means to transfer the connection/transaction pair managed in the business service layer to the DAOs. There are a variety of ways to do this, the most invasive being the explicitly pass a connection/transaction object as method arguments to your DAOs. Another way is to store the connection/transaction pair in thread local storage. In either case, if you are using ADO.NET you must invent some infrastructure code to perform this task. But wait, doesn't Enterprise Services solve this problem - and what about the functionality in the System.Transactions namespace? The answer is yes...and no. Enterprise Services lets you use the 'raw' ADO.NET API within a transaction context such that multiple DAO operations are grouped within the same transaction. The downside to Enterprise Services is that it always uses distributed (global) transactions via the Microsoft Distributed Transaction Coordinator (MS-DTC). For most applications this is overkill just to get this functionality as global transactions are significantly less performant than local ADO.NET transactions. There are similar issues with using the 'using TransactionScope' construct within the new System.Transactions namespace. The goal with TransactionScope is to define a, well - transaction scope - within a using statement. Plain ADO.NET code within that using block will then be a local ADO.NET based transaction if only a single transactional resource is accessed. However, the 'magic' of System.Transactions (and the database) is that local transactions will be promoted to distributed transactions when a second transaction resource is detected. The name that this goes by is Promotable Single Phase Enlistment (PSPE). However, there is a big caveat - opening up a second IDbConnection object to the same database with the same database string will trigger promotion from local to global transactions. As such, if your DAOs are performing their own connection management you will end up being bumped up to a distributed transaction. In order to avoid this situation for the common case of an application using a single database, you must pass around a connection object to your DAOs. It is also worth to note that many database providers (Oracle for sure) do not yet support PSPE and as such will always use a distributed transaction even if there is only a single database. Last but not least is the ability to use declarative transaction management. Not many topics in database transactionland give developers as much 'bang-for-the-buck' as declarative transactions since the noisy tedious bits of transactional API code in your application are pushed to the edges, usually in the form of class/method attributes. Only Enterprise Services offers this feature in the BCL. Spring fills the gap - it provides declarative transaction management if you are using local ADO.NET or System.Transactions (the most popular) or other data access technologies. Enterprise Services is not without it small warts as well, such as the need to separate your query/ retrieve operations from your create/update/delete operations if you want to use different isolation levels since declarative transaction metadata can only be applied at the class level. Nevertheless, all in all, Enterprise Services, in particular with the new 'Services Without Components' implementation for XP SP2/Server 2003, and hosted within the same process as your application code is as good as it gets out of the .NET box. Despite these positive points, it hasn't gained a significant mindshare in the development community. Spring's transaction support aims to relieve these 'pain-points' using the data access technologies within the BCL - and for other third party data access technologies as well. It provides declarative transaction management with a configurable means to obtain transaction option metadata - out of the box attributes and XML within Spring's IoC configuration file are supported. Finally, Spring's transaction support lets you mix data access technologies within a single transaction - for example ADO.NET and NHibernate operations.

Spring Framework (Version 1.3.2)

178

Transaction management With this long winded touchy/feely motivational section behind us, lets move on to see the code.

17.3. Key Abstractions


The key to the Spring transaction management abstraction is the notion of a transaction strategy. A transaction strategy is defined by the Spring.Transaction.IPlatformTransactionManager interface, shown below:
public interface IPlatformTransactionManager { ITransactionStatus GetTransaction( ITransactionDefinition definition ); void Commit( ITransactionStatus transactionStatus ); void Rollback( ITransactionStatus transactionStatus ); }

This is primarily a 'SPI' (Service Provider Interface), although it can be used Programatically. Note that in keeping with the Spring Framework's philosophy, IPlatformTransactionManager is an interface, and can thus be easily mocked or stubbed as necessary. IPlatformTransactionManager implementations are defined like any other object in the IoC container. The following implementations are provided AdoPlatformTransactionManager - local ADO.NET based transactions ServiceDomainPlatformTransactionManager - distributed transaction manager from Enterprise Services TxScopePlatformTransactionManager - local/distributed transaction manager from System.Transactions. HibernatePlatformTransactionManager - local transaction manager for use with NHibernate or mixed ADO.NET/NHibernate data access operations. Under the covers, the following API calls are made. For the AdoPlatformTransactionManager, Transaction.Begin(), Commit(), Rollback(). ServiceDomainPlatformTransactionManager uses the 'Services without Components' update so that your objects do not need to inherit from ServicedComponent or directly call the Enterprise Services API ServiceDomain.Enter(), Leave; ContextUtil.SetAbort(). TxScopePlatformTransactionManager calls; new TransactionScope(); .Complete(), Dispose(), Transaction.Current.Rollback(). Configuration properties for each transaction manager are specific to the data access technology used. Refer to the API docs for comprehensive information but the examples should give you a good basis for getting started. The HibernatePlatformTransactionManager is described more in the following section . The method returns a ITransactionStatus object, depending on a ITransactionDefinition parameters. The returned ITransactionStatus might represent a new or existing transaction (if there was a matching transaction in the current call stack - with the implication being that a ITransactionStatus is associated with a logical thread of execution.
GetTransaction(..)

The ITransactionDefinition interface specified Isolation: the degree of isolation this transaction has from the work of other transactions. For example, can this transaction see uncommitted writes from other transactions? Propagation: normally all code executed within a transaction scope will run in that transaction. However, there are several options specifying behavior if a transactional method is executed when a transaction context already exists: for example, simply continue running in the existing transaction (the common case); or suspending the existing transaction and creating a new transaction.

Spring Framework (Version 1.3.2)

179

Transaction management Timeout: how long this transaction may run before timing out (and automatically being rolled back by the underlying transaction infrastructure). Read-only status: a read-only transaction does not modify any data. Read-only transactions can be a useful optimization in some cases (such as when using NHibernate). These settings reflect standard transactional concepts. If necessary, please refer to a resource discussing transaction isolation levels and other core transaction concepts because understanding such core concepts is essential to using the Spring Framework or indeed any other transaction management solution. The ITransactionStatus interface provides a simple way for transactional code to control transaction execution and query transaction status. Regardless of whether you opt for declarative or programmatic transaction management in Spring, defining the correct IPlatformTransactionManager implementation is absolutely essential. In good Spring fashion, this important definition typically is made using via Dependency Injection. implementations normally require knowledge of the environment in which they work, ADO.NET, NHibernate, etc. The following example shows how a standard ADO.NET based IPlatformTransactionManager can be defined.
IPlatformTransactionManager

We must define a Spring IDbProvider and then use Spring's AdoPlatformTransactionManager, giving it a reference to the IDbProvider. For more information on the IDbProvider abstraction refer to the next chapter.
<objects xmlns='http://www.springframework.net' xmlns:db="http://www.springframework.net/database"> <db:provider id="DbProvider" provider="SqlServer-1.1" connectionString="Data Source=(local);Database=Spring;User ID=springqa;Password=springqa;Trusted_Connection=False"/> <object id="TransactionManager" type="Spring.Data.Core.AdoPlatformTransactionManager, Spring.Data"> <property name="DbProvider" ref="DbProvider"/> </object> . . . other object definitions . . . </objects>

We can also use a transaction manager based on System.Transactions just as easily, as shown in the following example
<object id="TransactionManager" type="Spring.Data.Core.TxScopeTransactionManager, Spring.Data"> </object>

Similarly for the HibernateTransactionManager as shown in the section on ORM transaction management. Note that in all these cases, application code will not need to change at all since, dependency injection is a perfect companion to using the strategy pattern. We can now change how transactions are managed merely by changing configuration, even if that change means moving from local to global transactions or vice versa.

17.4. Resource synchronization with transactions


How does application code participate with the resources (i.e. Connection/Transactions/Sessions) that are created/ reused/cleanedup via the different transaction managers? There are two approaches - a high-level and a low-level approach

Spring Framework (Version 1.3.2)

180

Transaction management

17.4.1. High-level approach


The preferred approach is to use Spring's high level persistence integration APIs. These do not replace native APIs, but internally handle resour