Title: Spring.NET
1- Spring.NET
- Introduction and Overview
- Michael.Stal_at_siemens.com
2Content
- Motivation
- Dependency Injection Basics
- Spring.NET Fundamentals
- Spring.NET AOP
- Further Ingredients
- Summary
- References
3Motivation
- Spring.NET is
- an application framework for buidling Enterprise
.NET applications - an IoC Container (Inversion of Control) that
manages and injects dependencies on behalf of
developers (DI Dependency Injection) - resembles the Java version but is not a naive
port - version 1.0 introduces DI and AOP
(Aspect-Oriented Programming). Upcoming versions
will add ASP.NET, Persistence, Remoting support
4Dependency Injection Explained (0)
What is a Dependency?
A Dependency between a source class X and a
target class Y occurs when each instance X needs
an instance of Y!
But whats the problem?
The problem is that X needs to know how to create
the Y instance!
5Dependency Injection Explained (1)
- Consider the following example
- Liability
- A depends on way to create or otherwise obtain a
B instance
Dependency resolved by A!
6Dependency Injection Explained (2)
- Other possibilities include setter injection and
constructor injection (A does not depend on how
Bs are created)
7Dependency Injection Explained (3)
- But how does the Container know which
dependencies to inject?
ltobject id a typeAgt ltset-prop
refbgt lt/objectgt ltobject id b type B/gt
Configuration of Dependencies
IoC Container
class A protected B _b public B b set
b value
Actual Implementation
8Dependency Injection Explained (4)
- Yet another possibility is field injection
(reflection-based) - But field injection is generally considered bad
design!
9IoC Containers for .NET
- PicoContainer.NET lightweight and highly
embeddable IoC container - StructureMap lightweight Inversion of Control
(IoC) Container written in C can improve the
architectural qualities of .NET apps by reducing
the mechanical costs of good design techniques - Castle Tools for application development
including small IoC container - Spring.NET full featured IoC container (port of
Java version)
10Spring.NET General Constituents
- Spring Core base library for DI
- Spring AOP enriches base container with AOP
concepts - Spring Web extends ASP.NET with DI, bidirectional
data binding - Spring Services enables the exposal of PONOs
(Plain Old .NET Objects) as Web/Enterprise/Remote
services - Spring Data provides a Data Access Layer. It also
eases ADO.NET - Spring.ORM provides integration of popular
persistence frameworks
11Introduction Example (1)
- Let us start with a Practice-First approach. An
object exampleObject that depends on other
objects
12Introduction Example (2)
- The configuration tells Spring.NET how objects
depend on each other
Object type namespace path class, assembly
ltobject id"exampleObject" type"Examples.Example
Object, ExamplesLibrary"gt ltproperty
name"objectOne" ref"anotherExampleObject"/gt
ltproperty name"objectTwo" ref"yetAnotherObject"/
gt ltproperty name"IntegerProperty"
value"1"/gt lt/objectgt ltobject id"anotherExampleO
bject" type"Examples.AnotherObject,
ExamplesLibrary"/gt ltobject id"yetAnotherObject"
type"Examples.YetAnotherObject,
ExamplesLibrary"/gt
Properties referring to other objects often
called dependencies or collaborators
13On Objects and Factories
- Spring.NET attempts
- to reduce dependencies between objects
- to act as non-invasive as possible almost no
dependencies of application from Spring.NET - IObjectFactory is
- the actual container that instantiates, manages
and configures collaborating objects. - represented by the interface IObjectFactory which
has many implementations (such as
XMLObjectFactory). - can be instantiated using new-operator or, even
better, via configuration file. Example -
- IResource input new FileSystemResource
("objects.xml") - IObjectFactory factory new XmlObjectFactory(inp
ut) - IApplicationContext denotes a superset of
IObjectFactory.
14Configuration
- Preferred way to create Object Factories and
Application contexts is via configuration
ltconfigurationgt ltconfigSectionsgt ltsectionGroup
name"spring"gt ltsection name"context"
type"Spring.Context.Support.ContextHandler,
Spring.Core"/gt ltsection name"objects"
type"Spring.Context.Support.DefaultSectionHandler
, Spring.Core" /gt lt/sectionGroupgt
lt/configSectionsgt ltspringgt ltcontextgt
ltresource uri"config//spring/objects"/gt
lt/contextgt ltobjectsgt ... lt/objectsgt
lt/springgt lt/configurationgt
Handlers used for Spring configuration section
Where to find object configuration, e.g. file,
assembly, config
Configuration of Spring managed objects
15Configuration contd
- Now instantiating and using ObjectFactory or
ApplicationContext is simple - Factories provide different methods
IApplicationContext ctx ContextRegistry.GetConte
xt() MyPerson person (MyPerson)
ctx.GetObject(myPerson")
IResource input new FileSystemResource
("objects.xml") XmlObjectFactory factory new
XmlObjectFactory(input) object foo
factory.GetObject ("foo") // gets the object
defined as 'foo' object bar factory "bar" //
same thing, just using the indexer
16Object Creation
- In most cases, objects are created using
constructors - Another possibility is using a static factory
method of a factory class - Or as the result of a non-static factory method
of another object
ltobject idmyObj" typeMyNS.MyObject,
MyLibrary"/gt
Type of factory not of created object!
ltobject idmyObj typeMyNS.MyFactory,
MyLibrary" factory-method"CreateInstance"/gt
ltobject idMyFactory" type"..."/gt ltobject
idMyObj" factory-method"CreateInstance" factory
-objectMyFactory"/gt
17Object Lifecycle
- Objects per default created as singletons
- objects id / name refers always to same instance
- lifecycle controlled by Spring
- Other possibility prototype (non-singleton)
- new object created for each separate access
access to id / name - lifecycle controlled by requester, not by Spring
factory
ltobject idmyObj" typeMyNS.MyObject,
MyLibrary" singleton"false"/gt ltobject
name"yetAnotherExample" typeMyNS.ExampleObjectT
wo, MyLibrary" singleton"true"/gt
18Types of Dependency Injection
- Spring .NET supports Property and Constructor
Injection - constructor-arg also applicable for factory
objects or static factory methods
ltobject idMyObject" typeMyNS.MixedIocObject,
MyLibrary"gt ltconstructor-arg name"objectOne"
ref"anotherExampleObject"/gt lt/objectgt ltobject
id"anotherExampleObject" typeMyNS.Class2,
MyLibrary"/gt public class MixedIocObject
private Class2 objectOne public
MixedIocObject (Class2 obj) this.objectOne
obj
19Ordering of Constructor Arguments
- constructor-arg elements are unordered. Thus, use
index - or names
ltobject namemyObj" typeMyNS.MYObject,
NyApp"gt ltconstructor-arg index"0"
value"7500000"/gt ltconstructor-arg index"1"
value"42"/gt lt/objectgt
ltobject namemyObj" typeMyNS.MYObject,
NyApp"gt ltconstructor-arg name"years"
value"7500000"/gt ltconstructor-arg
name"ultimateAnswer" value"42"/gt lt/objectgt
20Setting Complex Values
- Setting complex value types list, set,
name-values, dictionaries are supported - Inlining
- Additional Remarks
- Spring uses built-in TypeConverters to convert
from String to target type. It is easy to define
your own custom converters. - Special Spring.NET configuration element ltnullgt
to set values to null. - Other forms of references to collaborators
available ref local, ref parent
ltproperty name"SomeList"gt ltlistgt ltvaluegt
string lt/valuegt ltref object"myConnection"/gt
lt/listgt lt/propertygt
ltobject id"outer" type"..."gt ltproperty
name"target"gt ltobject type"ExampleApp.Answer
s, ExampleApp"gt ltproperty nameanswer"
value42"/gt lt/objectgt lt/propertygt lt/objectgt
21IFactoryObject
- Interface implemented by objects that are
themselves factories - Object GetObject() returns instance created by
factory - Bool isSingleton true if factory object returns
singletons - Type ObjectType object type returned by
GetObject() or null if not known in advance - Examples on next slides
22Advanced Dependency Injection
- It is possible to use other objects properties,
fields or methods for setting properties. - Spring.NET uses FactoryObjects for this purpose.
- The object theAge is instantiated using the
person objects embedded spouse.age property
ltobject name"person" type"Spring.Objects.TestObj
ect, Spring.Core.Tests"gt ltproperty
name"spouse"gt ltobject type"Spring.Objects.Tes
tObject, Spring.Core.Tests"gt ltproperty
name"age" value"21"/gt lt/objectgt
lt/propertygt lt/objectgt ltobject name"theAge"
type"Spring.Objects.Factory.Config.PropertyRetrie
vingFactoryObject, Spring.Core"gt ltproperty
name"TargetObject" ref"person"/gt ltproperty
name"TargetProperty" value"spouse.age"/gt lt/objec
tgt
23Advanced Dependency Injection (contd)
- An example for method-based injection
- This object will be created by calling the method
GetInstance (TargetMethod) of a MyClassFactory
object (TargetType) using the specified arguments
(Arguments) - Object can then be used for dependency injection
ltobject id"myObject" type"Spring.Objects.Factory
.Config.MethodInvokingFactoryObject,
Spring.Core"gt ltproperty name"TargetType"
value"Whatever.MyClassFactory, MyAssembly"/gt
ltproperty name"TargetMethod" value"GetInstance"/
gt lt!-- the ordering of arguments is significant
--gt ltproperty name"Arguments"gt ltlistgt
ltvaluegt1stlt/valuegt ltvaluegt2ndlt/valuegt
ltvaluegtand 3rd argumentslt/valuegt lt/listgt
lt/propertygt lt/objectgt
24Log4Net
- Another example for a IFactoryObject
implementation is log4Net
ltobjects xmlns"http//www.springframework.net" xm
lnsxsi"http//www.w3.org/2001/XMLSchema-instance
" xsischemaLocation"http//www.springframework.n
et http//www.springframework.net/xsd/spring-objec
ts.xsd" gt ltobject name"daoLogger"
type"Spring.Objects.Factory.Config.Log4NetFactory
Object, Spring.Core"gt ltproperty name"logName"
value"DAOLogger"/gt lt/objectgt ltobject
name"productDao" type"PropPlayApp.SimpleProductD
ao, PropPlayApp "gt ltproperty name"maxResults"
value"100"/gt ltproperty name"dbConnection"
ref"myConnection"/gt ltproperty name"log"
ref"daoLogger"/gt lt/objectgt ltobject
name"myConnection" type"System.Data.Odbc.OdbcCon
nection,
System.Data"gt ltproperty name"connectionstring
value"dsnMyDSNuidsapwdmy
Password"/gt lt/objectgt lt/objectsgt
25Lifecycle Callbacks
- Spring container can notify objects when they are
initialized or destroyed - Clasa may instead implement interfaces
(IDisposable, IInitializingObject) but then
dependencies on Spring.NET container are
introduced
ltobject id"exampleInitObject" type"Examples.Exam
pleObject" init-method"init destroy-methodclea
nup/gt public class ExampleObject public
void Init() // do some initialization
work public void cleanup() // do some
destruction work
26Some Additional Capabilities
- Autowiring is another option uses reflection to
determine and resolve dependencies (no config
required). Different types of autowiring
possible. Usually, better not to use autowiring. - For an object definition depends-on means this
object depends on other objects which should be
initialized first. - Objects can be defined with dependency checking
modes ao that Spring.NET will try to find out if
all properties of an object are defined. - Aliasing possible
- Object definitions might be abstract. Childs can
inherit
ltalias name"fromName" alias"toName"/gt
ltobject idparentObj abstracttruegt
ltproperty name"name" value"parent"/gt
ltproperty name"age" value"1"/gt lt/objectgt ltobject
idchildObj" type... parentparentObj"
init-method"Initialize"gt ltproperty name"name"
value"override"/gt lt/objectgt
27Object(Factory)PostProcessors
- A very powerful feature of Spring.NET are
ObjectPostProcessors and ObjectFactoryPostProcesso
rs - ObjectPostProcessors
- get invoked before and after object
initialization - can change object and return changed object to
Spring - for example used to wrap objects with proxies
- ObjectFactoryPostProcessors
- Can change object factories / application
contexts such as overwriting configuration
information or accessing it from another source - Examples
- PropertyPlaceHolderConfigurer
- PropertyOverrideConfigurer
- Object(Factory)PostProcessors automatically
detected by ApplicationContexts. Must be manually
registered with ObjectFactories.
28ApplicationContexts
- IApplicationContext objects superset of
IObjectFactory objects - Additional capabilities
- Automatic registration of Object(Factory)PostProce
ssors - Loading of hierarchical contexts
- Access to localized ressources
- Uniform access to ressources
- Loosely Coupled Event Propagation
- Should be always preferred over plain object
factories except for ressource-constrained
environments
29ApplicationContexts contd
- Example Hierarchical Contexts
- Example Resource Managers
ltspringgt ltcontextgt ltresource
uri"assembly//MyAssembly/MyProject/root-objects.
xml"/gt ltcontext name"mySubContext"gt
ltresource uri"file//objects.xml"/gt
lt/contextgt lt/contextgt lt/springgt
IApplicationContex ctx ContextRegistry.GetConte
xt("mySubContext")
ltobject name"myResourceManager"
type"Spring.Objects.Factory.Config.ResourceManage
rFactoryObject, Spring.Core"gt ltproperty
name"baseName"gt ltvaluegtSpring.Examples.AppConte
xt.MyResourcelt/valuegt lt/propertygt ltproperty
name"assemblyName"gt ltvaluegtSpring.Examples.AppC
ontextlt/valuegt lt/propertygt lt/objectgt // C
code string msg ctx.GetMessage("HelloMessage",
new object "Mr.",
"Anderson",CultureInfo.CurrentCulture )
30ApplicationContexts contd
- Spring.NET application containers automatically
register event publishers and send events to
detected known subscribers - Event reception by implementing
IApplicationListerener interface - Container itself also might send events such as
when closing a context. Example code (lot of
details omitted)
IApplicationContext ctx ContextRegistry.GetConte
xt() MyEventPublisher publisher
(MyEventPublisher)ctx.GetObject("MyEventPublisher"
) ctx.PublishEvents( publisher
) MyEventSubscriber subscriber
(MyEventSubscriber)ctx.GetObject("MyEventSubscribe
r") ctx.Subscribe( subscriber,
typeof(MyEventPublisher) )
31Spring.NET AOP
- One of the key components of Spring.NET
- AOP Concepts
- Aspect modularized cross-cutting concern
applicable to multiple objects - Joinpoint Execution point of a program such as a
method invocation or exception being thrown - Advice aspect to be conducted when program is at
a specific joinpoint. Such as before method
o.m() is executed write information to log - Pointcut set of joinpoints specifying when
advice should be executed - Advisor pair consisting of pointcut plus advice
- Introduction Using Spring.NET AOP to mix-in
functionality to objects - Target / advised object object where joinpoint
is contained and which gets proxied by Spring.NET
AOP - AOP Proxy Dynamic procy created by Spring.NET
including advice and delegating to advised object - Weaving process to produce an advised object
32General Design Principle
- Client retrieves application interface from proxy
- Client invoked method on application interface
- Proxy executes (chain of) advises on joinpoints
and delegates invocation to advised object
IProxyInterface
IApplicationInterface
Client
AOP Proxy
Advised Object
IApplicationInterface
Advice
Advice
Advice
33Motivating Example
- Here is a command pattern implementation
- Wed like to log each call to the Execute()
method on the console without touching our source
code using an advice
public interface ICommand void
Execute() public class ServiceCommand
ICommand public void Execute()
Console.Out.WriteLine("Service implementation...")
public class ConsoleLoggingAroundAdvice
IMethodInterceptor public object
Invoke(IMethodInvocation invocation)
Console.Out.WriteLine(calling method...")
object retv invocation.Proceed()
Console.Out.WriteLine(method returned "
retv) ¹ return retv º
34Motivating Example contd
- We have to tell Spring.NET about this intent
- Object gets proxied
ltobject id"consoleLoggingAroundAdvice"
type"Spring.Examples.AopQuickStart.ConsoleLogging
AroundAdvice"/gt ltobject id"myServiceObject
type"Spring.Aop.Framework.ProxyFactoryObject"gt
ltproperty name"target"gt ltobject
id"myServiceObjectTarget"
type"Spring.Examples.AopQuickStart.ServiceCommand
"/gt lt/propertygt ltproperty name"interceptorNam
es"gt ltlistgt ltvaluegtconsoleLoggingAroundA
dvicelt/valuegt lt/listgt lt/propertygt lt/objectgt
35Motivating Example contd
- Now we can use advised object. Note, that
actually we get the proxy not the target object
ICommand command (ICommand) ctx"myServiceObject
" command.Execute()
36Spring.NET AOP Fundamentals
- Pointcuts implement IPointCut
- Static and dynamic pointcuts (IsRuntimetrue)
possible - Dynamic pointcut example control flow pointcut
public interface IPointcut ITypeFilter
TypeFilter get IMethodMatcher MethodMatcher
get // Does type match? public interface
ITypeFilter bool Matches(Type type) // does
method match? public interface IMethodMatcher
bool IsRuntime get bool
Matches(MethodInfo method, Type
targetType) bool Matches(MethodInfo method,
Type targetType, object args)
37Pointcuts
- Pointcut operations union, intersection
- Regular Expression Pointcut (methods starting
with set..) - Attribute Pointcut (all methods with a specific
attribute)
ltobject id"settersAndAbsquatulatePointcut"
type"Spring.Aop.Support.SdkRegexpMethodPointcut,
Spring.Aop"gt ltproperty name"patterns"gt ltlistgt
ltvaluegt.set.lt/valuegt ltvaluegt.absquatulate
lt/valuegt lt/listgt lt/propertygt lt/objectgt
ltobject id"cachePointcut"
type"Spring.Aop.Support.AttributeMatchMethodPoint
cut, Spring.Aop"gt ltproperty name"Attribute"
value"Spring.Attributes.CacheAttribute,
Spring.Core"/gt lt/objectgt
38Pointcut Superclass
- Static Method Matcher
- You may inherit from this class to implement your
own pointcuts - By the way, in the case you are wondering In our
introduction we used the default TruePointcut
which maches for everything
public class TestStaticPointcut
StaticMethodMatcherPointcut public override
bool Matches(MethodInfo method, Type targetType)
// return true if custom criteria match
39Advisors
- Advisors combine a pointcut with an advice
- Regular Expression Advisor
- Attribute Advisor
ltobject id"settersAndAbsquatulateAdvisor"
type"Spring.Aop.Support.RegexpMethodPointcutAdvis
or, Spring.Aop"gt ltproperty name"advice"gt ltref
local"objectNameOfAopAllianceInterceptor"/gt lt/pr
opertygt ltproperty name"patterns"gt ltlistgt ltv
aluegt.set.lt/valuegt ltvaluegt.absquatulatelt/val
uegt lt/listgt lt/propertygt lt/objectgt
ltobject id"AspNetCacheAdvice"
type"Spring.Aop.Support.AttributeMatchMethodPoint
cutAdvisor, Spring.Aop"gt ltproperty
name"advice"gt ltobject type"Aspect.AspNetCac
heAdvice, Aspect"/gt lt/propertygt ltproperty
name"attribute" value"Framework.AspNetCacheAttri
bute, Framework" /gt lt/objectgt
40Advices
- Advices lifecycle per-class or per-instance
- Interception Around Advice
- Intercepts method invocation
- Code must call Proceed() to delegate invocation
to advised object
public class DebugInterceptor
IMethodInterceptor public object
Invoke(IMethodInvocation invocation)
Console.WriteLine("Before invocation0",
invocation) object rval invocation.Proceed()
Console.WriteLine("Invocation returned")
return rval
41Advices contd
- Before advice only called before actual method
invocation - Example counts number of calls
- Method Before() is only method within
IMethodBeforeAdvice
public class CountingBeforeAdvice
IMethodBeforeAdvice private int count public
void Before(MethodInfo method, object args,
object
target) count publi
c int Count get return count
42Advices contd
- After Returning Advice fires after method
invocation - Example counts number of calls
- Method AfterReturning() is only method within
IAfterReturningAdvice
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
43Advices contd
- After Throws Advice handles exceptions
- Method must have the following form
- Note IThrowsAdvice is just an empty marker
interface - Same implementation class may contain several
AfterThrowing methods
public class RemoteThrowsAdvice IThrowsAdvice
public void AfterThrowing(RemotingException
ex) // Do something with remoting
exception
AfterThrowing(MethodInfo method, Object args,
Object target, Exception subclass)
44Introductions
- Introductions used to add interfaces to existing
objects - Interface to be added
- Implementation class
public interface IAuditable DateTime
LastModifiedDate get set
public class AuditableMixin IAuditable
private DateTime date public
AuditableMixin() date new
DateTime() public DateTime LastModifiedDate
get return date set date value
45Introductions contd
- Now, we can implement an advisor
- Which applies the mixin on all objects. We might
have constrained the set of objects
public class AuditableAdvisor
DefaultIntroductionAdvisor public
AuditableAdvisor() base(new AuditableMixin())
46Using ProxyFactoryObject
- ProxyFactoryObject
- Basic way to create AOP Proxy
- Required if you need control over ordering and
application of pointcuts and advices - Implements IFactoryObject
- Benefit of using such a factory advices and
pointcuts can be managed by container
47Example for ProxyFactoryObject
- Proxy is returned that implements IPerson
ltobject id"personTarget" type"MyCompany.MyApp.Pe
rson, MyCompany"gt ltproperty name"name"
value"Tony"/gt ltproperty name"age"
value"51"/gt lt/objectgt ltobject id"myCustomInterce
ptor" type"MyCompany.MyApp.MyCustomInterceptor,
MyCompany"gt ltproperty name"customProperty"
value"configuration string"/gt lt/objectgt ltobject
id"debugInterceptor" type"Spring.Aop.Advice.Debu
gAdvice, Spring.Aop"gt lt/objectgt ltobject
id"person" type"Spring.Aop.Framework.ProxyFactor
yObject,
Spring.Aop"gt ltproperty
name"proxyInterfaces"
value"MyCompany.MyApp.IPerson"/gt ltproperty
name"target" ref"personTarget"/gt ltproperty
name"interceptorNames"gt ltlistgt ltvaluegtdebugI
nterceptorlt/valuegt ltvaluegtmyCustomInterceptorlt/
valuegt lt/listgt lt/propertygt lt/objectgt
Interfaces exported
Advised object
Applied advices
48Advanced Topics Spring.Services
- Spring.Services used with .NET Remoting,
Enterprise Services, Web services - Allows to export PONOs (Plain Old .NET Objects)
as COM objects, Web services, Remoting Objects - Allows to use dependency injection for these
entities - Allows to use AOP for these entities
- Example .NET Remoting
49Advanced Topics Spring.Web
- Spring.Web provides dependency injection to Web
pages and user and standard controls - It also supports bidirectional data binding
between controls on a form and a model - Bidirectional means that data can be stored from
controls to model on postbacks, and controls can
be initialized from models - It supports localization
- Spring.Web also externalizes flow control instead
of using Response.Redirect and Server.Transfer
50Advanced Topics Spring.Data and Spring.ORM
- Spring supports Transaction Management
- DAO pattern for using NHibernate, iBatis.NET,
ADO.NET - Should arrive soon. No support in version I was
able to test
51Further Ingredients of Spring.NET
- Threading and Concurrency Support following Doug
Lea ISync, SyncHolder, Latch, Semaphore - Object Pooling Support
52Installation 101
- Installation is simple
- First obtain new version of Spring.NET from
http//www.springframework.net/ (Ive used v1.1
Preview 2) - Install .msi file
- After installation youll find a new entry in
programs list - Read the online reference document at
http//www.springframework.net/doc/reference/html/
index.html (or the locally installed documents) - Spring.NET assemblies available in
ltYourDrivegt\Program
Files\Spring.NET\Spring.NET 1.1 Preview
2\bin\net\1.1\debugrelease\.dll - Additional support libraries in corresponding lib
paths
53Roadmap (taken from a presentation by Mark
Pollack,
- Spring 1.1 PR3 Release
- Framework for WinForms/SmartClient applications
1.2 - Integration withEnterprise Library (Security,
Cryptography, etc..) - ATLAS Integration
- TIBCO Messaging (RV/EMS)
- . . . Your requests and contributions . . .
- Spring.Net.Integration module in CVS
- Script to kick start full project
54Summary
- Spring now available for .NET developers. No more
reason to be jealous of Java colleagues - Spring.NET represents an important enhancement to
.NET DI enables your apps - It is not just a naive port of Spring for Java
- But, of course, it is subject to continuous
evolution - It takes a time to get used to it but then it
makes you more productive - My recommendation try it!
55Resources
- Documents and installation
- http//www.springframework.net/
- Books
- No special book on Spring.NET around, but I
recommend to read the Java literature - Professional Java Development with the Spring
Framework by Rod Johnson, Juergen Hoeller, Alef
Arendsen, Thomas Risberg, Colin Sampaleanu, Wrox
Press, 2005 - Pro Spring by Rob Harrop, Jan Machacek, Apress,
2005 - Articles
- http//msdn.microsoft.com/msdnmag/issues/05/09/Des
ignPatterns/
56QA
57Thanks for Attending