Our new project will use Spring.net 2.0, hence, I started learning how to use it. Need to create a prototype implementation for team.
How to install it?
Like other .net library, you just copy the dll files
(Spring.Services.dll, Spring.Aop.dll and Spring.Core, Common.Logging.dll and the counterpart xmls files to
to your project and do the configuration.
How to use it?
Take Spring Integration with WCF(Windows Communication Foundation) as an example,
Step 1: define the Services
namespace Spring.WcfQuickStart
{
[Serializable]
public class BinaryOperationArgs
{
private double x;
private double y;
public BinaryOperationArgs(double x, double y)
{
this.x = x;
this.y = y;
}
public double X
{
get { return x; }
}
public double Y
{
get { return y; }
}
}
[Serializable]
public class OperationResult
{
private double result;
public OperationResult(double result)
{
this.result = result;
}
public double Result
{
get { return result; }
}
}
[ServiceContract(Namespace = "http://Spring.WcfQuickStart")]
public interface ICalculator
{
[OperationContract]
double Add(double n1, double n2);
[OperationContract]
double Subtract(double n1, double n2);
[OperationContract]
double Multiply(double n1, double n2);
[OperationContract]
double Divide(double n1, double n2);
[OperationContract]
string GetName();
[OperationContract]
OperationResult Power(BinaryOperationArgs args);
}
}
Step 2: Implementation
namespace Spring.WcfQuickStart
{
public class CalculatorService : ICalculator
{
// the value will be injected in weaving time
private int sleepInSeconds;
public int SleepInSeconds
{
get { return sleepInSeconds; }
set { sleepInSeconds = value; }
}
public double Add(double n1, double n2)
{
Thread.Sleep(sleepInSeconds * 1000);
return n1 + n2;
}
public double Subtract(double n1, double n2)
{
Thread.Sleep(sleepInSeconds * 1000);
return n1 - n2;
}
public double Multiply(double n1, double n2)
{
Thread.Sleep(sleepInSeconds * 1000);
return n1 * n2;
}
public double Divide(double n1, double n2)
{
Thread.Sleep(sleepInSeconds * 1000);
return n1 / n2;
}
public OperationResult Power(BinaryOperationArgs args)
{
// do something
return new OperationResult(Math.Pow(args.X, args.Y));
}
public string GetName()
{
Thread.Sleep(SleepInSeconds * 1000);
return "WebApp Calculator";
}
}
}
Step 4: Define the IMethodInterceptor
public class SimplePerformanceInterceptor : IMethodInterceptor
{
private string prefix = "Invocation took";
public string Prefix
{
get { return prefix; }
set { prefix = value; }
}
#region IMethodInterceptor Members
// Summary:
// Implement this method to perform extra treatments before and after the call
// to the supplied invocation.
//
// Parameters:
// invocation:
// The method invocation that is being intercepted.
public object Invoke(IMethodInvocation invocation)
{
DateTime start = DateTime.Now;
try
{
return invocation.Proceed();
}
finally
{
DateTime stop = DateTime.Now;
TimeSpan time = stop - start;
Console.Out.WriteLine(Prefix + " " + time);
}
}
#endregion
}
Step 3: AOP codes
public class SimplePerformanceInterceptor : IMethodInterceptor
{
private string prefix = "Invocation took";
public string Prefix
{
get { return prefix; }
set { prefix = value; }
}
#region IMethodInterceptor Members
/// <summary>
/// IMethodInvocation
// Summary:
// Gets the method invocation that is to be invoked.
//
// Remarks:
// This property is a friendly implementation of the AopAlliance.Intercept.IJoinpoint.StaticPart
// property. It should be used in preference to the AopAlliance.Intercept.IJoinpoint.StaticPart
// property because it provides immediate access to the underlying method without
// the need to resort to a cast.
// MethodInfo Method { get; }
//
// Summary:
// Gets the proxy object for the invocation.
// object Proxy { get; }
//
// Summary:
// Gets the target object for the invocation.
// object Target { get; }
//
// Summary:
// Gets the type of the target object.
// Type TargetType { get; }
/// </summary>
/// <param name="invocation"></param>
/// <returns></returns>
public object Invoke(IMethodInvocation invocation)
{
DateTime start = DateTime.Now;
try
{ // deal with something about invocation
//...
return invocation.Proceed();
}
finally
{
DateTime stop = DateTime.Now;
TimeSpan time = stop - start;
Console.Out.WriteLine(Prefix + " " + time);
}
}
#endregion
}
Step 4: Configuration - web.config
<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 Configuration -->
<spring>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net"
xmlns:aop="http://www.springframework.net/aop">
<!-- Service definition -->
<object id="calculator" type="Spring.WcfQuickStart.CalculatorService, Spring.WcfQuickStart.ServerWeb"
singleton="false">
<!-- the value to be injected when weaved -->
<property name="SleepInSeconds" value="1"/>
</object>
<object id="serviceOperation" type="Spring.Aop.Support.SdkRegularExpressionMethodPointcut, Spring.Aop">
<property name="pattern" value="^Spring.WcfQuickStart.*"/>
</object>
<object id="perfAdvice" type="Spring.WcfQuickStart.SimplePerformanceInterceptor, Spring.WcfQuickStart.ServerWeb">
<!-- the value of Prefix will be injected in running time
<property name="Prefix" value="Service Layer Performance"/>
</object>
<!-- weave the advices to each crosscutting around the pointcuts,
<aop:config>
<aop:advisor pointcut-ref="serviceOperation" advice-ref="perfAdvice"/>
</aop:config>
</objects>
</spring>
<!-- WCF Service Configuration -->
<system.serviceModel>
<services>
<service name="calculator" behaviorConfiguration="DefaultBehavior">
<endpoint address="" binding="basicHttpBinding" contract="Spring.WcfQuickStart.ICalculator"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DefaultBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<appSettings/>
<connectionStrings/>
<system.web>
<!--
Set compilation debug="true" to insert debugging
symbols into the compiled page. Because this
affects performance, set this value to true only
during development.
-->
<compilation debug="true">
</compilation>
<!--
The <authentication> section enables configuration
of the security authentication mode used by
ASP.NET to identify an incoming user.
-->
<authentication mode="Windows"/>
<!--
The <customErrors> section enables configuration
of what to do if/when an unhandled error occurs
during the execution of a request. Specifically,
it enables developers to configure html error pages
to be displayed in place of a error stack trace.
<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
<error statusCode="403" redirect="NoAccess.htm" />
<error statusCode="404" redirect="FileNotFound.htm" />
</customErrors>
-->
</system.web>
</configuration>
step
How to install it?
Like other .net library, you just copy the dll files
(Spring.Services.dll, Spring.Aop.dll and Spring.Core, Common.Logging.dll and the counterpart xmls files to
to your project and do the configuration.
How to use it?
Take Spring Integration with WCF(Windows Communication Foundation) as an example,
Step 1: define the Services
namespace Spring.WcfQuickStart
{
[Serializable]
public class BinaryOperationArgs
{
private double x;
private double y;
public BinaryOperationArgs(double x, double y)
{
this.x = x;
this.y = y;
}
public double X
{
get { return x; }
}
public double Y
{
get { return y; }
}
}
[Serializable]
public class OperationResult
{
private double result;
public OperationResult(double result)
{
this.result = result;
}
public double Result
{
get { return result; }
}
}
[ServiceContract(Namespace = "http://Spring.WcfQuickStart")]
public interface ICalculator
{
[OperationContract]
double Add(double n1, double n2);
[OperationContract]
double Subtract(double n1, double n2);
[OperationContract]
double Multiply(double n1, double n2);
[OperationContract]
double Divide(double n1, double n2);
[OperationContract]
string GetName();
[OperationContract]
OperationResult Power(BinaryOperationArgs args);
}
}
Step 2: Implementation
namespace Spring.WcfQuickStart
{
public class CalculatorService : ICalculator
{
// the value will be injected in weaving time
private int sleepInSeconds;
public int SleepInSeconds
{
get { return sleepInSeconds; }
set { sleepInSeconds = value; }
}
public double Add(double n1, double n2)
{
Thread.Sleep(sleepInSeconds * 1000);
return n1 + n2;
}
public double Subtract(double n1, double n2)
{
Thread.Sleep(sleepInSeconds * 1000);
return n1 - n2;
}
public double Multiply(double n1, double n2)
{
Thread.Sleep(sleepInSeconds * 1000);
return n1 * n2;
}
public double Divide(double n1, double n2)
{
Thread.Sleep(sleepInSeconds * 1000);
return n1 / n2;
}
public OperationResult Power(BinaryOperationArgs args)
{
// do something
return new OperationResult(Math.Pow(args.X, args.Y));
}
public string GetName()
{
Thread.Sleep(SleepInSeconds * 1000);
return "WebApp Calculator";
}
}
}
Step 4: Define the IMethodInterceptor
public class SimplePerformanceInterceptor : IMethodInterceptor
{
private string prefix = "Invocation took";
public string Prefix
{
get { return prefix; }
set { prefix = value; }
}
#region IMethodInterceptor Members
// Summary:
// Implement this method to perform extra treatments before and after the call
// to the supplied invocation.
//
// Parameters:
// invocation:
// The method invocation that is being intercepted.
public object Invoke(IMethodInvocation invocation)
{
DateTime start = DateTime.Now;
try
{
return invocation.Proceed();
}
finally
{
DateTime stop = DateTime.Now;
TimeSpan time = stop - start;
Console.Out.WriteLine(Prefix + " " + time);
}
}
#endregion
}
Step 3: AOP codes
public class SimplePerformanceInterceptor : IMethodInterceptor
{
private string prefix = "Invocation took";
public string Prefix
{
get { return prefix; }
set { prefix = value; }
}
#region IMethodInterceptor Members
/// <summary>
/// IMethodInvocation
// Summary:
// Gets the method invocation that is to be invoked.
//
// Remarks:
// This property is a friendly implementation of the AopAlliance.Intercept.IJoinpoint.StaticPart
// property. It should be used in preference to the AopAlliance.Intercept.IJoinpoint.StaticPart
// property because it provides immediate access to the underlying method without
// the need to resort to a cast.
// MethodInfo Method { get; }
//
// Summary:
// Gets the proxy object for the invocation.
// object Proxy { get; }
//
// Summary:
// Gets the target object for the invocation.
// object Target { get; }
//
// Summary:
// Gets the type of the target object.
// Type TargetType { get; }
/// </summary>
/// <param name="invocation"></param>
/// <returns></returns>
public object Invoke(IMethodInvocation invocation)
{
DateTime start = DateTime.Now;
try
{ // deal with something about invocation
//...
return invocation.Proceed();
}
finally
{
DateTime stop = DateTime.Now;
TimeSpan time = stop - start;
Console.Out.WriteLine(Prefix + " " + time);
}
}
#endregion
}
Step 4: Configuration - web.config
<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 Configuration -->
<spring>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net"
xmlns:aop="http://www.springframework.net/aop">
<!-- Service definition -->
<object id="calculator" type="Spring.WcfQuickStart.CalculatorService, Spring.WcfQuickStart.ServerWeb"
singleton="false">
<!-- the value to be injected when weaved -->
<property name="SleepInSeconds" value="1"/>
</object>
<object id="serviceOperation" type="Spring.Aop.Support.SdkRegularExpressionMethodPointcut, Spring.Aop">
<property name="pattern" value="^Spring.WcfQuickStart.*"/>
</object>
<object id="perfAdvice" type="Spring.WcfQuickStart.SimplePerformanceInterceptor, Spring.WcfQuickStart.ServerWeb">
<!-- the value of Prefix will be injected in running time
<property name="Prefix" value="Service Layer Performance"/>
</object>
<!-- weave the advices to each crosscutting around the pointcuts,
<aop:config>
<aop:advisor pointcut-ref="serviceOperation" advice-ref="perfAdvice"/>
</aop:config>
</objects>
</spring>
<!-- WCF Service Configuration -->
<system.serviceModel>
<services>
<service name="calculator" behaviorConfiguration="DefaultBehavior">
<endpoint address="" binding="basicHttpBinding" contract="Spring.WcfQuickStart.ICalculator"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DefaultBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<appSettings/>
<connectionStrings/>
<system.web>
<!--
Set compilation debug="true" to insert debugging
symbols into the compiled page. Because this
affects performance, set this value to true only
during development.
-->
<compilation debug="true">
</compilation>
<!--
The <authentication> section enables configuration
of the security authentication mode used by
ASP.NET to identify an incoming user.
-->
<authentication mode="Windows"/>
<!--
The <customErrors> section enables configuration
of what to do if/when an unhandled error occurs
during the execution of a request. Specifically,
it enables developers to configure html error pages
to be displayed in place of a error stack trace.
<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
<error statusCode="403" redirect="NoAccess.htm" />
<error statusCode="404" redirect="FileNotFound.htm" />
</customErrors>
-->
</system.web>
</configuration>
step
Comments
Post a Comment