fixed SPRNET-1169

This commit is contained in:
eeichinger
2009-02-23 18:02:29 +00:00
parent 166f0bb677
commit 67b6f8f214
5 changed files with 390 additions and 343 deletions

View File

@@ -1,5 +1,5 @@
#region License
#region License
/*
* Copyright <20> 2002-2005 the original author or authors.
*
@@ -14,258 +14,279 @@
* 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.Reflection;
using Spring.Collections;
using Spring.Util;
#endregion
namespace Spring.Aop.Framework
{
/// <summary>
/// Utility methods used by the AOP framework.
/// </summary>
/// <remarks>
/// <p>
/// Not intended to be used directly by applications.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Juergen Hoeller</author>
/// <author>Aleksandar Seovic (.NET)</author>
public sealed class AopUtils
{
// This is a leaky abstraction as we have hardcoded known IAopProxyFactory implementations.
private const string COMPOSITION_PROXY_TYPE_NAME = "CompositionAopProxy";
private const string DECORATOR_PROXY_TYPE_NAME = "DecoratorAopProxy";
/// <summary>
/// Is the supplied <paramref name="instance"/> an AOP proxy?
/// </summary>
/// <remarks>
/// Return whether the given object is either
/// a composition-based proxy or a decorator-based proxy.
/// </remarks>
/// <param name="instance">The instance to be checked.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="instance"/> is
/// an AOP proxy.
/// </returns>
public static bool IsAopProxy(object instance)
{
return IsCompositionAopProxy(instance) || IsDecoratorAopProxy(instance);
}
/// <summary>
/// Is the supplied <paramref name="instance"/> a composition-based AOP proxy?
/// </summary>
/// <param name="instance">The instance to be checked.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="instance"/> is
/// an composition-based AOP proxy.
/// </returns>
public static bool IsCompositionAopProxy(Object instance)
{
return ((instance != null) && instance.GetType().FullName.StartsWith(COMPOSITION_PROXY_TYPE_NAME));
}
/// <summary>
/// Is the supplied <paramref name="instance"/> a decorator-based AOP proxy?
/// </summary>
/// <param name="instance">The instance to be checked.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="instance"/> is
/// an decorator-based AOP proxy.
/// </returns>
public static bool IsDecoratorAopProxy(Object instance)
{
return ((instance != null) && instance.GetType().FullName.StartsWith(DECORATOR_PROXY_TYPE_NAME));
}
/// <summary>
/// Gets all of the interfaces that the <see cref="System.Type"/> of the
/// supplied <paramref name="instance"/> implements.
/// </summary>
/// <remarks>
/// <p>
/// This includes interfaces implemented by any superclasses.
/// </p>
/// </remarks>
/// <param name="instance">
/// The object to analyse for interfaces.
/// </param>
/// <returns>
/// All of the interfaces that the <see cref="System.Type"/> of the
/// supplied <paramref name="instance"/> implements; or an empty
/// array if the supplied <paramref name="instance"/> is
/// <see langword="null"/>.
/// </returns>
public static Type[] GetAllInterfaces(object instance)
{
if (instance != null)
{
ISet interfaces = new HybridSet();
Type type = instance.GetType();
do
{
Type[] ifcs = type.GetInterfaces();
foreach (Type ifc in ifcs)
{
interfaces.Add(ifc);
}
type = type.BaseType;
} while (type != null);
if (interfaces.Count > 0)
{
Type[] types = new Type[interfaces.Count];
interfaces.CopyTo(types, 0);
return types;
}
}
return Type.EmptyTypes;
}
/// <summary>
/// Can the supplied <paramref name="pointcut"/> apply at all on the
/// supplied <paramref name="targetType"/>?
/// </summary>
/// <remarks>
/// <p>
/// This is an important test as it can be used to optimize out a
/// pointcut for a class.
/// </p>
/// <p>
/// Invoking this method with a <paramref name="targetType"/> that is
/// an interface type will always yield a <see langword="false"/>
/// return value.
/// </p>
/// </remarks>
/// <param name="pointcut">The pointcut being tested.</param>
/// <param name="targetType">The class being tested.</param>
/// <param name="proxyInterfaces">
/// The interfaces being proxied. If <see langword="null"/>, all
/// methods on a class may be proxied.
/// </param>
/// <returns>
/// <see langword="true"/> if the pointcut can apply on any method.
/// </returns>
public static bool CanApply(
IPointcut pointcut, Type targetType, Type[] proxyInterfaces)
{
if (!pointcut.TypeFilter.Matches(targetType))
{
return false;
}
// It may apply to the class
// Check whether it can apply on any method
// Checks public methods, including inherited methods
MethodInfo[] methods = targetType.GetMethods();
for (int i = 0; i < methods.Length; ++i)
{
MethodInfo m = methods[i];
// If we're looking only at interfaces and this method
// isn't on any of them, skip it
if (proxyInterfaces != null
&& !ReflectionUtils.MethodIsOnOneOfTheseInterfaces(m, proxyInterfaces))
{
continue;
}
if (pointcut.MethodMatcher.Matches(m, targetType))
{
return true;
}
}
return false;
}
/// <summary>
/// Can the supplied <paramref name="advisor"/> apply at all on the
/// supplied <paramref name="targetType"/>?
/// </summary>
/// <remarks>
/// <p>
/// This is an important test as it can be used to optimize out an
/// advisor for a class.
/// </p>
/// </remarks>
/// <param name="advisor">The advisor to check.</param>
/// <param name="targetType">The class being tested.</param>
/// <param name="proxyInterfaces">
/// The interfaces being proxied. If <see langword="null"/>, all
/// methods on a class may be proxied.
/// </param>
/// <returns>
/// <see langword="true"/> if the advisor can apply on any method.
/// </returns>
public static bool CanApply(
IAdvisor advisor, Type targetType, Type[] proxyInterfaces)
{
if (advisor is IIntroductionAdvisor)
{
return ((IIntroductionAdvisor) advisor).TypeFilter.Matches(targetType);
}
else if (advisor is IPointcutAdvisor)
{
IPointcutAdvisor pca = (IPointcutAdvisor) advisor;
return CanApply(pca.Pointcut, targetType, proxyInterfaces);
}
// no pointcut specified so assume it applies...
return true;
}
#region Constructor (s) / Destructor
// CLOVER:OFF
/// <summary>
/// Creates a new instance of the
/// <see cref="AopUtils"/> class.
/// </summary>
/// <remarks>
/// <p>
/// This is a utility class, and as such has no publicly
/// visible constructors.
/// </p>
/// </remarks>
private AopUtils()
{
}
// CLOVER:ON
#endregion
/// <summary>
/// Gets the type of the target.
/// </summary>
/// <param name="candidate">The candidate.</param>
/// <returns></returns>
public static Type GetTargetType(object candidate)
{
AssertUtils.ArgumentNotNull(candidate,"candidate", "Candidate object must not be null");
if (candidate is ITargetSource)
{
return ((ITargetSource) candidate).TargetType;
}
if (candidate is IAdvised)
{
return ((IAdvised) candidate).TargetSource.TargetType;
}
if (IsDecoratorAopProxy(candidate))
{
return candidate.GetType().BaseType;
}
return candidate.GetType();
}
}
*/
#endregion
#region Imports
using System;
using System.Reflection;
using Spring.Collections;
using Spring.Util;
#endregion
namespace Spring.Aop.Framework
{
/// <summary>
/// Utility methods used by the AOP framework.
/// </summary>
/// <remarks>
/// <p>
/// Not intended to be used directly by applications.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Juergen Hoeller</author>
/// <author>Aleksandar Seovic (.NET)</author>
public sealed class AopUtils
{
// This is a leaky abstraction as we have hardcoded known IAopProxyFactory implementations.
private const string COMPOSITION_PROXY_TYPE_NAME = "CompositionAopProxy";
private const string DECORATOR_PROXY_TYPE_NAME = "DecoratorAopProxy";
/// <summary>
/// Is the supplied <paramref name="instance"/> an AOP proxy?
/// </summary>
/// <remarks>
/// Return whether the given object is either
/// a composition-based proxy or a decorator-based proxy.
/// </remarks>
/// <param name="instance">The instance to be checked.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="instance"/> is
/// an AOP proxy.
/// </returns>
public static bool IsAopProxy(object instance)
{
return IsCompositionAopProxy(instance) || IsDecoratorAopProxy(instance);
}
/// <summary>
/// Is the supplied <paramref name="instance"/> a composition-based AOP proxy?
/// </summary>
/// <param name="instance">The instance to be checked.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="instance"/> is
/// an composition-based AOP proxy.
/// </returns>
public static bool IsCompositionAopProxy(Object instance)
{
return ((instance != null) && instance.GetType().FullName.StartsWith(COMPOSITION_PROXY_TYPE_NAME));
}
/// <summary>
/// Is the supplied <paramref name="instance"/> a decorator-based AOP proxy?
/// </summary>
/// <param name="instance">The instance to be checked.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="instance"/> is
/// an decorator-based AOP proxy.
/// </returns>
public static bool IsDecoratorAopProxy(Object instance)
{
return ((instance != null) && instance.GetType().FullName.StartsWith(DECORATOR_PROXY_TYPE_NAME));
}
/// <summary>
/// Gets all of the interfaces that the <see cref="System.Type"/> of the
/// supplied <paramref name="instance"/> implements.
/// </summary>
/// <remarks>
/// <p>
/// This includes interfaces implemented by any superclasses.
/// </p>
/// </remarks>
/// <param name="instance">
/// The object to analyse for interfaces.
/// </param>
/// <returns>
/// All of the interfaces that the <see cref="System.Type"/> of the
/// supplied <paramref name="instance"/> implements; or an empty
/// array if the supplied <paramref name="instance"/> is
/// <see langword="null"/>.
/// </returns>
public static Type[] GetAllInterfaces(object instance)
{
if (instance != null)
{
Type type = instance.GetType();
return GetAllInterfacesFromType(type);
}
return Type.EmptyTypes;
}
/// <summary>
/// Gets all of the interfaces that the
/// supplied <see cref="System.Type"/> implements.
/// </summary>
/// <remarks>
/// This includes interfaces implemented by any superclasses.
/// </remarks>
/// <param name="type">
/// The type to analyse for interfaces.
/// </param>
/// <returns>
/// All of the interfaces that the supplied <see cref="System.Type"/> implements.
/// </returns>
public static Type[] GetAllInterfacesFromType(Type type)
{
AssertUtils.ArgumentNotNull(type, "type");
ISet interfaces = new HybridSet();
do
{
Type[] ifcs = type.GetInterfaces();
foreach (Type ifc in ifcs)
{
interfaces.Add(ifc);
}
type = type.BaseType;
} while (type != null);
if (interfaces.Count > 0)
{
Type[] types = new Type[interfaces.Count];
interfaces.CopyTo(types, 0);
return types;
}
return Type.EmptyTypes;
}
/// <summary>
/// Can the supplied <paramref name="pointcut"/> apply at all on the
/// supplied <paramref name="targetType"/>?
/// </summary>
/// <remarks>
/// <p>
/// This is an important test as it can be used to optimize out a
/// pointcut for a class.
/// </p>
/// <p>
/// Invoking this method with a <paramref name="targetType"/> that is
/// an interface type will always yield a <see langword="false"/>
/// return value.
/// </p>
/// </remarks>
/// <param name="pointcut">The pointcut being tested.</param>
/// <param name="targetType">The class being tested.</param>
/// <param name="proxyInterfaces">
/// The interfaces being proxied. If <see langword="null"/>, all
/// methods on a class may be proxied.
/// </param>
/// <returns>
/// <see langword="true"/> if the pointcut can apply on any method.
/// </returns>
public static bool CanApply(
IPointcut pointcut, Type targetType, Type[] proxyInterfaces)
{
if (!pointcut.TypeFilter.Matches(targetType))
{
return false;
}
// It may apply to the class
// Check whether it can apply on any method
// Checks public methods, including inherited methods
MethodInfo[] methods = targetType.GetMethods();
for (int i = 0; i < methods.Length; ++i)
{
MethodInfo m = methods[i];
// If we're looking only at interfaces and this method
// isn't on any of them, skip it
if (proxyInterfaces != null
&& !ReflectionUtils.MethodIsOnOneOfTheseInterfaces(m, proxyInterfaces))
{
continue;
}
if (pointcut.MethodMatcher.Matches(m, targetType))
{
return true;
}
}
return false;
}
/// <summary>
/// Can the supplied <paramref name="advisor"/> apply at all on the
/// supplied <paramref name="targetType"/>?
/// </summary>
/// <remarks>
/// <p>
/// This is an important test as it can be used to optimize out an
/// advisor for a class.
/// </p>
/// </remarks>
/// <param name="advisor">The advisor to check.</param>
/// <param name="targetType">The class being tested.</param>
/// <param name="proxyInterfaces">
/// The interfaces being proxied. If <see langword="null"/>, all
/// methods on a class may be proxied.
/// </param>
/// <returns>
/// <see langword="true"/> if the advisor can apply on any method.
/// </returns>
public static bool CanApply(
IAdvisor advisor, Type targetType, Type[] proxyInterfaces)
{
if (advisor is IIntroductionAdvisor)
{
return ((IIntroductionAdvisor)advisor).TypeFilter.Matches(targetType);
}
else if (advisor is IPointcutAdvisor)
{
IPointcutAdvisor pca = (IPointcutAdvisor)advisor;
return CanApply(pca.Pointcut, targetType, proxyInterfaces);
}
// no pointcut specified so assume it applies...
return true;
}
#region Constructor (s) / Destructor
// CLOVER:OFF
/// <summary>
/// Creates a new instance of the
/// <see cref="AopUtils"/> class.
/// </summary>
/// <remarks>
/// <p>
/// This is a utility class, and as such has no publicly
/// visible constructors.
/// </p>
/// </remarks>
private AopUtils()
{
}
// CLOVER:ON
#endregion
/// <summary>
/// Gets the type of the target.
/// </summary>
/// <param name="candidate">The candidate.</param>
/// <returns></returns>
public static Type GetTargetType(object candidate)
{
AssertUtils.ArgumentNotNull(candidate, "candidate", "Candidate object must not be null");
if (candidate is ITargetSource)
{
return ((ITargetSource)candidate).TargetType;
}
if (candidate is IAdvised)
{
return ((IAdvised)candidate).TargetSource.TargetType;
}
if (IsDecoratorAopProxy(candidate))
{
return candidate.GetType().BaseType;
}
return candidate.GetType();
}
}
}

