synced AbstractAdvisorAutoProxyCreator hierarchy w/ Spring/J

introduced new "Role" property in IObjectDefinition
prepared introducing InfrastructureAdvisorAutoProxyCreator
This commit is contained in:
eeichinger
2009-06-25 20:06:10 +00:00
parent adb63f8e6d
commit ff3bb33a3a
22 changed files with 463 additions and 347 deletions

View File

@@ -1,18 +1,19 @@
Changes (1.2.0 to 1.2.1)
Changes (1.2.0 to 1.2.1 or greater)
========================
Spring.Core
-----------
1. within an ValidationGroup element (<v:group>,<v:exclusive>,..), nested validator elements now must occur after any
1. within an ValidationGroup element (<v:group>,<v:exclusive>,..), nested validator elements now must occur after any
<v:message>, <v:action> or <v:property> elements. The following was allowed previously, but now will raise a schema
validation error:
<v:group ..>
<v:validator ...>
<v:action ...>
change this to
<v:group ..>
<v:action ...>
<v:validator ...>
@@ -20,17 +21,31 @@ Spring.Core
2. XmlReaderContext constructor now requires an IObjectDefinitionFactory to be specified. Thus XmlReaderContext.ObjectDefinitionFactory
is read only now.
3. Changes to the Apache NMS API, which was not yet a public release when included in Spring 1.2.0 made breaking API changes.
3. Changes to the Apache NMS API, which was not yet a public release when included in Spring 1.2.0 made breaking API changes.
On NmsTemlate,
1) The property 'byte Priority' was changed to 'MsgPriority Priority'
2) The property 'bool Persistent' is no longer part of the NMS API but is still supported in a backward compatible
manner by Spring by translation to standard MsgDeliveryMode enumeration values of Persistent and NonPersistent.
A new property MsgDelivery has been added. The class, CachedMessageProducer, which is unlikely to be use by
A new property MsgDelivery has been added. The class, CachedMessageProducer, which is unlikely to be use by
end users, was directly upgraded to the latest API without any backwards compatibility support.
Spring.Aop
----------
1. AbstractAutoProxyCreator.FindEligibleAdvisors(Type) changed to
AbstractAutoProxyCreator.FindEligibleAdvisors(Type, Name)
Changes (1.2 RC1 to 1.2.0 or greater)
=====================================
none
Changes (1.1.2 to 1.2 RC1 or greater)
=====================================
Spring.Core
-----------

View File

