Transcript Spring.Net

Spring.Net
Steinar Dragsnes
email: steinar.dragsnes at viz.no
Agenda
Dependency Injection (IoC)
Spring.Net Services
AOP
Declarative Transaction Management through AOP
Additional Spring.Net components
 Spring.Web (out of scope)
 Spring.Integration
- NHibernate
Dependency Injection
Problem:
 How to put the various components and layers together without
creating a too tightly coupled system?
 How to allow for flexibility and technology changes (also
plugging in modules/components)?
IoC is not a new concept.
DI is a reaction to the heavyweight complexity in the mainstream
J2EE world (such as EJB framework).
Similar patterns; Service Locator, Factory.
Dependency Injection vs. Service Locator
Service Locator forces you to be dependent on the
locator.
With service locator the application class asks for a
service by an explicit message to the locator.
 PULL
With injection there is no explicit request, the service
appears in the application class.
 PUSH
Dependency Injection, less/no configuration of
dependency in your source.
Sample Application Architecture
Presentation
Layer
Service
Layer
Data
Access
Layer
Other
interfaces
Web interface
Service interfaces
Service implementations
DAO interfaces
DAO implementations
Data Repository
Domain
objects
Defining objects in the containter
Spring.Net uses XML to wire dependencies.
 Programmatic (C#)
 Annotations
The syntax is quite simple and straigth farwards:
<object id=”name” type=”namespace.class, assembly />
Within the object tags you can specify constructor args
and properties, just as you would do in a normal factory.
Example, UserService
public class UserService : IUserService
{
private IUserDao dao;
public UserService(IUserDao dao)
{
this.dao = dao;
}
...
}
Defining the service in the IoC container
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net">
...
<object id=”userService” type="SpringApp.Services.UserService, SpringApp.Core">
<!-- Injecting the UserDao into the service. -->
<constructor-arg name="dao" ref=”userDao" />
</object>
...
</objects>
public class UserService : IUserService
{
private IUserDao dao;
public UserService(IUserDao dao)
{
this.dao = dao;
}
...
}
Defining the service in the IoC container
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net">
...
<object id=”userDao" type="SpringApp.Data.NHibernate12.UserDao,
SpringApp.Data.NHibernate">
<property name="SessionFactory" ref="SessionFactory"/>
</object>
<object id=”userService” type="SpringApp.Services.UserService, SpringApp.Core">
<!-- Injecting the UserDao into the service. -->
<constructor-arg name="dao" ref=”userDao" />
</object>
...
</objects>
Container configuration
<configuration>
<configSections>
<sectionGroup name="spring">
<section name="context"
type="Spring.Context.Support.ContextHandler, Spring.Core"/>
</sectionGroup>
</configSections>
<spring>
<context>
<resource uri=“file://~/config/objects.xml"/>
</context>
</spring>
</configuration>
IApplicationContext context = ContextRegistry.GetContext();
IUserService service = (IUserService) context.GetObject(“userService");
DI and Application Wiring
Through this very basic example you can get an idea on how you
can configure and wire your application together.
Tips:
 Consider when you want to use DI and apply it where it gives
you most ”bang for the buck”.
 In the beginning, debugging the XML configuration can be
difficult.
 Whenever experiencing difficulties, do not hesitate to ask for
help at the Spring.Net user forum
[http://forum.springframework.net].
DI brings advantages
Easy to switch implementations without the need for a
recompile.
Easy to facilitate testing, unit testing, integration testing.
Better separation of concerns.
Less dependencies within your application.
Easier to write plugin modules.
Encourages best practices such as TDD, decoupling,
seperation of concerns, design by contract.
Spring.Net Services
Portable Service Abstractions (PSA)
 Write plain service classes (PONO)
 Decide later how you will distribute your objects
 Specify distribution technology through
configuration.
• .Net Remoting
• .Net Enterprise Services
• Web Services
Spring.Net Services
How is this achieved?
 Spring.Net creates a proxy at runtime that meets the
implementation requirements of a specific
distributed technology
<object id="saoUserService" type="Spring.Remoting.SaoExporter, Spring.Services">
<property name=“TargetName" value=“userService"/>
<property name=“ServiceName" value=“RemotedUserService"/>
</object>
<object id=“userService" type="SpringApp.Services.UserService, SpringApp.Core">
<constructor-arg name=“dao" ref=“userDao"/>
</object>
Enterprise Services
<object id=“comUserServiceComponent" type="Spring.EnterpriseServices.ServicedComponentExporter,
Spring.Services">
<property name="TargetName" value=“userService" />
<property name="TypeAttributes">
<list>
<object type="System.EnterpriseServices.TransactionAttribute, System.EnterpriseServices" />
</list>
</property>
…
</object>
<object type="Spring.EnterpriseServices.EnterpriseServicesExporter, Spring.Services">
<property name="ApplicationName"><value>Demo App</value></property>
<property name="AccessControl">
<object type=“…ApplicationAccessControlAttribute, …">
<property name="AccessChecksLevel"><value>ApplicationComponent</value></property>
</object>
</property>
<property name="Roles"><list><value>Admin : Administrator role</value></list></property>
<property name="Components">
<list>
<ref object=“comUserServiceComponent" />
</list>
</property>
<property name="Assembly"><value>SpringApp.Com.UserService</value></property>
</object>
Accessing the service from the client
Administrative type registration is performed using the wellknown
element in the client configuration section
Seperate service interface and implementation in different
assemblies
Thus clients can obtain a proxy to a specific implementation with
only a reference to the interface assembly.
<object id=“userService" type="Spring.Remoting.SaoFactoryObject, Spring.Services">
<property name=“ServiceInterface" value=“SpringApp.Services.IUserService,
SpringApp.IServices"/>
<property name=“ServiceUrl" value=“tcp://localhost:8005/RemotedUserService"/>
</object>
IApplicationContext context = ContextRegistry.GetContext();
IUserService service = (IUserService) context.GetObject(“userService");
Aspect Oriented Programming
Problem, an operation that is done repeatedly across many
classes and in the same class.
Logging, security, transaction management to name a few.
Extract the logic of these operations (aspects) into it’s own class.
Apply this logic at various locations in your code (pointcut).
Terminology
 ‘what’ = advice, ‘where’ = pointcut
Aspect Oriented Programming
Spring.Net provides an aspect library:
 Logging
 ExceptionHandling
 Caching
 Transaction
 Parameter Validation
Easy to create own aspects.
 Create a class that implements one of the interceptor contracts
(e.g. IMethodInterceptor)
 Create a custome attribute
 Either connect attribute and advice programmatic or preferably
in the Spring.Net container.
Configuring Aspects
<object id="transactionInterceptor" type="Spring.Transaction.Interceptor.TransactionInterceptor, Spring.Data">
<property name="TransactionManager" ref="hibernateTransactionManager"/>
<property name="TransactionAttributeSource">
<object type="Spring.Transaction.Interceptor.AttributesTransactionAttributeSource, Spring.Data"/>
</property>
</object>
<object id="transactionAdvisor"
type="Spring.Transaction.Interceptor.TransactionAttributeSourceAdvisor, Spring.Data">
<property name="TransactionInterceptor" ref="transactionInterceptor"/>
</object>
Configuring Aspects
<object id="autoProxyCreator" type="SpringApp.Aop.CustomAdvisorAutoProxyCreator, SpringApp.Core">
<property name="AttributeAdviceMap">
<dictionary>
<!-- Each entry creates an instance of Spring.Aop.Support.AttributeMatchMethodPointcutAdvisor -->
<entry key="Viz.Core.Aop.Attributes.Log4NetLoggingAroundAttribute,Viz.Core”
value="Viz.Core.Aop.Advice.Log4NetLoggingAroundAdvice,Viz.Core"/>
<entry key="Viz.Core.Security.Attributes.AccessPriviligesAttribute,Viz.Core"
value="Viz.Core.Security.Advices.AccessPriviligesAdvice,Viz.Core"/>
<entry key="Viz.Core.Persistence.nHibernate.Session.Attributes.SessionScopeAttribute,Viz.Core.Persistence"
value="Viz.Core.Persistence.nHibernate.Session.Advices.SessionScopeAdvice,Viz.Core.Persistence"/>
</dictionary>
</property>
</object>
How this turns out in code
[Transaction(ReadOnly = true)]
public IList LoadAll(Type entityType)
{
return dao.LoadAll(entityType);
}
[Logging]
[Permission(Permissions = Permission.ContentManager, Permission.PortfolioManager)
[Transaction]
public object SaveOrUpdate(object entity)
{
return dao.SaveOrUpdate(entity);
}
Spring.Net Data Access API
Provides a consistent programming model across different
transaction APIs such as ADO.NET, Enterprise Services,
System.Transactions, and NHibernate.
Declarative transaction management with any of the above data
access technologies (AOP)
You can keep the same API across different data access
technologies.
Changing the underlying transaction implementation is a matter of
configuration or a centralized programmatic change as compared
to a major overhauling.
Spring.Net NHibernate Integration
Spring.Net provides integration with NHibernate in terms of
 Resource management
• DbProvider
• SessionFactory
• Sessions, SessionScope, OSIV
 DAO implementation support
 Transaction strategies
You can use Spring's support for NHibernate without using the full
Sprting.Net stack or Spring’s transaction management