A target retrieved from a dynamic target source, is not entirely thread safe, e.g.ThreadLocalTargetSource [SPRNET-1289]
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -49,7 +49,7 @@ namespace Spring.Aop.Framework.DynamicProxy
|
||||
public override void PushTarget(ILGenerator il)
|
||||
{
|
||||
PushAdvisedProxy(il);
|
||||
il.Emit(OpCodes.Ldfld, References.TargetSourceWrapperField);
|
||||
il.Emit(OpCodes.Ldfld, References.TargetSourceField);
|
||||
il.EmitCall(OpCodes.Callvirt, References.GetTargetMethod, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
/*
|
||||
* Copyright <20> 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
@@ -60,9 +60,9 @@ namespace Spring.Aop.Framework.DynamicProxy
|
||||
public IAdvice[] m_introductions;
|
||||
|
||||
/// <summary>
|
||||
/// Target source wrapper
|
||||
/// Target source
|
||||
/// </summary>
|
||||
public ITargetSourceWrapper m_targetSourceWrapper;
|
||||
public ITargetSource m_targetSource;
|
||||
|
||||
/// <summary>
|
||||
/// Type of target object.
|
||||
@@ -127,7 +127,7 @@ namespace Spring.Aop.Framework.DynamicProxy
|
||||
{
|
||||
m_advised = (IAdvised)info.GetValue("advised", typeof(IAdvised));
|
||||
m_introductions = (IAdvice[])info.GetValue("introductions", typeof(IAdvice[]));
|
||||
m_targetSourceWrapper = (ITargetSourceWrapper)info.GetValue("tsWrapper", typeof(ITargetSourceWrapper));
|
||||
m_targetSource = (ITargetSource)info.GetValue("targetSource", typeof(ITargetSource));
|
||||
m_targetType = (Type)info.GetValue("targetType", typeof(Type));
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ namespace Spring.Aop.Framework.DynamicProxy
|
||||
{
|
||||
info.AddValue("advised", m_advised);
|
||||
info.AddValue("introductions", m_introductions);
|
||||
info.AddValue("tsWrapper", m_targetSourceWrapper);
|
||||
info.AddValue("targetSource", m_targetSource);
|
||||
info.AddValue("targetType", m_targetType);
|
||||
}
|
||||
|
||||
@@ -159,18 +159,9 @@ namespace Spring.Aop.Framework.DynamicProxy
|
||||
protected void Initialize(IAdvised advised, IAopProxy proxy)
|
||||
{
|
||||
this.m_advised = advised;
|
||||
this.m_targetSource = advised.TargetSource;
|
||||
this.m_targetType = advised.TargetSource.TargetType;
|
||||
|
||||
// initialize target
|
||||
if (advised.TargetSource.IsStatic)
|
||||
{
|
||||
this.m_targetSourceWrapper = new StaticTargetSourceWrapper(advised.TargetSource);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_targetSourceWrapper = new DynamicTargetSourceWrapper(advised.TargetSource);
|
||||
}
|
||||
|
||||
// initialize introduction advice
|
||||
this.m_introductions = new IAdvice[advised.Introductions.Length];
|
||||
for (int i = 0; i < advised.Introductions.Length; i++)
|
||||
|
||||
@@ -1,88 +1,88 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security.Permissions;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Aop.Framework.DynamicProxy
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class that each dynamic composition proxy has to extend.
|
||||
/// </summary>
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
/// <author>Bruno Baia</author>
|
||||
[Serializable]
|
||||
public abstract class BaseCompositionAopProxy : AdvisedProxy, IAopProxy, ISerializable
|
||||
{
|
||||
#region Constructor (s) / Destructor
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public BaseCompositionAopProxy()
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the
|
||||
/// <see cref="Spring.Aop.Framework.DynamicProxy.BaseCompositionAopProxy"/> class.
|
||||
/// </summary>
|
||||
/// <param name="advised">The proxy configuration.</param>
|
||||
public BaseCompositionAopProxy(IAdvised advised) : base(advised)
|
||||
{
|
||||
base.Initialize(advised, this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserialization constructor.
|
||||
/// </summary>
|
||||
/// <param name="info">Serialization data.</param>
|
||||
/// <param name="context">Serialization context.</param>
|
||||
protected BaseCompositionAopProxy(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{}
|
||||
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security.Permissions;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Aop.Framework.DynamicProxy
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class that each dynamic composition proxy has to extend.
|
||||
/// </summary>
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
/// <author>Bruno Baia</author>
|
||||
[Serializable]
|
||||
public abstract class BaseCompositionAopProxy : AdvisedProxy, IAopProxy, ISerializable
|
||||
{
|
||||
#region Constructor (s) / Destructor
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public BaseCompositionAopProxy()
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the
|
||||
/// <see cref="Spring.Aop.Framework.DynamicProxy.BaseCompositionAopProxy"/> class.
|
||||
/// </summary>
|
||||
/// <param name="advised">The proxy configuration.</param>
|
||||
public BaseCompositionAopProxy(IAdvised advised) : base(advised)
|
||||
{
|
||||
base.Initialize(advised, this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserialization constructor.
|
||||
/// </summary>
|
||||
/// <param name="info">Serialization data.</param>
|
||||
/// <param name="context">Serialization context.</param>
|
||||
protected BaseCompositionAopProxy(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{}
|
||||
|
||||
///<summary>
|
||||
///Populates a <see cref="T:System.Runtime.Serialization.SerializationInfo"></see> with the data needed to serialize the target object.
|
||||
///</summary>
|
||||
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
base.GetObjectData(info, context);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IAopProxy Members
|
||||
|
||||
/// <summary>
|
||||
/// Returns this proxy instance
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
object IAopProxy.GetProxy()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IAopProxy Members
|
||||
|
||||
/// <summary>
|
||||
/// Returns this proxy instance
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
object IAopProxy.GetProxy()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Equal, HashCode and ToString overrides
|
||||
@@ -94,31 +94,36 @@ namespace Spring.Aop.Framework.DynamicProxy
|
||||
/// <returns>true if the specified Object is equal to the current target object; otherwise, false</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
bool equals = false;
|
||||
object target = m_targetSource.GetTarget();
|
||||
AdvisedProxy otherProxy = obj as AdvisedProxy;
|
||||
object otherTarget = null;
|
||||
if (otherProxy != null)
|
||||
{
|
||||
using (m_targetSourceWrapper)
|
||||
using (otherProxy.m_targetSourceWrapper)
|
||||
{
|
||||
object target = m_targetSourceWrapper.GetTarget();
|
||||
object otherTarget = otherProxy.m_targetSourceWrapper.GetTarget();
|
||||
if (target == null)
|
||||
{
|
||||
return (otherTarget == null);
|
||||
}
|
||||
return target.Equals(otherTarget);
|
||||
}
|
||||
}
|
||||
|
||||
using (m_targetSourceWrapper)
|
||||
{
|
||||
object target = m_targetSourceWrapper.GetTarget();
|
||||
otherTarget = otherProxy.m_targetSource.GetTarget();
|
||||
if (target == null)
|
||||
{
|
||||
return (obj == null);
|
||||
equals = (otherTarget == null);
|
||||
}
|
||||
else
|
||||
{
|
||||
equals = target.Equals(otherTarget);
|
||||
}
|
||||
return target.Equals(obj);
|
||||
}
|
||||
else if (target == null)
|
||||
{
|
||||
equals = (obj == null);
|
||||
}
|
||||
else
|
||||
{
|
||||
equals = target.Equals(obj);
|
||||
}
|
||||
m_targetSource.ReleaseTarget(target);
|
||||
if (otherProxy != null)
|
||||
{
|
||||
otherProxy.m_targetSource.ReleaseTarget(otherTarget);
|
||||
}
|
||||
return equals;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -127,15 +132,14 @@ namespace Spring.Aop.Framework.DynamicProxy
|
||||
/// <returns>A hash code for the target object.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
using (m_targetSourceWrapper)
|
||||
int hashCode = 0;
|
||||
object target = m_targetSource.GetTarget();
|
||||
if (target != null)
|
||||
{
|
||||
object target = m_targetSourceWrapper.GetTarget();
|
||||
if (target != null)
|
||||
{
|
||||
return target.GetHashCode();
|
||||
}
|
||||
return 0;
|
||||
hashCode = target.GetHashCode();
|
||||
}
|
||||
m_targetSource.ReleaseTarget(target);
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -144,17 +148,20 @@ namespace Spring.Aop.Framework.DynamicProxy
|
||||
/// <returns>A String that represents the target object</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
using (m_targetSourceWrapper)
|
||||
string str;
|
||||
object target = m_targetSource.GetTarget();
|
||||
if (target != null)
|
||||
{
|
||||
object target = m_targetSourceWrapper.GetTarget();
|
||||
if (target != null)
|
||||
{
|
||||
return target.ToString();
|
||||
}
|
||||
return base.ToString();
|
||||
str = target.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
str = base.ToString();
|
||||
}
|
||||
m_targetSource.ReleaseTarget(target);
|
||||
return str;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -42,10 +42,9 @@ namespace Spring.Aop.Framework.DynamicProxy
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// The local variable to store
|
||||
/// the <see cref="Spring.Aop.Framework.ITargetSourceWrapper"/> instance.
|
||||
/// The local variable to store the target instance.
|
||||
/// </summary>
|
||||
protected LocalBuilder targetSource;
|
||||
protected LocalBuilder target;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -84,11 +83,21 @@ namespace Spring.Aop.Framework.DynamicProxy
|
||||
protected override void DeclareLocals(ILGenerator il, MethodInfo method)
|
||||
{
|
||||
base.DeclareLocals(il, method);
|
||||
targetSource = il.DeclareLocal(typeof(ITargetSourceWrapper));
|
||||
target = il.DeclareLocal(typeof(object));
|
||||
|
||||
#if DEBUG
|
||||
targetSource.SetLocalSymInfo("targetSource");
|
||||
target.SetLocalSymInfo("target");
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates the IL instructions that pushes
|
||||
/// the target instance on which calls should be delegated to.
|
||||
/// </summary>
|
||||
/// <param name="il">The IL generator to use.</param>
|
||||
protected override void PushTarget(ILGenerator il)
|
||||
{
|
||||
il.Emit(OpCodes.Ldloc, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -101,32 +110,18 @@ namespace Spring.Aop.Framework.DynamicProxy
|
||||
/// </param>
|
||||
protected override void GenerateMethodLogic(
|
||||
ILGenerator il, MethodInfo method, MethodInfo interfaceMethod)
|
||||
{
|
||||
Label jmpEndFinally = il.DefineLabel();
|
||||
{
|
||||
PushAdvisedProxy(il);
|
||||
il.Emit(OpCodes.Ldfld, References.TargetSourceField);
|
||||
il.EmitCall(OpCodes.Callvirt, References.GetTargetMethod, null);
|
||||
il.Emit(OpCodes.Stloc, target);
|
||||
|
||||
// save target source so we can call Dispose later
|
||||
PushAdvisedProxy(il);
|
||||
il.Emit(OpCodes.Ldfld, References.TargetSourceWrapperField);
|
||||
il.Emit(OpCodes.Stloc, targetSource);
|
||||
|
||||
// open try/finally block
|
||||
il.BeginExceptionBlock();
|
||||
|
||||
base.GenerateMethodLogic(il, method, interfaceMethod);
|
||||
|
||||
// open finally block
|
||||
il.BeginFinallyBlock();
|
||||
|
||||
// call Dispose on target source
|
||||
il.Emit(OpCodes.Ldloc, targetSource);
|
||||
il.Emit(OpCodes.Brfalse, jmpEndFinally);
|
||||
il.Emit(OpCodes.Ldloc, targetSource);
|
||||
il.EmitCall(OpCodes.Callvirt, References.DisposeMethod, null);
|
||||
|
||||
il.MarkLabel(jmpEndFinally);
|
||||
|
||||
// close try/finally block
|
||||
il.EndExceptionBlock();
|
||||
base.GenerateMethodLogic(il, method, interfaceMethod);
|
||||
|
||||
PushAdvisedProxy(il);
|
||||
il.Emit(OpCodes.Ldfld, References.TargetSourceField);
|
||||
PushTarget(il);
|
||||
il.EmitCall(OpCodes.Callvirt, References.GetReleaseTargetMethod, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using Spring.Util;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Aop.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// Decorates a target source with the <see cref="System.IDisposable"/>
|
||||
/// interface.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// This implementation will release the target object when said object
|
||||
/// is disposed.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
[Serializable]
|
||||
public sealed class DynamicTargetSourceWrapper : ITargetSourceWrapper
|
||||
{
|
||||
private ITargetSource targetSource;
|
||||
private object target;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the
|
||||
/// <see cref="Spring.Aop.Framework.DynamicTargetSourceWrapper"/>
|
||||
/// class.
|
||||
/// </summary>
|
||||
/// <param name="targetSource">
|
||||
/// The target object that proxy methods will be delegated to.
|
||||
/// </param>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// If the supplied <paramref name="targetSource"/> is
|
||||
/// <see langword="null"/>.
|
||||
/// </exception>
|
||||
internal DynamicTargetSourceWrapper(ITargetSource targetSource)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(targetSource, "targetSource");
|
||||
this.targetSource = targetSource;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the target object that proxy methods will be delegated to.
|
||||
/// </summary>
|
||||
/// <returns>The target object.</returns>
|
||||
public object GetTarget()
|
||||
{
|
||||
if (this.target == null)
|
||||
{
|
||||
this.target = targetSource.GetTarget();
|
||||
}
|
||||
|
||||
return this.target;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases the dynamic target when this object is disposed.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && this.target != null)
|
||||
{
|
||||
this.targetSource.ReleaseTarget(this.target);
|
||||
this.target = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace Spring.Aop.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// Decorates a target source with the <see cref="System.IDisposable"/>
|
||||
/// interface.
|
||||
/// </summary>
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
public interface ITargetSourceWrapper : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the target object that proxy methods will be delegated to.
|
||||
/// </summary>
|
||||
/// <returns>The target object.</returns>
|
||||
object GetTarget();
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using Spring.Util;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Aop.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// Decorates a target source with the <see cref="System.IDisposable"/>
|
||||
/// interface.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Because the target source is static, the target object can be cached
|
||||
/// and simply returned as is.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
[Serializable]
|
||||
public sealed class StaticTargetSourceWrapper : ITargetSourceWrapper
|
||||
{
|
||||
private object target;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the
|
||||
/// <see cref="Spring.Aop.Framework.StaticTargetSourceWrapper"/>
|
||||
/// class.
|
||||
/// </summary>
|
||||
/// <param name="targetSource">
|
||||
/// The target object that proxy methods will be delegated to.
|
||||
/// </param>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// If the supplied <paramref name="targetSource"/> is
|
||||
/// <see langword="null"/>.
|
||||
/// </exception>
|
||||
internal StaticTargetSourceWrapper(ITargetSource targetSource)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(targetSource, "targetSource");
|
||||
this.target = targetSource.GetTarget();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the target object that proxy methods will be delegated to.
|
||||
/// </summary>
|
||||
/// <returns>The target object.</returns>
|
||||
public object GetTarget()
|
||||
{
|
||||
return this.target;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing,
|
||||
/// releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <note type="implementnotes">
|
||||
/// This is a no-op operation in this implementation.
|
||||
/// </note>
|
||||
/// </remarks>
|
||||
public void Dispose()
|
||||
{
|
||||
// do nothing, this is static target source wrapper...
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -239,11 +239,6 @@
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Aop\Framework\DynamicTargetSourceWrapper.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Aop\Framework\HashtableCachingAdvisorChainFactory.cs"
|
||||
SubType = "Code"
|
||||
@@ -284,11 +279,6 @@
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Aop\Framework\ITargetSourceWrapper.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Aop\Framework\ProxyConfig.cs"
|
||||
SubType = "Code"
|
||||
@@ -309,11 +299,6 @@
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Aop\Framework\StaticTargetSourceWrapper.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Aop\Framework\Adapter\AdvisorAdapterRegistrationManager.cs"
|
||||
SubType = "Code"
|
||||
|
||||
@@ -241,11 +241,6 @@
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Aop\Framework\DynamicTargetSourceWrapper.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Aop\Framework\HashtableCachingAdvisorChainFactory.cs"
|
||||
SubType = "Code"
|
||||
@@ -286,11 +281,6 @@
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Aop\Framework\ITargetSourceWrapper.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Aop\Framework\ProxyConfig.cs"
|
||||
SubType = "Code"
|
||||
@@ -311,11 +301,6 @@
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Aop\Framework\StaticTargetSourceWrapper.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "Aop\Framework\Adapter\AdvisorAdapterRegistrationManager.cs"
|
||||
SubType = "Code"
|
||||
|
||||
@@ -205,9 +205,6 @@
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Aop\Framework\DynamicProxy\TargetAopProxyMethodBuilder.cs" />
|
||||
<Compile Include="Aop\Framework\DynamicTargetSourceWrapper.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Aop\Framework\HashtableCachingAdvisorChainFactory.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
@@ -232,7 +229,6 @@
|
||||
<Compile Include="Aop\Framework\ITargetAware.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Aop\Framework\ITargetSourceWrapper.cs" />
|
||||
<Compile Include="Aop\Framework\ProxyConfig.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
@@ -245,9 +241,6 @@
|
||||
<Compile Include="Aop\Framework\ReflectiveMethodInvocation.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Aop\Framework\StaticTargetSourceWrapper.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Aop\IAdvisor.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
||||
@@ -216,9 +216,6 @@
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Aop\Framework\DynamicProxy\TargetAopProxyMethodBuilder.cs" />
|
||||
<Compile Include="Aop\Framework\DynamicTargetSourceWrapper.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Aop\Framework\HashtableCachingAdvisorChainFactory.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
@@ -243,7 +240,6 @@
|
||||
<Compile Include="Aop\Framework\ITargetAware.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Aop\Framework\ITargetSourceWrapper.cs" />
|
||||
<Compile Include="Aop\Framework\ProxyConfig.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
@@ -256,9 +252,6 @@
|
||||
<Compile Include="Aop\Framework\ReflectiveMethodInvocation.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Aop\Framework\StaticTargetSourceWrapper.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Aop\IAdvisor.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
||||
@@ -270,17 +270,13 @@ namespace Spring.Proxy
|
||||
protected virtual void CallDirectTargetMethod(
|
||||
ILGenerator il, MethodInfo targetMethod)
|
||||
{
|
||||
// setup target object for call
|
||||
PushTarget(il);
|
||||
|
||||
// TODO (EE): check for null and interface type and throw NotSupportedException
|
||||
LocalBuilder targetRef = il.DeclareLocal(typeof(object));
|
||||
il.Emit(OpCodes.Stloc, targetRef);
|
||||
|
||||
CallAssertUnderstands(il, targetMethod, targetRef, "target");
|
||||
// setup target instance for CallAssertUnderstands
|
||||
PushTarget(il);
|
||||
CallAssertUnderstands(il, targetMethod, "target");
|
||||
|
||||
// setup target and cast to type method is on
|
||||
il.Emit(OpCodes.Ldloc, targetRef);
|
||||
PushTarget(il);
|
||||
il.Emit(OpCodes.Castclass, targetMethod.DeclaringType);
|
||||
|
||||
// setup parameters for call
|
||||
@@ -295,17 +291,18 @@ namespace Spring.Proxy
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Emits code to ensure that target understands the method and throw a sensible exception otherwise.
|
||||
/// Emits code to ensure that target on stack understands the method and throw a sensible exception otherwise.
|
||||
/// </summary>
|
||||
protected virtual void CallAssertUnderstands(ILGenerator il, MethodInfo method, LocalBuilder targetRef, string targetName)
|
||||
/// <param name="il">The IL generator to use.</param>
|
||||
/// <param name="method">The method to test for</param>
|
||||
/// <param name="targetName">the name of the target to be used in error messages</param>
|
||||
protected virtual void CallAssertUnderstands(ILGenerator il, MethodInfo method, string targetName)
|
||||
{
|
||||
// AssertArgumentType
|
||||
il.Emit(OpCodes.Ldloc, targetRef);
|
||||
il.Emit(OpCodes.Ldstr, targetName);
|
||||
il.Emit(OpCodes.Ldtoken, method.DeclaringType);
|
||||
il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(RuntimeTypeHandle) }));
|
||||
// il.Emit(OpCodes.Ldstr, string.Format("Interface method '{0}.{1}()' was not handled by any interceptor and the target does not implement this method.", method.DeclaringType.FullName, method.Name));
|
||||
il.Emit(OpCodes.Call, typeof(AssertUtils).GetMethod("Understands", new Type[] { typeof(object), typeof(string), typeof(Type) }));
|
||||
il.Emit(OpCodes.Call, References.GetTypeFromHandleMethod);
|
||||
//il.Emit(OpCodes.Ldstr, string.Format("Interface method '{0}.{1}()' was not handled by any interceptor and the target does not implement this method.", method.DeclaringType.FullName, method.Name));
|
||||
il.Emit(OpCodes.Call, References.UnderstandsMethod);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -315,17 +312,13 @@ namespace Spring.Proxy
|
||||
/// <param name="method">The method to proxy.</param>
|
||||
protected virtual void CallDirectBaseMethod(ILGenerator il, MethodInfo method)
|
||||
{
|
||||
// setup proxy instance for call
|
||||
PushProxy(il);
|
||||
|
||||
// TODO (EE): check for null and interface type and throw NotSupportedException
|
||||
LocalBuilder targetRef = il.DeclareLocal(typeof(object));
|
||||
il.Emit(OpCodes.Stloc, targetRef);
|
||||
// setup proxy instance for CallAssertUnderstands
|
||||
PushProxy(il);
|
||||
CallAssertUnderstands(il, method, "base");
|
||||
|
||||
CallAssertUnderstands(il, method, targetRef, "base");
|
||||
|
||||
// setup target and cast to type method is on
|
||||
il.Emit(OpCodes.Ldloc, targetRef);
|
||||
// setup proxy and cast to type method is on
|
||||
PushProxy(il);
|
||||
il.Emit(OpCodes.Castclass, method.DeclaringType);
|
||||
|
||||
// setup parameters for call
|
||||
@@ -389,4 +382,18 @@ namespace Spring.Proxy
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region References helper class definition
|
||||
|
||||
internal struct References
|
||||
{
|
||||
// methods
|
||||
public static readonly MethodInfo GetTypeFromHandleMethod =
|
||||
typeof(Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(RuntimeTypeHandle) });
|
||||
|
||||
public static readonly MethodInfo UnderstandsMethod =
|
||||
typeof(AssertUtils).GetMethod("Understands", new Type[] { typeof(object), typeof(string), typeof(Type) });
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -233,7 +233,7 @@ namespace Spring.EnterpriseServices
|
||||
/// <summary>
|
||||
/// Suppress output to avoid Spring.Core dependency
|
||||
/// </summary>
|
||||
protected override void CallAssertUnderstands(ILGenerator il, MethodInfo method, LocalBuilder targetRef, string targetName)
|
||||
protected override void CallAssertUnderstands(ILGenerator il, MethodInfo method, string targetName)
|
||||
{
|
||||
// base.CallAssertUnderstands(il, method, targetRef, targetName);
|
||||
}
|
||||
|
||||
@@ -847,8 +847,6 @@ namespace Spring.Aop.Framework.DynamicProxy
|
||||
CreateProxy(advised) as AbstractProxyTypeBuilderTests.InterfaceWithGenericMethod;
|
||||
Assert.IsNotNull(proxy);
|
||||
|
||||
DynamicProxyManager.SaveAssembly();
|
||||
|
||||
proxy.PolymorphicMethod<int>();
|
||||
proxy.PolymorphicMethod<string>();
|
||||
|
||||
@@ -870,6 +868,11 @@ namespace Spring.Aop.Framework.DynamicProxy
|
||||
|
||||
proxy.WithMixedConstraint<bool, DerivedTestObject>();
|
||||
Assert.AreEqual(10, ni.Count);
|
||||
|
||||
//if (this is DecoratorAopProxyTests)
|
||||
//{
|
||||
// DynamicProxyManager.SaveAssembly();
|
||||
//}
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -17,6 +17,7 @@ using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Collections;
|
||||
using Common.Logging;
|
||||
using NUnit.Framework;
|
||||
using Spring.Objects;
|
||||
@@ -42,7 +43,6 @@ namespace Spring.Aop.Target
|
||||
{
|
||||
this.ObjectFactory = new XmlObjectFactory (
|
||||
new ReadOnlyXmlTestResource ("threadLocalTests.xml", GetType ()));
|
||||
//TODO-LOGGING XmlConfigurator.Configure (new FileInfo ("Spring.Aop.Tests.dll.config"));
|
||||
log = LogManager.GetLogger (MethodBase.GetCurrentMethod ().DeclaringType);
|
||||
}
|
||||
|
||||
@@ -152,5 +152,79 @@ namespace Spring.Aop.Target
|
||||
// Bound to two threads
|
||||
Assert.AreEqual (2, ((IThreadLocalTargetSourceStats) apartment).Objects);
|
||||
}
|
||||
|
||||
private static bool multiThreadedTestFailed = false;
|
||||
|
||||
[Test]
|
||||
public virtual void MultiThreadedTest()
|
||||
{
|
||||
multiThreadedTestFailed = false;
|
||||
|
||||
this.ObjectFactory = new XmlObjectFactory(
|
||||
new ReadOnlyXmlTestResource("threadLocalTests.xml", GetType()));
|
||||
log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
// Initialize property.
|
||||
IMultiThreadInterface mtObject = (IMultiThreadInterface)ObjectFactory.GetObject("mtTest");
|
||||
|
||||
// Start threads.
|
||||
ArrayList threads = new ArrayList();
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
Thread thread = new Thread(new ParameterizedThreadStart(CheckName));
|
||||
threads.Add(thread);
|
||||
thread.Start(mtObject);
|
||||
}
|
||||
|
||||
// Wait for threads to end.
|
||||
foreach (Thread thread in threads)
|
||||
{
|
||||
thread.Join();
|
||||
}
|
||||
|
||||
Assert.IsFalse(multiThreadedTestFailed);
|
||||
}
|
||||
|
||||
private void CheckName(object mtObject)
|
||||
{
|
||||
string name = ((IMultiThreadInterface)mtObject).GenerateAndSetName(100);
|
||||
|
||||
// Returned name should be equal to property.
|
||||
if (!name.Equals(((IMultiThreadInterface)mtObject).Name))
|
||||
{
|
||||
multiThreadedTestFailed = true;
|
||||
}
|
||||
//Console.WriteLine(String.Format("Expected: {0}; Actual: {1}",
|
||||
// name, ((IMultiThreadInterface)mtObject).Name));
|
||||
}
|
||||
|
||||
#region Helper classes
|
||||
|
||||
public interface IMultiThreadInterface
|
||||
{
|
||||
string Name { get; }
|
||||
string GenerateAndSetName(int sleep);
|
||||
}
|
||||
|
||||
public class MultiThreadClass : IMultiThreadInterface
|
||||
{
|
||||
private string _name;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return _name; }
|
||||
}
|
||||
|
||||
public string GenerateAndSetName(int sleep)
|
||||
{
|
||||
string generated = "Thread_" + Thread.CurrentThread.ManagedThreadId;
|
||||
_name = generated;
|
||||
|
||||
Thread.Sleep(sleep);
|
||||
return generated;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -69,4 +69,13 @@
|
||||
<ref local="threadLocalTs2" />
|
||||
</property>
|
||||
</object>
|
||||
|
||||
<object id="mtPrototype" type="Spring.Aop.Target.ThreadLocalTargetSourceTests+MultiThreadClass" singleton="false" />
|
||||
<object id="mtTest" type="Spring.Aop.Framework.ProxyFactoryObject">
|
||||
<property name="targetSource">
|
||||
<object type="Spring.Aop.Target.ThreadLocalTargetSource">
|
||||
<property name="targetObjectName" value="mtPrototype" />
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</objects>
|
||||
|
||||
Reference in New Issue
Block a user