@@ -35,21 +35,18 @@ namespace Spring.Aop.Config
{
/// <summary>
/// Utility class for handling registration of auto-proxy creators used internally by the
/// <code>aop</code> namespace tags.
/// <code>aop</code> and <code>tx</code> namespace tags.
/// </summary>
/// <author>Rob Harrop</author>
/// <author>Juergen Hoeller</author>
/// <author>Mark Pollack (.NET)</author>
/// <author>Mark Pollack (.NET)</author>
/// <author>Erich Eichinger (.NET)</author>
public class AopNamespaceUtils
{
/// <summary>
/// The object name of the internally managed auto-proxy creator.
/// </summary>
public const string AUTO_PROXY_CREATOR_OBJECT_NAME =
"Spring.Aop.Config.InternalAutoProxyCreator";
public static readonly string AUTO_PROXY_CREATOR_OBJECT_NAME = "Spring.Aop.Config.InternalAutoProxyCreator";
/// <summary>
/// Registers the auto proxy creator if necessary.

View File

@@ -21,6 +21,7 @@
#region Imports
using System;
using System.Collections;
using System.Reflection;
using Spring.Collections;
using Spring.Util;
@@ -217,8 +218,36 @@ namespace Spring.Aop.Framework
/// <returns>
/// <see langword="true"/> if the pointcut can apply on any method.
/// </returns>
public static bool CanApply(
IPointcut pointcut, Type targetType, Type[] proxyInterfaces)
public static bool CanApply(IPointcut pointcut, Type targetType, Type[] proxyInterfaces)
{
return CanApply(pointcut, targetType, proxyInterfaces, false);
}
/// <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>
/// <param name="hasIntroductions">whether or not the advisor chain for the target object includes any introductions.</param>
/// <returns>
/// <see langword="true"/> if the pointcut can apply on any method.
/// </returns>
public static bool CanApply(IPointcut pointcut, Type targetType, Type[] proxyInterfaces, bool hasIntroductions)
{
if (!pointcut.TypeFilter.Matches(targetType))
{
@@ -266,8 +295,32 @@ namespace Spring.Aop.Framework
/// <returns>
/// <see langword="true"/> if the advisor can apply on any method.
/// </returns>
public static bool CanApply(
IAdvisor advisor, Type targetType, Type[] proxyInterfaces)
public static bool CanApply(IAdvisor advisor, Type targetType, Type[] proxyInterfaces)
{
return CanApply(advisor, targetType, proxyInterfaces, 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>
/// <param name="hasIntroductions">whether or not the advisor chain for the target object includes any introductions.</param>
/// <returns>
/// <see langword="true"/> if the advisor can apply on any method.
/// </returns>
public static bool CanApply(IAdvisor advisor, Type targetType, Type[] proxyInterfaces, bool hasIntroductions)
{
if (advisor is IIntroductionAdvisor)
{
@@ -276,7 +329,7 @@ namespace Spring.Aop.Framework
else if (advisor is IPointcutAdvisor)
{
IPointcutAdvisor pca = (IPointcutAdvisor)advisor;
return CanApply(pca.Pointcut, targetType, proxyInterfaces);
return CanApply(pca.Pointcut, targetType, proxyInterfaces, hasIntroductions);
}
// no pointcut specified so assume it applies...
return true;

View File

@@ -22,17 +22,19 @@
using System;
using System.Collections;
using Common.Logging;
using Spring.Aop.Framework.DynamicProxy;
using Spring.Core;
using Spring.Objects.Factory;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Config;
using Spring.Util;
#endregion
namespace Spring.Aop.Framework.AutoProxy
{
/// <summary>
/// Abstract IOBjectPostProcessor implementation that creates AOP proxies.
/// Abstract IObjectPostProcessor implementation that creates AOP proxies.
/// This class is completely generic; it contains no special code to handle
/// any particular aspects, such as pooling aspects.
/// </summary>
@@ -50,9 +52,21 @@ namespace Spring.Aop.Framework.AutoProxy
/// </remarks>
/// <seealso cref="Spring.Aop.Framework.AutoProxy.AbstractAdvisorAutoProxyCreator.FindCandidateAdvisors"/>
/// <author>Rod Johnson</author>
/// <author>Adhari C Mahendra (.NET)</author>
/// <author>Adhari C Mahendra (.NET)</author>
/// <author>Erich Eichinger</author>
public abstract class AbstractAdvisorAutoProxyCreator : AbstractAutoProxyCreator
{
private readonly ILog Log;
private ObjectFactoryAdvisorRetrievalHelper _advisorRetrievalHelper;
/// <summary>
/// Initialize
/// </summary>
protected AbstractAdvisorAutoProxyCreator()
{
Log = LogManager.GetLogger(this.GetType());
}
/// <summary>
/// We override this method to ensure that all candidate advisors are materialized
/// under a stack trace including this object. Otherwise, the dependencies won't
@@ -60,85 +74,139 @@ namespace Spring.Aop.Framework.AutoProxy
/// </summary>
public override IObjectFactory ObjectFactory
{
//TODO investigate override...
set
{
base.ObjectFactory = value;
if (!(value is IConfigurableListableObjectFactory))
{
throw new InvalidOperationException(
"Can not use AdvisorAutoProxyCreator without a ConfigurableListableObjectFactory");
throw new InvalidOperationException("Can not use AdvisorAutoProxyCreator without a ConfigurableListableObjectFactory");
}
InitObjectFactory((IConfigurableListableObjectFactory) value);
}
get { return base.ObjectFactory; }
}
/// <summary>
/// An new <see cref="IConfigurableListableObjectFactory"/> was set. Initialize this creator instance
/// according to the specified object factory.
/// </summary>
/// <param name="objectFactory"></param>
protected virtual void InitObjectFactory(IConfigurableListableObjectFactory objectFactory)
{
_advisorRetrievalHelper = new ObjectFactoryAdvisorRetrievalHelperAdapter(this, objectFactory);
}
/// <summary>
/// Return whether the given object is to be proxied, what additional
/// advices (e.g. AOP Alliance interceptors) and advisors to apply.
/// </summary>
/// <param name="objType">the new object instance</param>
/// <param name="name">the name of the object</param>
/// <param name="customTargetSource">targetSource returned by TargetSource property:
/// may be ignored. Will be null unless a custom target source is in use.</param>
/// <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>
/// <remarks>
/// <p>The previous name of this method was "GetInterceptorAndAdvisorForObject".
/// <p>The previous targetName of this method was "GetInterceptorAndAdvisorForObject".
/// It has been renamed in the course of general terminology clarification
/// in Spring 1.1. An AOP Alliance Interceptor is just a special form of
/// Advice, so the generic Advice term is preferred now.</p>
/// <p>The third parameter, customTargetSource, is new in Spring 1.1;
/// add it to existing implementations of this method.</p>
/// </remarks>
protected override object[] GetAdvicesAndAdvisorsForObject(Type objType, string name, ITargetSource customTargetSource)
/// </remarks>
/// <param name="targetType">the type of the target object</param>
/// <param name="targetName">the name of the target object</param>
/// <param name="customTargetSource">targetSource returned by TargetSource property:
/// may be ignored. Will be null unless a custom target source is in use.</param>
/// <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 override object[] GetAdvicesAndAdvisorsForObject(Type targetType, string targetName, ITargetSource customTargetSource)
{
IList advisors = FindEligibleAdvisors(objType);
IList advisors = FindEligibleAdvisors(targetType, targetName);
if (advisors.Count == 0)
{
return DO_NOT_PROXY;
}
advisors = SortAdvisors(advisors);
if (advisors is ArrayList)
return ((ArrayList) advisors).ToArray();
else
{
return advisors as object[];
}
return (object[]) CollectionUtils.ToArray(advisors, typeof (object));
}
/// <summary>
/// Find all eligible advices and for autoproxying this class.
/// </summary>
/// <param name="type"></param>
/// <returns>the empty list, not null, if there are no pointcuts or interceptors</returns>
protected IList FindEligibleAdvisors(Type type)
/// <param name="targetType">the type of the object to be advised</param>
/// <param name="targetName">the name of the object to be advised</param>
/// <returns>
/// the empty list, not null, if there are no pointcuts or interceptors.
/// The by-order sorted list of advisors otherwise
/// </returns>
protected IList FindEligibleAdvisors(Type targetType, string targetName)
{
IList candidateAdvisors = FindCandidateAdvisors();
IList eligibleAdvisors = new ArrayList();
for (int i = 0; i < candidateAdvisors.Count; i++)
{
IAdvisor candidate = (IAdvisor) candidateAdvisors[i];
if (AopUtils.CanApply(candidate, type, null))
{
eligibleAdvisors.Add(candidate);
if (logger.IsInfoEnabled)
{
logger.Info(string.Format("Candidate advisor [{0}] accepted for type [{1}]", candidate, type.ToString()));
}
}
else
{
if (logger.IsInfoEnabled)
{
logger.Info(string.Format("Candidate advisor [{0}] rejected for type [{1}]", candidate, type.ToString()));
}
}
}
IList candidateAdvisors = FindCandidateAdvisors(targetType, targetName);
IList eligibleAdvisors = FindAdvisorsThatCanApply(candidateAdvisors, targetType, targetName);
ExtendAdvisors(eligibleAdvisors, targetType, targetName);
eligibleAdvisors = SortAdvisors(eligibleAdvisors);
return eligibleAdvisors;
}
/// <summary>
/// Find all possible advisor candidates to use in auto-proxying
/// </summary>
/// <param name="targetType">the type of the object to be advised</param>
/// <param name="targetName">the name of the object to be advised</param>
/// <returns>the list of candidate advisors</returns>
protected virtual IList FindCandidateAdvisors(Type targetType, string targetName)
{
return _advisorRetrievalHelper.FindAdvisorObjects(targetType, targetName);
}
/// <summary>
/// From the given list of candidate advisors, select the ones that are applicable
/// to the given target specified by targetType and name.
/// </summary>
/// <param name="candidateAdvisors">the list of candidate advisors to date</param>
/// <param name="targetType">the target object's type</param>
/// <param name="targetName">the target object's name</param>
/// <returns>the list of applicable advisors</returns>
protected virtual IList FindAdvisorsThatCanApply(IList candidateAdvisors, Type targetType, string targetName)
{
if (candidateAdvisors.Count==0)
{
return candidateAdvisors;
}
ArrayList eligibleAdvisors = new ArrayList();
foreach(IAdvisor candidate in candidateAdvisors)
{
if (candidate is IIntroductionAdvisor && AopUtils.CanApply(candidate, targetType, null))
{
if (logger.IsInfoEnabled)
{
logger.Info(string.Format("Candidate advisor [{0}] accepted for targetType [{1}]", candidate, targetType));
}
eligibleAdvisors.Add(candidate);
}
}
bool hasIntroductions = eligibleAdvisors.Count > 0;
foreach(IAdvisor candidate in candidateAdvisors)
{
if (candidate is IIntroductionAdvisor) continue;
if (AopUtils.CanApply(candidate, targetType, null, hasIntroductions))
{
if (logger.IsInfoEnabled)
{
logger.Info(string.Format("Candidate advisor [{0}] accepted for targetType [{1}]", candidate, targetType));
}
eligibleAdvisors.Add(candidate);
}
else
{
if (logger.IsInfoEnabled)
{
logger.Info(string.Format("Candidate advisor [{0}] rejected for targetType [{1}]", candidate, targetType));
}
}
}
return eligibleAdvisors;
}
@@ -147,8 +215,13 @@ namespace Spring.Aop.Framework.AutoProxy
/// </summary>
/// <param name="advisors">The advisors.</param>
/// <returns></returns>
protected IList SortAdvisors(IList advisors)
protected virtual IList SortAdvisors(IList advisors)
{
if (advisors.Count==0)
{
return advisors;
}
if (advisors is ArrayList)
((ArrayList) advisors).Sort(new OrderComparator());
else if (advisors is Array)
@@ -156,10 +229,43 @@ namespace Spring.Aop.Framework.AutoProxy
return advisors;
}
/// <summary>
/// Find all candidate advisors to use in auto-proxying.
/// </summary>
/// <returns>list of Advisors</returns>
protected abstract IList FindCandidateAdvisors();
/// <summary>
/// Extension hook that subclasses can override to register additional advisors,
/// given the sorted advisors obtained to date.<br/>
/// The default implementation does nothing.<br/>
/// Typically used to add advisors that expose contextual information required by some of the later advisors.
/// </summary>
/// <param name="advisors">Advisors that have already been identified as applying to a given object</param>
/// <param name="objectType">the type of the object to be advised</param>
/// <param name="objectName">the name of the object to be advised</param>
protected virtual void ExtendAdvisors(IList advisors, Type objectType, string objectName)
{}
/// <summary>
/// Whether the given advisor is eligible for the specified target. The default implementation
/// always returns true.
/// </summary>
/// <param name="advisorName">the advisor name</param>
/// <param name="targetType">the target object's type</param>
/// <param name="targetName">the target object's name</param>
protected virtual bool IsEligibleAdvisorObject(string advisorName, Type targetType, string targetName)
{
return true;
}
private class ObjectFactoryAdvisorRetrievalHelperAdapter : ObjectFactoryAdvisorRetrievalHelper
{
private readonly AbstractAdvisorAutoProxyCreator _owner;
public ObjectFactoryAdvisorRetrievalHelperAdapter(AbstractAdvisorAutoProxyCreator owner, IConfigurableListableObjectFactory owningFactory) : base(owningFactory)
{
_owner = owner;
}
protected override bool IsEligibleObject(string advisorName, Type objectType, string objectName)
{
return _owner.IsEligibleAdvisorObject(advisorName, objectType, objectName);
}
}
}
}

View File

@@ -355,10 +355,10 @@ namespace Spring.Aop.Framework.AutoProxy
/// Sometimes we need to be able to avoid this happening if it will lead to
/// a circular reference. This implementation returns false.
/// </summary>
/// <param name="objectType">the type of the object</param>
/// <param name="objectName">the name of the object</param>
/// <param name="targetType">the type of the object</param>
/// <param name="targetName">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 targetType, string targetName)
{
return false;
}
@@ -434,32 +434,32 @@ namespace Spring.Aop.Framework.AutoProxy
/// advices (e.g. AOP Alliance interceptors) and advisors to apply.
/// </summary>
/// <remarks>
/// <p>The previous name of this method was "GetInterceptorAndAdvisorForObject".
/// <p>The previous targetName of this method was "GetInterceptorAndAdvisorForObject".
/// It has been renamed in the course of general terminology clarification
/// in Spring 1.1. An AOP Alliance Interceptor is just a special form of
/// Advice, so the generic Advice term is preferred now.</p>
/// <p>The third parameter, customTargetSource, is new in Spring 1.1;
/// add it to existing implementations of this method.</p>
/// </remarks>
/// <param name="objType">the new object instance</param>
/// <param name="name">the name of the object</param>
/// <param name="targetType">the new object instance</param>
/// <param name="targetName">the name of the object</param>
/// <param name="customTargetSource">targetSource returned by TargetSource property:
/// may be ignored. Will be null unless a custom target source is in use.</param>
/// <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 targetType, string targetName, ITargetSource customTargetSource);
/// <summary>
/// Create an AOP proxy for the given object.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <param name="objectName">The name of the object.</param>
/// <param name="targetType">Type of the object.</param>
/// <param name="targetName">The name of the object.</param>
/// <param name="specificInterceptors">The set of interceptors that is specific to this
/// 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 targetType, string targetName, object[] specificInterceptors, ITargetSource targetSource)
{
ProxyFactory proxyFactory = CreateProxyFactory();
// copy our properties (proxyTargetClass) inherited from ProxyConfig
@@ -472,7 +472,7 @@ namespace Spring.Aop.Framework.AutoProxy
{
// Must allow for introductions; can't just set interfaces to
// the target's interfaces only.
Type[] targetInterfaceTypes = AopUtils.GetAllInterfacesFromType(objectType);
Type[] targetInterfaceTypes = AopUtils.GetAllInterfacesFromType(targetType);
foreach (Type interfaceType in targetInterfaceTypes)
{
proxyFactory.AddInterface(interfaceType);
@@ -480,7 +480,7 @@ namespace Spring.Aop.Framework.AutoProxy
}
IAdvisor[] advisors = BuildAdvisors(objectName, specificInterceptors);
IAdvisor[] advisors = BuildAdvisors(targetName, specificInterceptors);
foreach (IAdvisor advisor in advisors)
{
@@ -513,11 +513,11 @@ namespace Spring.Aop.Framework.AutoProxy
/// Determines the advisors for the given object, including the specific interceptors
/// as well as the common interceptor, all adapted to the Advisor interface.
/// </summary>
/// <param name="objectName">The name of the object.</param>
/// <param name="targetName">The name of the object.</param>
/// <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 targetName, object[] specificInterceptors)
{
// handle prototypes correctly
IAdvisor[] commonInterceptors = ResolveInterceptorNames();
@@ -542,7 +542,7 @@ 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", targetName, nrOfCommonInterceptors, nrOfSpecificInterceptors));
}

View File

@@ -39,12 +39,12 @@ namespace Spring.Aop.Framework.AutoProxy
/// <summary>
///Overridden to call <see cref="IsEligibleForProxying"/>.
/// </summary>
/// <param name="objectType">the type of the object</param>
/// <param name="objectName">the name of the object</param>
/// <param name="targetType">the type of the object</param>
/// <param name="targetName">the name of the object</param>
/// <returns>if remarkable to skip</returns>
protected override bool ShouldSkip( Type objectType, string objectName )
protected override bool ShouldSkip( Type targetType, string targetName )
{
bool shouldSkip = !IsEligibleForProxying( objectType, objectName );
bool shouldSkip = !IsEligibleForProxying( targetType, targetName );
return shouldSkip;
}
@@ -54,14 +54,14 @@ namespace Spring.Aop.Framework.AutoProxy
/// <remarks>
/// Whether an object shall be proxied or not is determined by the result of <see cref="IsEligibleForProxying"/>.
/// </remarks>
/// <param name="objType">ingored</param>
/// <param name="name">ignored</param>
/// <param name="targetType">ingored</param>
/// <param name="targetName">ignored</param>
/// <param name="customTargetSource">ignored</param>
/// <returns>
/// Always <see cref="AbstractAutoProxyCreator.PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS"/> to indicate, that the object shall be proxied.
/// </returns>
/// <seealso cref="AbstractAutoProxyCreator.PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS"/>
protected override object[] GetAdvicesAndAdvisorsForObject( Type objType, string name, ITargetSource customTargetSource )
protected override object[] GetAdvicesAndAdvisorsForObject( Type targetType, string targetName, ITargetSource customTargetSource )
{
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
@@ -72,10 +72,10 @@ namespace Spring.Aop.Framework.AutoProxy
/// <remarks>
/// Override this method to allow or reject proxying for the given object.
/// </remarks>
/// <param name="objType">the object's type</param>
/// <param name="name">the name of the object</param>
/// <param name="targetType">the object's type</param>
/// <param name="targetName">the name of the object</param>
/// <seealso cref="AbstractAutoProxyCreator.ShouldSkip"/>
/// <returns>whether the given object shall be proxied.</returns>
protected abstract bool IsEligibleForProxying( Type objType, string name );
protected abstract bool IsEligibleForProxying( Type targetType, string targetName );
}
}

View File

@@ -61,15 +61,15 @@ namespace Spring.Aop.Framework.AutoProxy
}
/// <summary>
/// Determines, whether the given object shall be proxied by matching <paramref name="objType"/> against <see cref="AttributeTypes"/>.
/// Determines, whether the given object shall be proxied by matching <paramref name="targetType"/> against <see cref="AttributeTypes"/>.
/// </summary>
/// <param name="objType">the object's type</param>
/// <param name="name">the name of the object</param>
protected override bool IsEligibleForProxying( Type objType, string name )
/// <param name="targetType">the object's type</param>
/// <param name="targetName">the name of the object</param>
protected override bool IsEligibleForProxying( Type targetType, string targetName )
{
AssertUtils.ArgumentNotNull(this.AttributeTypes, "AttributeTypes");
bool shallProxy = IsAnnotatedWithAnyOfAttribute( objType, this.AttributeTypes, this.CheckInherited );
bool shallProxy = IsAnnotatedWithAnyOfAttribute( targetType, this.AttributeTypes, this.CheckInherited );
return shallProxy;
}

View File

@@ -21,9 +21,7 @@
#region Imports
using System;
using System.Collections;
using Spring.Objects.Factory;
using Spring.Objects.Factory.Config;
#endregion
@@ -36,16 +34,15 @@ namespace Spring.Aop.Framework.AutoProxy
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Adhari C Mahendra (.NET)</author>
public class DefaultAdvisorAutoProxyCreator : AbstractAdvisorAutoProxyCreator, IObjectNameAware, IInitializingObject
/// <author>Erich Eichinger (.NET)</author>
public class DefaultAdvisorAutoProxyCreator : AbstractAdvisorAutoProxyCreator, IObjectNameAware
{
/// <summary>
/// Separator between prefix and remainder of object name
/// </summary>
public static readonly string SEPARATOR = ".";
private bool usePrefix;
private string advisorObjectNamePrefix;
private IList advisors;
#region Properties
@@ -72,126 +69,45 @@ namespace Spring.Aop.Framework.AutoProxy
set { advisorObjectNamePrefix = value; }
}
#endregion
#region IObjectNameAware Members
/// <summary>
/// Set the name of the object in the object factory that created this object.
/// </summary>
/// <value>The name of the object in the factory.</value>
/// <remarks>
/// <p>
/// Invoked after population of normal object properties but before an init
/// callback like <see cref="T:Spring.Objects.Factory.IInitializingObject"/>'s
/// <see cref="M:Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
/// method or a custom init-method.
/// </p>
/// </remarks>
public string ObjectName
{
set
{
// If no infrastructure object name prefix has been set, override it.
if (advisorObjectNamePrefix == null)
{
advisorObjectNamePrefix = value + SEPARATOR;
}
}
}
#endregion
/// <summary>
/// Find all candidate advices to use in auto proxying.
/// </summary>
/// <returns>list of Advice</returns>
protected override IList FindCandidateAdvisors()
{
if (advisors == null)
{
throw new InvalidOperationException("Must not be called before AfterPropertiesSet()");
}
if (logger.IsDebugEnabled)
{
logger.Debug(string.Format("returning available advisors"));
}
return advisors;
/// <summary>
/// Whether the given advisor is eligible for the specified target.
/// </summary>
/// <param name="advisorName">the advisor name</param>
/// <param name="targetType">the target object's type</param>
/// <param name="targetName">the target object's name</param>
protected override bool IsEligibleAdvisorObject(string advisorName, Type targetType, string targetName)
{
return (!usePrefix || advisorName.StartsWith(advisorObjectNamePrefix));
}
private IList InstantiateCandidateAdvisors()
{
if (logger.IsDebugEnabled)
{
logger.Debug(string.Format("instantiating available advisors"));
}
//This is ensured in AbstractAdvisorAutoProxyCreator. Will be more type safe once sync with Spring Java 2.x
IConfigurableListableObjectFactory owningFactory = ObjectFactory as IConfigurableListableObjectFactory;
if (owningFactory == null)
{
throw new InvalidOperationException("Cannot use DefaultAdvisorAutoProxyCreator without a IListableObjectFactory");
}
ArrayList candidateAdvisors = new ArrayList();
string[] advisorNames = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(
owningFactory, typeof(IAdvisor), true, false);
for (int i = 0; i < advisorNames.Length; i++)
{
string name = advisorNames[i];
if ( (!usePrefix || name.StartsWith(advisorObjectNamePrefix)) && !owningFactory.IsCurrentlyInCreation(name))
{
try
{
IAdvisor advisor = (IAdvisor) owningFactory.GetObject(name);
candidateAdvisors.Add(advisor);
} catch (ObjectCreationException ex)
{
Exception rootEx = ex.GetBaseException();
if (rootEx is ObjectCurrentlyInCreationException)
{
ObjectCurrentlyInCreationException oce = (ObjectCurrentlyInCreationException) rootEx;
if (owningFactory.IsCurrentlyInCreation(oce.ObjectName))
{
if (logger.IsDebugEnabled)
{
logger.Debug(string.Format("Ignoring currently created advisor '{0}': exception message = {1}",
name, ex.Message));
}
continue;
}
}
throw;
}
}
}
string[] aspectNames = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(
owningFactory, typeof(IAdvisors), true, false);
for (int i = 0; i < aspectNames.Length; i++)
{
string name = aspectNames[i];
if (!usePrefix || name.StartsWith(advisorObjectNamePrefix))
{
IAdvisors advisors = (IAdvisors)owningFactory.GetObject(name);
candidateAdvisors.AddRange(advisors.Advisors);
}
}
return candidateAdvisors;
}
/// <summary>
/// Invoked by an <see cref="Spring.Objects.Factory.IObjectFactory"/>
/// after it has injected all of an object's dependencies.
/// </summary>
public void AfterPropertiesSet()
{
advisors = InstantiateCandidateAdvisors();
}
#region IObjectNameAware Members
/// <summary>
/// Set the name of the object in the object factory that created this object.
/// </summary>
/// <value>The name of the object in the factory.</value>
/// <remarks>
/// <p>
/// Invoked after population of normal object properties but before an init
/// callback like <see cref="T:Spring.Objects.Factory.IInitializingObject"/>'s
/// <see cref="M:Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
/// method or a custom init-method.
/// </p>
/// </remarks>
public string ObjectName
{
set
{
// If no infrastructure object name prefix has been set, override it.
if (advisorObjectNamePrefix == null)
{
advisorObjectNamePrefix = value + SEPARATOR;
}
}
}
#endregion
}
}

View File

@@ -71,11 +71,11 @@ namespace Spring.Aop.Framework.AutoProxy
/// <summary>
/// Identify as object to proxy if the object name is in the configured list of names.
/// </summary>
protected override bool IsEligibleForProxying( Type objType, string name )
protected override bool IsEligibleForProxying( Type targetType, string targetName )
{
AssertUtils.ArgumentNotNull(this.ObjectNames, "ObjectNames");
bool shallProxy = PatternMatchUtils.IsObjectNameMatch(objType, name, this.ObjectNames, new PatternMatchUtils.ObjectNameMatchPredicate(IsMatch), ObjectFactoryUtils.FactoryObjectPrefix);
bool shallProxy = PatternMatchUtils.IsObjectNameMatch(targetType, targetName, this.ObjectNames, new PatternMatchUtils.ObjectNameMatchPredicate(IsMatch), ObjectFactoryUtils.FactoryObjectPrefix);
return shallProxy;
}

View File

@@ -49,11 +49,11 @@ namespace Spring.Aop.Framework.AutoProxy
/// <summary>
/// Determines, whether the given object shall be proxied.
/// </summary>
protected override bool IsEligibleForProxying( Type objType, string name )
protected override bool IsEligibleForProxying( Type targetType, string targetName )
{
AssertUtils.ArgumentNotNull(_pointcut, "Pointcut");
bool shallProxy = AopUtils.CanApply( _pointcut, objType, null );
bool shallProxy = AopUtils.CanApply( _pointcut, targetType, null );
return shallProxy;
}
}

View File

@@ -55,15 +55,15 @@ namespace Spring.Aop.Framework.AutoProxy
/// <remarks>
/// Override this method to allow or reject proxying for the given object.
/// </remarks>
/// <param name="objType">the object's type</param>
/// <param name="name">the name of the object</param>
/// <param name="targetType">the object's type</param>
/// <param name="targetName">the name of the object</param>
/// <seealso cref="AbstractAutoProxyCreator.ShouldSkip"/>
/// <returns>whether the given object shall be proxied.</returns>
protected override bool IsEligibleForProxying(Type objType, string name)
protected override bool IsEligibleForProxying(Type targetType, string targetName)
{
AssertUtils.ArgumentNotNull(_typeNameFilter, "TypeNames");
bool shallProxy = _typeNameFilter.Matches(objType);
bool shallProxy = _typeNameFilter.Matches(targetType);
return shallProxy;
}
}

View File

@@ -138,7 +138,9 @@
<Compile Include="Aop\Framework\AopUtils.cs" />
<Compile Include="Aop\Framework\AutoProxy\AbstractFilteringAutoProxyCreator.cs" />
<Compile Include="Aop\Framework\AutoProxy\AttributeAutoProxyCreator.cs" />
<Compile Include="Aop\Framework\AutoProxy\InfrastructureAdvisorAutoProxyCreator.cs" />
<Compile Include="Aop\Framework\AutoProxy\InheritanceBasedAopConfigurer.cs" />
<Compile Include="Aop\Framework\AutoProxy\ObjectFactoryAdvisorRetrievalHelper.cs" />
<Compile Include="Aop\Framework\AutoProxy\PointcutFilteringAutoProxyCreator.cs" />
<Compile Include="Aop\Framework\AutoProxy\TypeNameAutoProxyCreator.cs" />
<Compile Include="Aop\Framework\DynamicMethodInvocation.cs" />

View File

@@ -120,6 +120,11 @@ namespace Spring.Objects.Factory.Config
/// </summary>
string Scope { get; set; }
/// <summary>
/// Get the role hint for this object definition
/// </summary>
ObjectRole Role { get; }
/// <summary>
/// Returns the <see cref="System.Type"/> of the object definition (if any).
/// </summary>

View File

@@ -49,7 +49,6 @@ namespace Spring.Objects.Factory.Support
private static readonly string SCOPE_SINGLETON = "singleton";
private static readonly string SCOPE_PROTOTYPE = "prototype";
#region Constructor (s) / Destructor
/// <summary>
@@ -126,6 +125,7 @@ namespace Spring.Objects.Factory.Support
IsAbstract = other.IsAbstract;
// IsSingleton = other.IsSingleton;
Scope = other.Scope;
Role = other.Role;
IsLazyInit = other.IsLazyInit;
ConstructorArgumentValues
= new ConstructorArgumentValues(other.ConstructorArgumentValues);
@@ -271,6 +271,15 @@ namespace Spring.Objects.Factory.Support
}
}
/// <summary>
/// Get or set the role hint for this object definition
/// </summary>
public virtual ObjectRole Role
{
get { return role; }
set { role = value; }
}
/// <summary>
/// Is this definition a <b>singleton</b>, with
/// a single, shared instance returned on all calls to an enclosing
@@ -797,6 +806,7 @@ namespace Spring.Objects.Factory.Support
private bool isLazyInit = false;
private bool isAbstract = false;
private string scope = SCOPE_SINGLETON;
private ObjectRole role = ObjectRole.ROLE_APPLICATION;
private object objectType;
private AutoWiringMode autowireMode = AutoWiringMode.No;
private DependencyCheckingMode dependencyCheck = DependencyCheckingMode.None;

View File

@@ -60,6 +60,11 @@ namespace Spring.Objects.Factory.Support
/// </summary>
new EventValues EventHandlerValues { get; set; }
/// <summary>
/// Get or set the role hint for this object definition
/// </summary>
new ObjectRole Role { get; set; }
/// <summary>
/// Return a description of the resource that this object definition
/// came from (for the purpose of showing context in case of errors).

View File

@@ -575,6 +575,7 @@
<Compile Include="Objects\Factory\Config\ISingletonObjectRegistry.cs" />
<Compile Include="Objects\Factory\Config\ObjectDefinitionHolder.cs" />
<Compile Include="Objects\Factory\Config\ObjectDefinitionVisitor.cs" />
<Compile Include="Objects\Factory\Config\ObjectRole.cs" />
<Compile Include="Objects\Factory\Config\ResourceHandlerConfigurer.cs" />
<Compile Include="Objects\Factory\Config\SharedStateAwareProcessor.cs" />
<Compile Include="Objects\Factory\Config\SmartInstantiationAwareObjectPostProcessor.cs" />

View File

@@ -1,5 +1,5 @@
#region License
#region License
/*
* Copyright 2002-2007 the original author or authors.
*
@@ -14,107 +14,106 @@
* 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;
using System.Xml;
using Spring.Aop.Config;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
using Spring.Objects.Factory.Xml;
using Spring.Transaction.Interceptor;
namespace Spring.Transaction.Config
{
/// <summary>
/// IObjectDefinitionParser implementation that allows users to easily configure all the
/// infrastructure objects required to enable attribute-driven transction demarcation.
/// </summary>
/// <author>Rob Harrop</author>
/// <author>Juergen Hoeller</author>
/// <author>Mark Pollack (.NET)</author>
public class AttributeDrivenObjectDefinitionParser : AbstractObjectDefinitionParser
{
/// <summary>
/// Object property name for injection the TransactionInterceptor
/// </summary>
private static readonly string TRANSACTION_INTERCEPTOR = "transactionInterceptor";
/// <summary>
/// The '<code>proxy-target-type</code>' attribute
/// </summary>
private static readonly string PROXY_TARGET_TYPE = "proxy-target-type";
/// <summary>
/// The '<code>order</code>' property/attribute
/// </summary>
private static readonly string ORDER = "order";
/// <summary>
/// Central template method to actually parse the supplied XmlElement
/// into one or more IObjectDefinitions.
/// </summary>
/// <param name="element">The element that is to be parsed into one or more <see cref="IObjectDefinition"/>s</param>
/// <param name="parserContext">The the object encapsulating the current state of the parsing process;
/// provides access to a <see cref="IObjectDefinitionRegistry"/></param>
/// <returns>
/// The primary IObjectDefinition resulting from the parsing of the supplied XmlElement
/// </returns>
protected override AbstractObjectDefinition ParseInternal(XmlElement element, ParserContext parserContext)
{
*/
#endregion
using System;
using System.Xml;
using Spring.Aop.Config;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
using Spring.Objects.Factory.Xml;
using Spring.Transaction.Interceptor;
namespace Spring.Transaction.Config
{
/// <summary>
/// IObjectDefinitionParser implementation that allows users to easily configure all the
/// infrastructure objects required to enable attribute-driven transction demarcation.
/// </summary>
/// <author>Rob Harrop</author>
/// <author>Juergen Hoeller</author>
/// <author>Mark Pollack (.NET)</author>
public class AttributeDrivenObjectDefinitionParser : AbstractObjectDefinitionParser
{
/// <summary>
/// Object property name for injection the TransactionInterceptor
/// </summary>
private static readonly string TRANSACTION_INTERCEPTOR = "transactionInterceptor";
/// <summary>
/// The '<code>proxy-target-type</code>' attribute
/// </summary>
private static readonly string PROXY_TARGET_TYPE = "proxy-target-type";
/// <summary>
/// The '<code>order</code>' property/attribute
/// </summary>
private static readonly string ORDER = "order";
/// <summary>
/// Central template method to actually parse the supplied XmlElement
/// into one or more IObjectDefinitions.
/// </summary>
/// <param name="element">The element that is to be parsed into one or more <see cref="IObjectDefinition"/>s</param>
/// <param name="parserContext">The the object encapsulating the current state of the parsing process;
/// provides access to a <see cref="IObjectDefinitionRegistry"/></param>
/// <returns>
/// The primary IObjectDefinition resulting from the parsing of the supplied XmlElement
/// </returns>
protected override AbstractObjectDefinition ParseInternal(XmlElement element, ParserContext parserContext)
{
ConfigureAutoProxyCreator(parserContext, element);
string transactionManagerName = GetAttributeValue(element, TxNamespaceUtils.TRANSACTION_MANAGER_ATTRIBUTE);
Type sourceType = typeof (AttributesTransactionAttributeSource);
//Create the TransactionInterceptor definition.
RootObjectDefinition interceptorDefinition = new RootObjectDefinition(typeof (TransactionInterceptor));
interceptorDefinition.PropertyValues.Add(TxNamespaceUtils.TRANSACTION_MANAGER_PROPERTY,
new RuntimeObjectReference(transactionManagerName));
interceptorDefinition.PropertyValues.Add(TxNamespaceUtils.TRANSACTION_ATTRIBUTE_SOURCE,
new RootObjectDefinition(sourceType));
//Create the TransactionAttributeSourceAdvisor definition.
RootObjectDefinition advisorDefinition = new RootObjectDefinition(typeof (TransactionAttributeSourceAdvisor));
advisorDefinition.PropertyValues.Add(TRANSACTION_INTERCEPTOR, interceptorDefinition);
if (element.HasAttribute(ORDER))
{
advisorDefinition.PropertyValues.Add(ORDER, GetAttributeValue(element, ORDER));
}
return advisorDefinition;
}
/// <summary>
/// Configures the auto proxy creator.
/// </summary>
/// <param name="parserContext">The parser context.</param>
/// <param name="element">The element.</param>
private static void ConfigureAutoProxyCreator(ParserContext parserContext, XmlElement element)
{
AopNamespaceUtils.RegisterAutoProxyCreatorIfNecessary(parserContext, element);
bool proxyTargetClass =
parserContext.ParserHelper.IsTrueStringValue(GetAttributeValue(element, PROXY_TARGET_TYPE));
if (proxyTargetClass)
{
AopNamespaceUtils.ForceAutoProxyCreatorToUseDecoratorProxy(parserContext.Registry);
}
}
/// <summary>
/// Gets a value indicating whether an ID should be generated instead of read
/// from the passed in XmlElement.
/// </summary>
/// <value><c>true</c> if should generate id; otherwise, <c>false</c>.</value>
/// <remarks>Note that this flag is about always generating an ID; the parser
/// won't even check for an "id" attribute in this case.
/// </remarks>
protected override bool ShouldGenerateId
{
get { return true; }
}
}
string transactionManagerName = GetAttributeValue(element, TxNamespaceUtils.TRANSACTION_MANAGER_ATTRIBUTE);
Type sourceType = typeof(AttributesTransactionAttributeSource);
//Create the TransactionInterceptor definition.
RootObjectDefinition interceptorDefinition = new RootObjectDefinition(typeof(TransactionInterceptor));
interceptorDefinition.PropertyValues.Add(TxNamespaceUtils.TRANSACTION_MANAGER_PROPERTY,
new RuntimeObjectReference(transactionManagerName));
interceptorDefinition.PropertyValues.Add(TxNamespaceUtils.TRANSACTION_ATTRIBUTE_SOURCE,
new RootObjectDefinition(sourceType));
//Create the TransactionAttributeSourceAdvisor definition.
RootObjectDefinition advisorDefinition = new RootObjectDefinition(typeof(TransactionAttributeSourceAdvisor));
advisorDefinition.PropertyValues.Add(TRANSACTION_INTERCEPTOR, interceptorDefinition);
if (element.HasAttribute(ORDER))
{
advisorDefinition.PropertyValues.Add(ORDER, GetAttributeValue(element, ORDER));
}
return advisorDefinition;
}
/// <summary>
/// Configures the auto proxy creator.
/// </summary>
/// <param name="parserContext">The parser context.</param>
/// <param name="element">The element.</param>
private static void ConfigureAutoProxyCreator(ParserContext parserContext, XmlElement element)
{
AopNamespaceUtils.RegisterAutoProxyCreatorIfNecessary(parserContext, element);
bool proxyTargetClass = parserContext.ParserHelper.IsTrueStringValue(GetAttributeValue(element, PROXY_TARGET_TYPE));
if (proxyTargetClass)
{
AopNamespaceUtils.ForceAutoProxyCreatorToUseDecoratorProxy(parserContext.Registry);
}
}
/// <summary>
/// Gets a value indicating whether an ID should be generated instead of read
/// from the passed in XmlElement.
/// </summary>
/// <value><c>true</c> if should generate id; otherwise, <c>false</c>.</value>
/// <remarks>Note that this flag is about always generating an ID; the parser
/// won't even check for an "id" attribute in this case.
/// </remarks>
protected override bool ShouldGenerateId
{
get { return true; }
}
}
}

View File

@@ -121,9 +121,9 @@ namespace Spring.Aop.Framework.AutoProxy
this.ObjectFactory = objectFactory;
}
protected override object[] GetAdvicesAndAdvisorsForObject(Type objType, string name, ITargetSource customTargetSource)
protected override object[] GetAdvicesAndAdvisorsForObject(Type targetType, string targetName, ITargetSource customTargetSource)
{
if (typeof(IFactoryObject).IsAssignableFrom(objType))
if (typeof(IFactoryObject).IsAssignableFrom(targetType))
{
return DO_NOT_PROXY;
}

View File

@@ -55,7 +55,7 @@ namespace Spring.Aop.Framework.AutoProxy
Assert.IsTrue(AopUtils.IsAopProxy(context.GetObject("independentObject")));
// products of the factory created at runtime should be proxied
Assert.IsTrue(AopUtils.IsAopProxy(context.GetObject("testObjectFactory")));
Assert.IsFalse(AopUtils.IsAopProxy(context.GetObject("testObjectFactory")));
}
}