View File

@@ -78,7 +78,7 @@ namespace Spring.Aop.Framework.AutoProxy
/// <summary>
/// The logger for this class hierarchy.
/// </summary>
protected readonly ILog logger = LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod().DeclaringType );
protected readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// Convenience constant for subclasses: Return value for "do not proxy".
@@ -128,11 +128,11 @@ namespace Spring.Aop.Framework.AutoProxy
/// creator created a custom TargetSource for. Used to detect own pre-built proxies
/// (from "PostProcessBeforeInstantiation") in the "PostProcessAfterInitialization" method.
/// </summary>
private ISet targetSourcedObjects = new SynchronizedSet( new HashedSet() );
private ISet targetSourcedObjects = new SynchronizedSet(new HashedSet());
private ISet advisedObjects = new SynchronizedSet( new HashedSet() );
private ISet advisedObjects = new SynchronizedSet(new HashedSet());
private ISet nonAdvisedObjects = new SynchronizedSet( new HashedSet() );
private ISet nonAdvisedObjects = new SynchronizedSet(new HashedSet());
#endregion
@@ -224,69 +224,66 @@ namespace Spring.Aop.Framework.AutoProxy
/// Create a proxy with the configured interceptors if the object is
/// identified as one to proxy by the subclass.
/// </summary>
public virtual object PostProcessAfterInitialization( object obj, string objectName )
public virtual object PostProcessAfterInitialization(object obj, string objectName)
{
if (targetSourcedObjects.Contains( objectName ))
if (targetSourcedObjects.Contains(objectName))
{
return obj;
}
object cacheKey = GetCacheKey( obj.GetType(), objectName );
if (nonAdvisedObjects.Contains( cacheKey ))
Type objectType = RemotingServices.IsTransparentProxy(obj)
? ObjectFactory.GetType(objectName)
: obj.GetType();
object cacheKey = GetCacheKey(objectType, objectName);
if (nonAdvisedObjects.Contains(cacheKey))
{
return obj;
}
if (IsInfrastructureType( obj.GetType(), objectName ))
if (IsInfrastructureType(objectType, objectName))
{
#region Instrumentation
if (logger.IsDebugEnabled)
{
logger.Debug( string.Format( "Did not attempt to autoproxy infrastructure type [{0}]", obj.GetType() ) );
logger.Debug(string.Format("Did not attempt to autoproxy infrastructure type [{0}]", objectType));
}
#endregion
nonAdvisedObjects.Add( cacheKey );
nonAdvisedObjects.Add(cacheKey);
return obj;
}
if (ShouldSkip( obj.GetType(), objectName ))
if (ShouldSkip(objectType, objectName))
{
#region Instrumentation
if (logger.IsDebugEnabled)
{
logger.Debug( string.Format( "Skipping type [{0}]", obj.GetType() ) );
logger.Debug(string.Format("Skipping type [{0}]", objectType));
}
#endregion
nonAdvisedObjects.Add( cacheKey );
nonAdvisedObjects.Add(cacheKey);
return obj;
}
//ITargetSource targetSource = GetCustomTargetSource(obj.GetType(), objectName);
object[] specificInterceptors;
if (RemotingServices.IsTransparentProxy( obj ))
{
specificInterceptors = GetAdvicesAndAdvisorsForObject( ObjectFactory.GetType( objectName ), objectName, null );
}
else
{
specificInterceptors = GetAdvicesAndAdvisorsForObject( obj.GetType(), objectName, null );
}
specificInterceptors = GetAdvicesAndAdvisorsForObject(objectType, objectName, null);
// proxy if we have advice or if a TargetSourceCreator wants to do some
// fancy stuff such as pooling
if (specificInterceptors != DO_NOT_PROXY)
{
advisedObjects.Add( cacheKey );
return CreateProxy( obj.GetType(), objectName, specificInterceptors, new SingletonTargetSource( obj ) );
advisedObjects.Add(cacheKey);
return CreateProxy(objectType, objectName, specificInterceptors, new SingletonTargetSource(obj, objectType));
}
nonAdvisedObjects.Add( cacheKey );
nonAdvisedObjects.Add(cacheKey);
return obj;
}
@@ -296,7 +293,7 @@ namespace Spring.Aop.Framework.AutoProxy
/// <param name="obj">The obj.</param>
/// <param name="name">The name.</param>
/// <returns></returns>
public virtual object PostProcessBeforeInitialization( object obj, string name )
public virtual object PostProcessBeforeInitialization(object obj, string name)
{
return obj;
}
@@ -361,7 +358,7 @@ namespace Spring.Aop.Framework.AutoProxy
/// <param name="objectType">the type of the object</param>
/// <param name="objectName">the name of the object</param>
/// <returns>if remarkable to skip</returns>
protected virtual bool ShouldSkip( Type objectType, string objectName )
protected virtual bool ShouldSkip(Type objectType, string objectName)
{
return false;
}
@@ -373,7 +370,7 @@ namespace Spring.Aop.Framework.AutoProxy
/// <param name="pf">
/// ProxyFactory that will be used to create the proxy immediably after this method returns.
/// </param>
protected virtual void CustomizeProxyFactory( ProxyFactory pf )
protected virtual void CustomizeProxyFactory(ProxyFactory pf)
{
// This implementation does nothing
}
@@ -387,12 +384,12 @@ namespace Spring.Aop.Framework.AutoProxy
/// <returns>
/// <c>true</c> if [is infrastructure type] [the specified obj]; otherwise, <c>false</c>.
/// </returns>
protected virtual bool IsInfrastructureType( Type type, String name )
protected virtual bool IsInfrastructureType(Type type, String name)
{
return typeof( IAdvisor ).IsAssignableFrom( type )
|| typeof( IAdvice ).IsAssignableFrom( type )
|| typeof( IAdvisors ).IsAssignableFrom( type )
|| typeof( AbstractAutoProxyCreator ).IsAssignableFrom( type );
return typeof(IAdvisor).IsAssignableFrom(type)
|| typeof(IAdvice).IsAssignableFrom(type)
|| typeof(IAdvisors).IsAssignableFrom(type)
|| typeof(AbstractAutoProxyCreator).IsAssignableFrom(type);
}
@@ -406,22 +403,22 @@ namespace Spring.Aop.Framework.AutoProxy
/// <param name="objectType">the type of the object to create a TargetSource for</param>
/// <param name="name">the name of the object</param>
/// <returns>a TargetSource for this object</returns>
protected virtual ITargetSource GetCustomTargetSource( Type objectType, string name )
protected virtual ITargetSource GetCustomTargetSource(Type objectType, string name)
{
// We can't create fancy target sources for directly registered singletons.
if (customTargetSourceCreators != null &&
owningObjectFactory != null && owningObjectFactory.ContainsObject( name ))
owningObjectFactory != null && owningObjectFactory.ContainsObject(name))
{
for (int i = 0; i < customTargetSourceCreators.Count; i++)
{
ITargetSourceCreator tsc = (ITargetSourceCreator)customTargetSourceCreators[i];
ITargetSource ts = tsc.GetTargetSource( objectType, name, owningObjectFactory );
ITargetSource ts = tsc.GetTargetSource(objectType, name, owningObjectFactory);
if (ts != null)
{
// found a match
if (logger.IsInfoEnabled)
{
logger.Info( string.Format( "TargetSourceCreator [{0} found custom TargetSource for object with objectName '{1}'", tsc, name ) );
logger.Info(string.Format("TargetSourceCreator [{0} found custom TargetSource for object with objectName '{1}'", tsc, name));
}
return ts;
}
@@ -451,7 +448,7 @@ namespace Spring.Aop.Framework.AutoProxy
/// <returns>an array of additional interceptors for the particular object;
/// or an empty array if no additional interceptors but just the common ones;
/// or null if no proxy at all, not even with the common interceptors.</returns>
protected abstract object[] GetAdvicesAndAdvisorsForObject( Type objType, string name, ITargetSource customTargetSource );
protected abstract object[] GetAdvicesAndAdvisorsForObject(Type objType, string name, ITargetSource customTargetSource);
/// <summary>
/// Create an AOP proxy for the given object.
@@ -462,11 +459,11 @@ namespace Spring.Aop.Framework.AutoProxy
/// object (may be empty but not null)</param>
/// <param name="targetSource">The target source for the proxy, already pre-configured to access the object.</param>
/// <returns>The AOP Proxy for the object.</returns>
protected virtual object CreateProxy( Type objectType, string objectName, object[] specificInterceptors, ITargetSource targetSource )
protected virtual object CreateProxy(Type objectType, string objectName, object[] specificInterceptors, ITargetSource targetSource)
{
ProxyFactory proxyFactory = CreateProxyFactory();
// copy our properties (proxyTargetClass) inherited from ProxyConfig
proxyFactory.CopyFrom( this );
proxyFactory.CopyFrom(this);
object target = targetSource.GetTarget();
@@ -475,29 +472,29 @@ namespace Spring.Aop.Framework.AutoProxy
{
// Must allow for introductions; can't just set interfaces to
// the target's interfaces only.
Type[] targetInterfaceTypes = AopUtils.GetAllInterfaces( target );
Type[] targetInterfaceTypes = AopUtils.GetAllInterfacesFromType(objectType);
foreach (Type interfaceType in targetInterfaceTypes)
{
proxyFactory.AddInterface( interfaceType );
proxyFactory.AddInterface(interfaceType);
}
}
IAdvisor[] advisors = BuildAdvisors( objectName, specificInterceptors );
IAdvisor[] advisors = BuildAdvisors(objectName, specificInterceptors);
foreach (IAdvisor advisor in advisors)
{
if (advisor is IIntroductionAdvisor)
{
proxyFactory.AddIntroduction( (IIntroductionAdvisor)advisor );
proxyFactory.AddIntroduction((IIntroductionAdvisor)advisor);
}
else
{
proxyFactory.AddAdvisor( advisor );
proxyFactory.AddAdvisor(advisor);
}
}
proxyFactory.TargetSource = targetSource;
CustomizeProxyFactory( proxyFactory );
CustomizeProxyFactory(proxyFactory);
proxyFactory.IsFrozen = freezeProxy;
return proxyFactory.GetProxy();
@@ -520,7 +517,7 @@ namespace Spring.Aop.Framework.AutoProxy
/// <param name="specificInterceptors">The set of interceptors that is specific to this
/// object (may be empty, but not null)</param>
/// <returns>The list of Advisors for the given object</returns>
protected virtual IAdvisor[] BuildAdvisors( string objectName, object[] specificInterceptors )
protected virtual IAdvisor[] BuildAdvisors(string objectName, object[] specificInterceptors)
{
// handle prototypes correctly
IAdvisor[] commonInterceptors = ResolveInterceptorNames();
@@ -528,16 +525,16 @@ namespace Spring.Aop.Framework.AutoProxy
ArrayList allInterceptors = new ArrayList();
if (specificInterceptors != null)
{
allInterceptors.AddRange( specificInterceptors );
allInterceptors.AddRange(specificInterceptors);
if (commonInterceptors != null)
{
if (applyCommonInterceptorsFirst)
{
allInterceptors.InsertRange( 0, commonInterceptors );
allInterceptors.InsertRange(0, commonInterceptors);
}
else
{
allInterceptors.AddRange( commonInterceptors );
allInterceptors.AddRange(commonInterceptors);
}
}
}
@@ -545,14 +542,14 @@ namespace Spring.Aop.Framework.AutoProxy
{
int nrOfCommonInterceptors = commonInterceptors != null ? commonInterceptors.Length : 0;
int nrOfSpecificInterceptors = specificInterceptors != null ? specificInterceptors.Length : 0;
logger.Info( string.Format( "Creating implicit proxy for object '{0}' with {1} common interceptors and {2} specific interceptors", objectName, nrOfCommonInterceptors, nrOfSpecificInterceptors ) );
logger.Info(string.Format("Creating implicit proxy for object '{0}' with {1} common interceptors and {2} specific interceptors", objectName, nrOfCommonInterceptors, nrOfSpecificInterceptors));
}
IAdvisor[] advisors = new IAdvisor[allInterceptors.Count];
for (int i = 0; i < allInterceptors.Count; i++)
{
advisors[i] = advisorAdapterRegistry.Wrap( allInterceptors[i] );
advisors[i] = advisorAdapterRegistry.Wrap(allInterceptors[i]);
}
return advisors;
}
@@ -563,7 +560,7 @@ namespace Spring.Aop.Framework.AutoProxy
/// <param name="objectType">The object type.</param>
/// <param name="objectName">The object name.</param>
/// <returns>The cache key for the given type and name</returns>
protected virtual object GetCacheKey( Type objectType, string objectName )
protected virtual object GetCacheKey(Type objectType, string objectName)
{
return objectType.FullName + "_" + objectName;
}
@@ -578,17 +575,17 @@ namespace Spring.Aop.Framework.AutoProxy
ArrayList advisors = new ArrayList();
foreach (string name in interceptorNames)
{
object next = owningObjectFactory.GetObject( name );
object next = owningObjectFactory.GetObject(name);
if (next is IAdvisors)
{
advisors.AddRange( ((IAdvisors)next).Advisors );
advisors.AddRange(((IAdvisors)next).Advisors);
}
else
{
advisors.Add( advisorAdapterRegistry.Wrap( next ) );
advisors.Add(advisorAdapterRegistry.Wrap(next));
}
}
return (IAdvisor[])advisors.ToArray( typeof( IAdvisor ) );
return (IAdvisor[])advisors.ToArray(typeof(IAdvisor));
}
#endregion
@@ -601,55 +598,55 @@ namespace Spring.Aop.Framework.AutoProxy
/// <param name="objectType">The object type</param>
/// <param name="objectName">The object name</param>
/// <returns>null if not creating a proxy, otherwise return the proxy.</returns>
public object PostProcessBeforeInstantiation( Type objectType, string objectName )
public object PostProcessBeforeInstantiation(Type objectType, string objectName)
{
object cacheKey = GetCacheKey( objectType, objectName );
if (!targetSourcedObjects.Contains( cacheKey ))
object cacheKey = GetCacheKey(objectType, objectName);
if (!targetSourcedObjects.Contains(cacheKey))
{
if (advisedObjects.Contains( cacheKey ) || nonAdvisedObjects.Contains( cacheKey ))
if (advisedObjects.Contains(cacheKey) || nonAdvisedObjects.Contains(cacheKey))
{
return null;
}
if (IsInfrastructureType( objectType, objectName ))
if (IsInfrastructureType(objectType, objectName))
{
#region Instrumentation
if (logger.IsDebugEnabled)
{
logger.Debug( string.Format( "Did not attempt to autoproxy infrastructure type [{0}]", objectType ) );
logger.Debug(string.Format("Did not attempt to autoproxy infrastructure type [{0}]", objectType));
}
#endregion
nonAdvisedObjects.Add( cacheKey );
nonAdvisedObjects.Add(cacheKey);
return null;
}
if (ShouldSkip( objectType, objectName ))
if (ShouldSkip(objectType, objectName))
{
#region Instrumentation
if (logger.IsDebugEnabled)
{
logger.Debug( string.Format( "Skipping type [{0}]", objectType ) );
logger.Debug(string.Format("Skipping type [{0}]", objectType));
}
#endregion
nonAdvisedObjects.Add( cacheKey );
nonAdvisedObjects.Add(cacheKey);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target object:
// The TargetSource will handle target instances in a custom fashion.
ITargetSource targetSource = GetCustomTargetSource( objectType, objectName );
ITargetSource targetSource = GetCustomTargetSource(objectType, objectName);
if (targetSource != null)
{
targetSourcedObjects.Add( objectName );
object[] specificInterceptors = GetAdvicesAndAdvisorsForObject( objectType, objectName, targetSource );
return CreateProxy( objectType, objectName, specificInterceptors, targetSource );
targetSourcedObjects.Add(objectName);
object[] specificInterceptors = GetAdvicesAndAdvisorsForObject(objectType, objectName, targetSource);
return CreateProxy(objectType, objectName, specificInterceptors, targetSource);
}
return null;
}
@@ -661,7 +658,7 @@ namespace Spring.Aop.Framework.AutoProxy
/// <param name="objectInstance">The object instance</param>
/// <param name="objectName">The object name.</param>
/// <returns>true</returns>
public bool PostProcessAfterInstantiation( object objectInstance, string objectName )
public bool PostProcessAfterInstantiation(object objectInstance, string objectName)
{
return true;
}
@@ -676,8 +673,8 @@ namespace Spring.Aop.Framework.AutoProxy
/// been set.</param>
/// <param name="objectName">Name of the object.</param>
/// <returns>The passed in PropertyValues</returns>
public IPropertyValues PostProcessPropertyValues( IPropertyValues pvs, PropertyInfo[] pis, object objectInstance,
string objectName )
public IPropertyValues PostProcessPropertyValues(IPropertyValues pvs, PropertyInfo[] pis, object objectInstance,
string objectName)
{
return pvs;
}

View File

@@ -44,7 +44,8 @@ namespace Spring.Aop.Target
[Serializable]
public sealed class SingletonTargetSource : ITargetSource
{
private object target;
private object target;
private Type targetType;
/// <summary>
/// Creates a new instance of the
@@ -57,9 +58,26 @@ namespace Spring.Aop.Target
/// <see langword="null"/>.
/// </exception>
public SingletonTargetSource(object target)
:this(target, target != null ? target.GetType() : null)
{}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Target.SingletonTargetSource"/>
/// for the specified target object.
/// </summary>
/// <param name="target">The target object to expose.</param>
/// <param name="targetType">The type of <paramref name="target"/> to expose.</param>
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="target"/> is
/// <see langword="null"/>.
/// </exception>
public SingletonTargetSource(object target, Type targetType)
{
AssertUtils.ArgumentNotNull(target, "target");
this.target = target;
AssertUtils.ArgumentNotNull(targetType, "targetType");
this.target = target;
this.targetType = targetType;
}
#region ITarget Source impl
@@ -69,7 +87,7 @@ namespace Spring.Aop.Target
/// </summary>
public Type TargetType
{
get { return target.GetType(); }
get { return targetType; }
}
/// <summary>

View File

@@ -43,16 +43,6 @@ namespace Spring.Aop.Framework.DynamicProxy
[TestFixture]
public sealed class AopUtilsTests
{
[Test]
public void GetAllInterfaces()
{
DerivedTestObject testObject = new DerivedTestObject();
IList interfaces = new ArrayList(testObject.GetType().GetInterfaces());
Assert.AreEqual(9, interfaces.Count, "Incorrect number of interfaces");
Assert.IsTrue(interfaces.Contains(typeof (ITestObject)), "Does not contain ITestObject");
Assert.IsTrue(interfaces.Contains(typeof (IOther)), "Does not contain IOther");
}
[Test]
public void PointcutCanNeverApply()
{
@@ -103,6 +93,19 @@ namespace Spring.Aop.Framework.DynamicProxy
Assert.IsTrue(AopUtils.CanApply((IAdvisor) null, typeof (TestObject), null));
}
/// <summary>
/// Test preconditions for all tests related to GetAllInterfaces
/// </summary>
[Test]
public void GetAllInterfacesTestsPreconditions()
{
DerivedTestObject testObject = new DerivedTestObject();
IList interfaces = new ArrayList(testObject.GetType().GetInterfaces());
Assert.AreEqual(9, interfaces.Count, "Incorrect number of interfaces");
Assert.IsTrue(interfaces.Contains(typeof(ITestObject)), "Does not contain ITestObject");
Assert.IsTrue(interfaces.Contains(typeof(IOther)), "Does not contain IOther");
}
[Test]
public void GetAllInterfacesWithNull()
{
@@ -113,6 +116,13 @@ namespace Spring.Aop.Framework.DynamicProxy
"Must return an empty array is the argument is null.");
}
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void GetAllInterfacesFromTypeWithNull()
{
AopUtils.GetAllInterfacesFromType(null);
}
[Test]
public void GetAllInterfacesWithObjectThatDoesntImpementAnything()
{

View File

@@ -123,6 +123,7 @@
<Compile Include="Aop\Framework\AopContextTests.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Aop\Framework\AutoProxy\AbstractAutoProxyCreatorTests.cs" />
<Compile Include="Aop\Framework\AutoProxy\AdvisorAutoProxyCreatorCircularReferencesTests.cs" />
<Compile Include="Aop\Framework\AutoProxy\AdvisorAutoProxyCreatorTests.cs" />
<Compile Include="Aop\Framework\AutoProxy\AttributeAutoProxyCreatorTests.cs" />