diff --git a/BreakingChanges-1.2.txt b/BreakingChanges-1.2.txt index 57511ae2..498d2970 100644 --- a/BreakingChanges-1.2.txt +++ b/BreakingChanges-1.2.txt @@ -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 (,,..), nested validator elements now must occur after any +1. within an ValidationGroup element (,,..), nested validator elements now must occur after any , or elements. The following was allowed previously, but now will raise a schema validation error: - + - + change this to - + @@ -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 ----------- diff --git a/src/Spring/Spring.Aop/Aop/Config/AopNamespaceUtils.cs b/src/Spring/Spring.Aop/Aop/Config/AopNamespaceUtils.cs index 0f839e44..6e332855 100644 --- a/src/Spring/Spring.Aop/Aop/Config/AopNamespaceUtils.cs +++ b/src/Spring/Spring.Aop/Aop/Config/AopNamespaceUtils.cs @@ -35,21 +35,18 @@ namespace Spring.Aop.Config { /// /// Utility class for handling registration of auto-proxy creators used internally by the - /// aop namespace tags. + /// aop and tx namespace tags. /// /// Rob Harrop /// Juergen Hoeller - /// Mark Pollack (.NET) + /// Mark Pollack (.NET) + /// Erich Eichinger (.NET) public class AopNamespaceUtils { - /// /// The object name of the internally managed auto-proxy creator. /// - 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"; /// /// Registers the auto proxy creator if necessary. diff --git a/src/Spring/Spring.Aop/Aop/Framework/AopUtils.cs b/src/Spring/Spring.Aop/Aop/Framework/AopUtils.cs index 7bb2d969..af92656d 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AopUtils.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AopUtils.cs @@ -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 /// /// if the pointcut can apply on any method. /// - 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); + } + /// + /// Can the supplied apply at all on the + /// supplied ? + /// + /// + ///

+ /// This is an important test as it can be used to optimize out a + /// pointcut for a class. + ///

+ ///

+ /// Invoking this method with a that is + /// an interface type will always yield a + /// return value. + ///

+ ///
+ /// The pointcut being tested. + /// The class being tested. + /// + /// The interfaces being proxied. If , all + /// methods on a class may be proxied. + /// + /// whether or not the advisor chain for the target object includes any introductions. + /// + /// if the pointcut can apply on any method. + /// + 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 /// /// if the advisor can apply on any method. /// - 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); + } + + /// + /// Can the supplied apply at all on the + /// supplied ? + /// + /// + ///

+ /// This is an important test as it can be used to optimize out an + /// advisor for a class. + ///

+ ///
+ /// The advisor to check. + /// The class being tested. + /// + /// The interfaces being proxied. If , all + /// methods on a class may be proxied. + /// + /// whether or not the advisor chain for the target object includes any introductions. + /// + /// if the advisor can apply on any method. + /// + 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; diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAdvisorAutoProxyCreator.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAdvisorAutoProxyCreator.cs index fbb67b99..1c5a115d 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAdvisorAutoProxyCreator.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAdvisorAutoProxyCreator.cs @@ -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 { /// - /// 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. /// @@ -50,9 +52,21 @@ namespace Spring.Aop.Framework.AutoProxy /// /// /// Rod Johnson - /// Adhari C Mahendra (.NET) + /// Adhari C Mahendra (.NET) + /// Erich Eichinger public abstract class AbstractAdvisorAutoProxyCreator : AbstractAutoProxyCreator { + private readonly ILog Log; + private ObjectFactoryAdvisorRetrievalHelper _advisorRetrievalHelper; + + /// + /// Initialize + /// + protected AbstractAdvisorAutoProxyCreator() + { + Log = LogManager.GetLogger(this.GetType()); + } + /// /// 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 /// 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; } + } + + /// + /// An new was set. Initialize this creator instance + /// according to the specified object factory. + /// + /// + protected virtual void InitObjectFactory(IConfigurableListableObjectFactory objectFactory) + { + _advisorRetrievalHelper = new ObjectFactoryAdvisorRetrievalHelperAdapter(this, objectFactory); } /// /// Return whether the given object is to be proxied, what additional /// advices (e.g. AOP Alliance interceptors) and advisors to apply. /// - /// the new object instance - /// the name of the object - /// targetSource returned by TargetSource property: - /// may be ignored. Will be null unless a custom target source is in use. - /// - /// 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. - /// /// - ///

The previous name of this method was "GetInterceptorAndAdvisorForObject". + ///

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.

///

The third parameter, customTargetSource, is new in Spring 1.1; /// add it to existing implementations of this method.

- ///
- protected override object[] GetAdvicesAndAdvisorsForObject(Type objType, string name, ITargetSource customTargetSource) + /// + /// the type of the target object + /// the name of the target object + /// targetSource returned by TargetSource property: + /// may be ignored. Will be null unless a custom target source is in use. + /// + /// 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. + /// + 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)); } /// /// Find all eligible advices and for autoproxying this class. /// - /// - /// the empty list, not null, if there are no pointcuts or interceptors - protected IList FindEligibleAdvisors(Type type) + /// the type of the object to be advised + /// the name of the object to be advised + /// + /// the empty list, not null, if there are no pointcuts or interceptors. + /// The by-order sorted list of advisors otherwise + /// + 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; + } + + /// + /// Find all possible advisor candidates to use in auto-proxying + /// + /// the type of the object to be advised + /// the name of the object to be advised + /// the list of candidate advisors + protected virtual IList FindCandidateAdvisors(Type targetType, string targetName) + { + return _advisorRetrievalHelper.FindAdvisorObjects(targetType, targetName); + } + + /// + /// From the given list of candidate advisors, select the ones that are applicable + /// to the given target specified by targetType and name. + /// + /// the list of candidate advisors to date + /// the target object's type + /// the target object's name + /// the list of applicable advisors + 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 ///
/// The advisors. /// - 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; } - /// - /// Find all candidate advisors to use in auto-proxying. - /// - /// list of Advisors - protected abstract IList FindCandidateAdvisors(); + /// + /// Extension hook that subclasses can override to register additional advisors, + /// given the sorted advisors obtained to date.
+ /// The default implementation does nothing.
+ /// Typically used to add advisors that expose contextual information required by some of the later advisors. + ///
+ /// Advisors that have already been identified as applying to a given object + /// the type of the object to be advised + /// the name of the object to be advised + protected virtual void ExtendAdvisors(IList advisors, Type objectType, string objectName) + {} + + /// + /// Whether the given advisor is eligible for the specified target. The default implementation + /// always returns true. + /// + /// the advisor name + /// the target object's type + /// the target object's name + 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); + } + } } } \ No newline at end of file diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAutoProxyCreator.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAutoProxyCreator.cs index 8fe22aee..a4f8d814 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAutoProxyCreator.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractAutoProxyCreator.cs @@ -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. /// - /// the type of the object - /// the name of the object + /// the type of the object + /// the name of the object /// if remarkable to skip - 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. /// /// - ///

The previous name of this method was "GetInterceptorAndAdvisorForObject". + ///

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.

///

The third parameter, customTargetSource, is new in Spring 1.1; /// add it to existing implementations of this method.

///
- /// the new object instance - /// the name of the object + /// the new object instance + /// the name of the object /// targetSource returned by TargetSource property: /// may be ignored. Will be null unless a custom target source is in use. /// 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. - protected abstract object[] GetAdvicesAndAdvisorsForObject(Type objType, string name, ITargetSource customTargetSource); + protected abstract object[] GetAdvicesAndAdvisorsForObject(Type targetType, string targetName, ITargetSource customTargetSource); /// /// Create an AOP proxy for the given object. /// - /// Type of the object. - /// The name of the object. + /// Type of the object. + /// The name of the object. /// The set of interceptors that is specific to this /// object (may be empty but not null) /// The target source for the proxy, already pre-configured to access the object. /// The AOP Proxy for the object. - 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. /// - /// The name of the object. + /// The name of the object. /// The set of interceptors that is specific to this /// object (may be empty, but not null) /// The list of Advisors for the given object - 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)); } diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractFilteringAutoProxyCreator.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractFilteringAutoProxyCreator.cs index 5462b463..47cc1e1f 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractFilteringAutoProxyCreator.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AbstractFilteringAutoProxyCreator.cs @@ -39,12 +39,12 @@ namespace Spring.Aop.Framework.AutoProxy /// ///Overridden to call . /// - /// the type of the object - /// the name of the object + /// the type of the object + /// the name of the object /// if remarkable to skip - 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 /// /// Whether an object shall be proxied or not is determined by the result of . /// - /// ingored - /// ignored + /// ingored + /// ignored /// ignored /// /// Always to indicate, that the object shall be proxied. /// /// - 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 /// /// Override this method to allow or reject proxying for the given object. /// - /// the object's type - /// the name of the object + /// the object's type + /// the name of the object /// /// whether the given object shall be proxied. - protected abstract bool IsEligibleForProxying( Type objType, string name ); + protected abstract bool IsEligibleForProxying( Type targetType, string targetName ); } } \ No newline at end of file diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AttributeAutoProxyCreator.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AttributeAutoProxyCreator.cs index 66d6de06..c4cb5526 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AttributeAutoProxyCreator.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/AttributeAutoProxyCreator.cs @@ -61,15 +61,15 @@ namespace Spring.Aop.Framework.AutoProxy } /// - /// Determines, whether the given object shall be proxied by matching against . + /// Determines, whether the given object shall be proxied by matching against . /// - /// the object's type - /// the name of the object - protected override bool IsEligibleForProxying( Type objType, string name ) + /// the object's type + /// the name of the object + 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; } diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/DefaultAdvisorAutoProxyCreator.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/DefaultAdvisorAutoProxyCreator.cs index 960a6d1d..df790b0f 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/DefaultAdvisorAutoProxyCreator.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/DefaultAdvisorAutoProxyCreator.cs @@ -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 /// /// Rod Johnson /// Adhari C Mahendra (.NET) - public class DefaultAdvisorAutoProxyCreator : AbstractAdvisorAutoProxyCreator, IObjectNameAware, IInitializingObject + /// Erich Eichinger (.NET) + public class DefaultAdvisorAutoProxyCreator : AbstractAdvisorAutoProxyCreator, IObjectNameAware { - /// /// Separator between prefix and remainder of object name /// 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 + + /// + /// Set the name of the object in the object factory that created this object. + /// + /// The name of the object in the factory. + /// + ///

+ /// Invoked after population of normal object properties but before an init + /// callback like 's + /// + /// method or a custom init-method. + ///

+ ///
+ public string ObjectName + { + set + { + // If no infrastructure object name prefix has been set, override it. + if (advisorObjectNamePrefix == null) + { + advisorObjectNamePrefix = value + SEPARATOR; + } + } + } + #endregion - /// - /// Find all candidate advices to use in auto proxying. - /// - /// list of Advice - 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; + + /// + /// Whether the given advisor is eligible for the specified target. + /// + /// the advisor name + /// the target object's type + /// the target object's name + 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; - } - - - - /// - /// Invoked by an - /// after it has injected all of an object's dependencies. - /// - public void AfterPropertiesSet() - { - advisors = InstantiateCandidateAdvisors(); - } - - #region IObjectNameAware Members - - /// - /// Set the name of the object in the object factory that created this object. - /// - /// The name of the object in the factory. - /// - ///

- /// Invoked after population of normal object properties but before an init - /// callback like 's - /// - /// method or a custom init-method. - ///

- ///
- public string ObjectName - { - set - { - // If no infrastructure object name prefix has been set, override it. - if (advisorObjectNamePrefix == null) - { - advisorObjectNamePrefix = value + SEPARATOR; - } - } - } - - #endregion } } \ No newline at end of file diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/ObjectNameAutoProxyCreator.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/ObjectNameAutoProxyCreator.cs index 137ad39a..f931d031 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/ObjectNameAutoProxyCreator.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/ObjectNameAutoProxyCreator.cs @@ -71,11 +71,11 @@ namespace Spring.Aop.Framework.AutoProxy /// /// Identify as object to proxy if the object name is in the configured list of names. /// - 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; } diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/PointcutFilteringAutoProxyCreator.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/PointcutFilteringAutoProxyCreator.cs index 46add6c8..977c1084 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/PointcutFilteringAutoProxyCreator.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/PointcutFilteringAutoProxyCreator.cs @@ -49,11 +49,11 @@ namespace Spring.Aop.Framework.AutoProxy /// /// Determines, whether the given object shall be proxied. /// - 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; } } diff --git a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/TypeNameAutoProxyCreator.cs b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/TypeNameAutoProxyCreator.cs index 777c03a4..9e768e0e 100644 --- a/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/TypeNameAutoProxyCreator.cs +++ b/src/Spring/Spring.Aop/Aop/Framework/AutoProxy/TypeNameAutoProxyCreator.cs @@ -55,15 +55,15 @@ namespace Spring.Aop.Framework.AutoProxy /// /// Override this method to allow or reject proxying for the given object. /// - /// the object's type - /// the name of the object + /// the object's type + /// the name of the object /// /// whether the given object shall be proxied. - 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; } } diff --git a/src/Spring/Spring.Aop/Spring.Aop.2008.csproj b/src/Spring/Spring.Aop/Spring.Aop.2008.csproj index 13bd5343..76bda49d 100644 --- a/src/Spring/Spring.Aop/Spring.Aop.2008.csproj +++ b/src/Spring/Spring.Aop/Spring.Aop.2008.csproj @@ -138,7 +138,9 @@ + + diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/IObjectDefinition.cs b/src/Spring/Spring.Core/Objects/Factory/Config/IObjectDefinition.cs index 5e629e95..c486a046 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Config/IObjectDefinition.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Config/IObjectDefinition.cs @@ -120,6 +120,11 @@ namespace Spring.Objects.Factory.Config /// string Scope { get; set; } + /// + /// Get the role hint for this object definition + /// + ObjectRole Role { get; } + /// /// Returns the of the object definition (if any). /// diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectDefinition.cs b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectDefinition.cs index 8cad90e7..309d92ae 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectDefinition.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectDefinition.cs @@ -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 /// @@ -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 } } + /// + /// Get or set the role hint for this object definition + /// + public virtual ObjectRole Role + { + get { return role; } + set { role = value; } + } + /// /// Is this definition a singleton, 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; diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/IConfigurableObjectDefinition.cs b/src/Spring/Spring.Core/Objects/Factory/Support/IConfigurableObjectDefinition.cs index e49becb1..0c9a6828 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/IConfigurableObjectDefinition.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/IConfigurableObjectDefinition.cs @@ -60,6 +60,11 @@ namespace Spring.Objects.Factory.Support /// new EventValues EventHandlerValues { get; set; } + /// + /// Get or set the role hint for this object definition + /// + new ObjectRole Role { get; set; } + /// /// Return a description of the resource that this object definition /// came from (for the purpose of showing context in case of errors). diff --git a/src/Spring/Spring.Core/Spring.Core.2008.csproj b/src/Spring/Spring.Core/Spring.Core.2008.csproj index 0ae27fdb..c4f2062f 100644 --- a/src/Spring/Spring.Core/Spring.Core.2008.csproj +++ b/src/Spring/Spring.Core/Spring.Core.2008.csproj @@ -575,6 +575,7 @@ + diff --git a/src/Spring/Spring.Data/Transaction/Config/AttributeDrivenObjectDefinitionParser.cs b/src/Spring/Spring.Data/Transaction/Config/AttributeDrivenObjectDefinitionParser.cs index 43184152..cfc38e58 100644 --- a/src/Spring/Spring.Data/Transaction/Config/AttributeDrivenObjectDefinitionParser.cs +++ b/src/Spring/Spring.Data/Transaction/Config/AttributeDrivenObjectDefinitionParser.cs @@ -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 -{ - /// - /// IObjectDefinitionParser implementation that allows users to easily configure all the - /// infrastructure objects required to enable attribute-driven transction demarcation. - /// - /// Rob Harrop - /// Juergen Hoeller - /// Mark Pollack (.NET) - public class AttributeDrivenObjectDefinitionParser : AbstractObjectDefinitionParser - { - /// - /// Object property name for injection the TransactionInterceptor - /// - private static readonly string TRANSACTION_INTERCEPTOR = "transactionInterceptor"; - - /// - /// The 'proxy-target-type' attribute - /// - private static readonly string PROXY_TARGET_TYPE = "proxy-target-type"; - - /// - /// The 'order' property/attribute - /// - private static readonly string ORDER = "order"; - - /// - /// Central template method to actually parse the supplied XmlElement - /// into one or more IObjectDefinitions. - /// - /// The element that is to be parsed into one or more s - /// The the object encapsulating the current state of the parsing process; - /// provides access to a - /// - /// The primary IObjectDefinition resulting from the parsing of the supplied XmlElement - /// - 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 +{ + /// + /// IObjectDefinitionParser implementation that allows users to easily configure all the + /// infrastructure objects required to enable attribute-driven transction demarcation. + /// + /// Rob Harrop + /// Juergen Hoeller + /// Mark Pollack (.NET) + public class AttributeDrivenObjectDefinitionParser : AbstractObjectDefinitionParser + { + /// + /// Object property name for injection the TransactionInterceptor + /// + private static readonly string TRANSACTION_INTERCEPTOR = "transactionInterceptor"; + + /// + /// The 'proxy-target-type' attribute + /// + private static readonly string PROXY_TARGET_TYPE = "proxy-target-type"; + + /// + /// The 'order' property/attribute + /// + private static readonly string ORDER = "order"; + + /// + /// Central template method to actually parse the supplied XmlElement + /// into one or more IObjectDefinitions. + /// + /// The element that is to be parsed into one or more s + /// The the object encapsulating the current state of the parsing process; + /// provides access to a + /// + /// The primary IObjectDefinition resulting from the parsing of the supplied XmlElement + /// + 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; - } - - /// - /// Configures the auto proxy creator. - /// - /// The parser context. - /// The element. - 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); - } - } - - /// - /// Gets a value indicating whether an ID should be generated instead of read - /// from the passed in XmlElement. - /// - /// true if should generate id; otherwise, false. - /// Note that this flag is about always generating an ID; the parser - /// won't even check for an "id" attribute in this case. - /// - 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; + } + + /// + /// Configures the auto proxy creator. + /// + /// The parser context. + /// The element. + 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); + } + } + + /// + /// Gets a value indicating whether an ID should be generated instead of read + /// from the passed in XmlElement. + /// + /// true if should generate id; otherwise, false. + /// Note that this flag is about always generating an ID; the parser + /// won't even check for an "id" attribute in this case. + /// + protected override bool ShouldGenerateId + { + get { return true; } + } + } } \ No newline at end of file diff --git a/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/AbstractAutoProxyCreatorTests.cs b/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/AbstractAutoProxyCreatorTests.cs index d23c52c9..00f7824d 100644 --- a/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/AbstractAutoProxyCreatorTests.cs +++ b/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/AbstractAutoProxyCreatorTests.cs @@ -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; } diff --git a/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/AdvisorAutoProxyCreatorCircularReferencesTests.cs b/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/AdvisorAutoProxyCreatorCircularReferencesTests.cs index da9faa86..b473843d 100644 --- a/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/AdvisorAutoProxyCreatorCircularReferencesTests.cs +++ b/test/Spring/Spring.Aop.Tests/Aop/Framework/AutoProxy/AdvisorAutoProxyCreatorCircularReferencesTests.cs @@ -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"))); } } diff --git a/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.dll.config b/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.dll.config index 62a67b4a..572f0ef2 100644 --- a/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.dll.config +++ b/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.dll.config @@ -29,7 +29,8 @@ limitations under the License. --> - + + diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/UnsupportedObjectDefinitionImplementation.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/UnsupportedObjectDefinitionImplementation.cs index e3b8c2f7..97864de8 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/UnsupportedObjectDefinitionImplementation.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/UnsupportedObjectDefinitionImplementation.cs @@ -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(); } diff --git a/test/Spring/Spring.Data.Tests/Spring.Data.Tests.2008.csproj b/test/Spring/Spring.Data.Tests/Spring.Data.Tests.2008.csproj index d216efb9..c329294c 100644 --- a/test/Spring/Spring.Data.Tests/Spring.Data.Tests.2008.csproj +++ b/test/Spring/Spring.Data.Tests/Spring.Data.Tests.2008.csproj @@ -1,7 +1,7 @@  Local - 9.0.21022 + 9.0.30729 2.0 {ACD39D47-1811-40FA-9E7E-5DEA5B9CE6C0} Debug @@ -166,6 +166,7 @@ +