View File

@@ -29,7 +29,8 @@ limitations under the License.
</factoryAdapter>
-->
<factoryAdapter type="Common.Logging.Simple.NoOpLoggerFactoryAdapter, Common.Logging">
<factoryAdapter type="Common.Logging.Simple.TraceLoggerFactoryAdapter, Common.Logging">
<arg key="level" value="ALL" />
</factoryAdapter>
</logging>

View File

@@ -83,6 +83,11 @@ namespace Spring.Objects.Factory
set { throw new System.NotImplementedException(); }
}
public ObjectRole Role
{
get { throw new NotImplementedException(); }
}
public Type ObjectType
{
get { throw new NotImplementedException(); }

View File

@@ -1,7 +1,7 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<ProjectType>Local</ProjectType>
<ProductVersion>9.0.21022</ProductVersion>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{ACD39D47-1811-40FA-9E7E-5DEA5B9CE6C0}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -166,6 +166,7 @@
<EmbeddedResource Include="Data\AutoDeclarativeTxTests.xml" />
<EmbeddedResource Include="Data\Common\AdditionalProviders.xml" />
<Content Include="Spring.Data.Tests.dll.config" />
<Content Include="Transaction\Config\TxNamespaceParserTests_TxAttributeDriven.xml" />
<EmbeddedResource Include="Transaction\Interceptor\MatchAlwaysTransactionAttributeSourceTests.xml" />
<EmbeddedResource Include="Transaction\Config\TxNamespaceParserTests.xml" />
</ItemGroup>