synced AdvisedSupport with Spring/J

This commit is contained in:
eeichinger
2009-07-24 16:34:14 +00:00
parent bf2fc3df7b
commit 0bc02e8db1
23 changed files with 1716 additions and 1308 deletions

View File

@@ -39,7 +39,8 @@ namespace Spring.Aop.Framework.Adapter
/// interface.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public class DefaultAdvisorAdapterRegistry : IAdvisorAdapterRegistry
{
private readonly IList adapters = new ArrayList();

View File

@@ -27,7 +27,8 @@ namespace Spring.Aop.Framework.Adapter
/// <see cref="IAdvisorAdapterRegistry"/> instance.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public sealed class GlobalAdvisorAdapterRegistry : DefaultAdvisorAdapterRegistry
{
private static readonly GlobalAdvisorAdapterRegistry instance

View File

@@ -1,7 +1,7 @@
#region License
/*
* Copyright <20> 2002-2005 the original author or authors.
* Copyright <20> 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,14 +18,11 @@
#endregion
#region Imports
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Reflection;
using System.Text;
using AopAlliance.Aop;
using AopAlliance.Intercept;
using Spring.Aop;
@@ -34,8 +31,6 @@ using Spring.Aop.Target;
using Spring.Util;
using Spring.Proxy;
#endregion
namespace Spring.Aop.Framework
{
/// <summary>
@@ -81,14 +76,7 @@ namespace Spring.Aop.Framework
/// <summary>
/// List of introductions.
/// </summary>
private IList _introductions = new ArrayList();
/// <summary>
/// Array updated on changes to the advisors list, which is easier to
/// manipulate internally
/// </summary>
private IIntroductionAdvisor[] _introductionsArray
= new IIntroductionAdvisor[] { };
private ArrayList _introductions = new ArrayList();
/// <summary>
/// Interface map specifying which object should interface methods be
@@ -114,8 +102,8 @@ namespace Spring.Aop.Framework
/// </summary>
private bool isActive;
private Type proxyType;
private ConstructorInfo proxyConstructor;
private Type cachedProxyType;
private ConstructorInfo cachedProxyConstructor;
/// <summary>
/// The list of <see cref="Spring.Aop.Framework.AdvisedSupport"/> event listeners.
@@ -124,8 +112,14 @@ namespace Spring.Aop.Framework
/// <summary>
/// The advisor chain factory.
/// </summary>
private IAdvisorChainFactory advisorChainFactory;
/// </summary>
private IAdvisorChainFactory advisorChainFactory;
/// <summary>
/// If no explicit interfaces are specified, interfaces will be automatically determined
/// from the target type
/// </summary>
private bool autoDetectInterfaces;
#endregion
@@ -137,8 +131,10 @@ namespace Spring.Aop.Framework
/// default advisor chain factory.
/// </summary>
public AdvisedSupport()
{
AdvisorChainFactory = new HashtableCachingAdvisorChainFactory();
{
this.advisorChainFactory = new HashtableCachingAdvisorChainFactory();
this.AddListener(this.advisorChainFactory);
this.autoDetectInterfaces = true;
}
/// <summary>
@@ -159,8 +155,38 @@ namespace Spring.Aop.Framework
AddInterfaceInternal(intf);
}
}
}
}
/// <summary>
/// Creates a new instance of the <see cref="Spring.Aop.Framework.ProxyFactory"/>
/// class that proxys all of the interfaces exposed by the supplied
/// <paramref name="target"/>.
/// </summary>
/// <param name="target">The object to proxy.</param>
/// <exception cref="AopConfigException">
/// If the <paramref name="target"/> is <cref lang="null"/>.
/// </exception>
public AdvisedSupport(object target)
: this(GetInterfaces(target))
{
Target = target;
}
/// <summary>
/// Creates a new instance of the <see cref="Spring.Aop.Framework.ProxyFactory"/>
/// class that proxys all of the interfaces exposed by the supplied
/// <paramref name="targetSource"/>'s target.
/// </summary>
/// <param name="targetSource">The <see cref="ITargetSource"/> providing access to the object to proxy.</param>
/// <exception cref="AopConfigException">
/// If the <paramref name="targetSource"/> is <cref lang="null"/>.
/// </exception>
public AdvisedSupport(ITargetSource targetSource)
: this(GetInterfaces(targetSource != null ? targetSource.TargetType : null))
{
TargetSource = targetSource;
}
#endregion
#region IAdvised implementation
@@ -188,9 +214,10 @@ namespace Spring.Aop.Framework
}
}
set
{
{
AssertUtils.ArgumentNotNull(value, "AdvisorChainFactory");
lock (this.SyncRoot)
{
{
if (this.advisorChainFactory != null)
{
RemoveListener(this.advisorChainFactory);
@@ -215,17 +242,19 @@ namespace Spring.Aop.Framework
get { return this.m_targetSource; }
set
{
bool initialized = !(this.m_targetSource is EmptyTargetSource);
this.m_targetSource = value;
if (this.m_targetSource != null && !initialized && interfaceMap.Count == 0)
{
Type[] interfaces = ReflectionUtils.GetInterfaces(this.m_targetSource.TargetType);
foreach (Type intf in interfaces)
{
AddInterfaceInternal(intf);
}
}
m_targetSource= (value != null) ? value : EmptyTargetSource.Empty;
// TODO (EE):remove
// bool initialized = !(this.m_targetSource is EmptyTargetSource);
// this.m_targetSource = value;
//
// if (this.m_targetSource != null && !initialized && interfaceMap.Count == 0)
// {
// Type[] interfaces = ReflectionUtils.GetInterfaces(this.m_targetSource.TargetType);
// foreach (Type intf in interfaces)
// {
// AddInterfaceInternal(intf);
// }
// }
}
}
@@ -246,7 +275,6 @@ namespace Spring.Aop.Framework
lock (this.SyncRoot)
{
IAdvisor[] advisorsArray = this._advisorsArray;
IIntroductionAdvisor[] introductionsArray = this._introductionsArray;
for (int i = 0; i < advisorsArray.Length; i++)
{
@@ -256,9 +284,9 @@ namespace Spring.Aop.Framework
if (!canBeSerialized) return false;
}
for (int i = 0; i < introductionsArray.Length; i++)
for (int i = 0; i < this._introductions.Count; i++)
{
IIntroductionAdvisor advisor = introductionsArray[i];
IIntroductionAdvisor advisor = (IIntroductionAdvisor) this._introductions[i];
canBeSerialized = advisor.GetType().IsSerializable
&& advisor.Advice.GetType().IsSerializable;
if (!canBeSerialized) return false;
@@ -293,14 +321,26 @@ namespace Spring.Aop.Framework
{
lock (this.SyncRoot)
{
this.interfaceMap.Clear();
for (int i = 0; i < value.Length; i++)
{
AddInterfaceInternal(value[i]);
}
InterfacesChanged();
DieIfFrozen("Cannot change interface list if frozen");
SetInterfacesInternal(value);
}
}
}
/// <summary>
/// Set interfaces to be proxied, bypassing locking and <see cref="ProxyConfig.IsFrozen"/>
/// </summary>
protected void SetInterfacesInternal(Type[] value)
{
this.interfaceMap.Clear();
if (value != null)
{
for (int i = 0; i < value.Length; i++)
{
AddInterfaceInternal(value[i]);
}
}
InterfacesChanged();
}
/// <summary>
@@ -368,9 +408,7 @@ namespace Spring.Aop.Framework
{
get
{
// lock(this.SyncRoot)
{
// return (IAdvisor[]) _advisorsArray.Clone();
return _advisorsArray;
}
}
@@ -399,7 +437,7 @@ namespace Spring.Aop.Framework
{
lock (this.SyncRoot)
{
return (IIntroductionAdvisor[])this._introductionsArray.Clone();
return (IIntroductionAdvisor[])this._introductions.ToArray(typeof(IIntroductionAdvisor));
}
}
}
@@ -585,12 +623,9 @@ namespace Spring.Aop.Framework
if (index == -1)
{
return false;
}
else
{
RemoveAdvisorInternal(index);
return true;
}
}
RemoveAdvisorInternal(index);
return true;
}
}
@@ -664,38 +699,9 @@ namespace Spring.Aop.Framework
RemoveInterface(intf);
}
this._introductions.RemoveAt(index);
UpdateIntroductionsArray();
}
}
//
// /// <summary>
// /// Removes the supplied <paramref name="interceptor"/> from the list of
// /// <see cref="Spring.Aop.Framework.AdvisedSupport.Advisors"/> for this
// /// proxy.
// /// </summary>
// /// <param name="interceptor">
// /// The <see cref="AopAlliance.Intercept.IInterceptor"/> to be removed.
// /// </param>
// /// <exception cref="AopConfigException">
// /// If this proxy configuration is frozen and the
// /// <paramref name="interceptor"/> cannot be added.
// /// </exception>
// public bool RemoveInterceptor(IInterceptor interceptor)
// {
// AssertFrozen("Cannot remove interceptor: config is frozen");
// int index = IndexOf(interceptor);
// if (index == -1)
// {
// return false;
// }
// else
// {
// RemoveAdvisor(index);
// return true;
// }
// }
/// <summary>
/// Adds the supplied <paramref name="advisor"/> to the list
/// of <see cref="Spring.Aop.Framework.AdvisedSupport.Advisors"/>.
@@ -729,7 +735,7 @@ namespace Spring.Aop.Framework
this._advisors.Insert(index, advisor);
}
UpdateAdvisorsArray();
InterceptorsChanged();
AdviceChanged();
}
}
@@ -810,7 +816,6 @@ namespace Spring.Aop.Framework
{
this.interfaceMap[intf] = introductionAdvisor;
}
UpdateIntroductionsArray();
if (this.interfaceMap.Count != intfCount)
{
InterfacesChanged();
@@ -924,16 +929,36 @@ namespace Spring.Aop.Framework
/// As <see cref="System.Object.ToString()"/> will normally be passed straight through
/// to the advised target, this method returns the <see cref="System.Object.ToString()"/>
/// equivalent for the AOP proxy itself.
/// </summary>
/// </summary>
/// <remarks>To override this format, override <see cref="ToProxyConfigStringInternal"/></remarks>
/// <returns>
/// A <see cref="System.String"/> description of the proxy configuration.
/// </returns>
public virtual string ToProxyConfigString()
public string ToProxyConfigString()
{
lock (this.SyncRoot)
{
return ToStringInternal();
{
return ToProxyConfigStringInternal();
}
}
/// <summary>
/// Returns textual information about this configuration object
/// </summary>
/// <returns></returns>
protected virtual string ToProxyConfigStringInternal()
{
StringBuilder buffer = new StringBuilder(this.GetType().FullName + ":\n");
buffer.Append(this.interfaceMap.Count + " interfaces=[");
this.InterfacesToString(buffer);
buffer.Append("];\n");
buffer.Append(this._advisors.Count + " pointcuts=[");
this.AdvisorsToString(buffer);
buffer.Append("];\n");
buffer.Append("targetSource=[" + this.m_targetSource + "];\n");
buffer.Append("advisorChainFactory=" + this.advisorChainFactory + ";\n");
buffer.Append(base.ToString());
return buffer.ToString();
}
#endregion
@@ -952,7 +977,18 @@ namespace Spring.Aop.Framework
#endregion
#region Properties
#region Properties
/// <summary>
/// If no explicit interfaces are specified, interfaces will be automatically determined
/// from the target type on proxy creation. Defaults to true
/// </summary>
public bool AutoDetectInterfaces
{
get { return autoDetectInterfaces; }
set { autoDetectInterfaces = value; }
}
/// <summary>
/// Sets the target object that is to be advised.
/// </summary>
@@ -1003,8 +1039,8 @@ namespace Spring.Aop.Framework
/// </value>
internal Type ProxyType
{
get { return this.proxyType; }
set { this.proxyType = value; }
get { return this.cachedProxyType; }
set { this.cachedProxyType = value; }
}
/// <summary>
@@ -1012,8 +1048,8 @@ namespace Spring.Aop.Framework
/// </summary>
internal ConstructorInfo ProxyConstructor
{
get { return this.proxyConstructor; }
set { this.proxyConstructor = value; }
get { return this.cachedProxyConstructor; }
set { this.cachedProxyConstructor = value; }
}
/// <summary>
@@ -1249,7 +1285,7 @@ namespace Spring.Aop.Framework
}
this._advisors.RemoveAt(index);
this.UpdateAdvisorsArray();
this.InterceptorsChanged();
this.AdviceChanged();
}
/// <summary>
@@ -1328,16 +1364,8 @@ namespace Spring.Aop.Framework
this._advisorsArray = advisorsArray;
}
/// <summary>
/// Bring the introductions array up to date with the list.
/// </summary>
private void UpdateIntroductionsArray()
{
IIntroductionAdvisor[] introductionsArray = new IIntroductionAdvisor[this._introductions.Count];
this._introductions.CopyTo(introductionsArray, 0);
this._introductionsArray = introductionsArray;
}
#region IAdvisedSupportListener support
/// <summary>
/// Callback method that is invoked when the list of proxied interfaces
/// has changed.
@@ -1351,9 +1379,10 @@ namespace Spring.Aop.Framework
/// to be generated on the next call to get a proxy.
/// </p>
/// </remarks>
private void InterfacesChanged()
protected virtual void InterfacesChanged()
{
ProxyType = null;
this.cachedProxyType = null;
this.cachedProxyConstructor = null;
if (this.isActive)
{
foreach (IAdvisedSupportListener listener in this.listeners)
@@ -1366,7 +1395,7 @@ namespace Spring.Aop.Framework
/// <summary>
/// Callback method that is invoked when the interceptor list has changed.
/// </summary>
private void InterceptorsChanged()
protected virtual void AdviceChanged()
{
if (this.isActive)
{
@@ -1389,9 +1418,11 @@ namespace Spring.Aop.Framework
{
listener.Activated(this);
}
}
}
}
}
#endregion
/// <summary>
/// Creates an AOP proxy using this instance's configuration data.
/// </summary>
@@ -1407,7 +1438,33 @@ namespace Spring.Aop.Framework
protected internal virtual IAopProxy CreateAopProxy()
{
lock (this.SyncRoot)
{
{
if (this.autoDetectInterfaces && CountNonIntroductionInterfaces() == 0
// && !this.ProxyTargetType
)
{
this.interfaceMap.Clear();
// add all target interfaces
Type[] targetInterfaces = ReflectionUtils.GetInterfaces(this.TargetType);
foreach(Type targetInterface in targetInterfaces )
{
this.interfaceMap[targetInterface] = null;
}
// add introduced interfaces
foreach(IIntroductionAdvisor introduction in this._introductions)
{
foreach(Type introducedInterface in introduction.Interfaces)
{
this.interfaceMap[introducedInterface] = introduction;
}
}
if (targetInterfaces.Length > 0)
{
InterfacesChanged();
}
}
if (!this.isActive)
{
Activate();
@@ -1416,6 +1473,22 @@ namespace Spring.Aop.Framework
}
}
/// <summary>
/// Calculates the number of <see cref="Interfaces"/> not delegating to one of the <see cref="Introductions"/>.
/// </summary>
private int CountNonIntroductionInterfaces()
{
int c = 0;
foreach(Type interfaceType in this.interfaceMap.Keys)
{
if (this.interfaceMap[interfaceType] == null)
{
c++;
}
}
return c;
}
/// <summary>
/// Copies the configuration from the supplied other
/// <see cref="Spring.Aop.Framework.AdvisedSupport"/> into this instance.
@@ -1434,26 +1507,58 @@ namespace Spring.Aop.Framework
/// instance.
/// </param>
protected internal virtual void CopyConfigurationFrom(AdvisedSupport other)
{
CopyConfigurationFrom(other, other.TargetSource, new ArrayList(other.Advisors), new ArrayList(other.Introductions));
}
/// <summary>
/// Copies the configuration from the supplied other
/// <see cref="Spring.Aop.Framework.AdvisedSupport"/> into this instance.
/// </summary>
/// <remarks>
/// <p>
/// Useful when this instance has been created using the no-argument
/// constructor, and needs to get all of its confiuration data from
/// another <see cref="Spring.Aop.Framework.AdvisedSupport"/> (most
/// usually to have an independant copy of said configuration data).
/// </p>
/// </remarks>
/// <param name="other">
/// The <see cref="Spring.Aop.Framework.AdvisedSupport"/> instance
/// containing the configiration data that is to be copied into this
/// instance.
/// </param>
/// <param name="targetSource">the new target source</param>
/// <param name="advisors">the advisors for the chain</param>
/// <param name="introductions">the introductions for the chain</param>
protected internal virtual void CopyConfigurationFrom(AdvisedSupport other, ITargetSource targetSource, IList advisors, IList introductions)
{
CopyFrom(other);
this.m_targetSource = other.m_targetSource;
this.proxyType = other.proxyType;
this.proxyConstructor = other.proxyConstructor;
foreach (Type intf in other.interfaceMap.Keys)
{
this.interfaceMap[intf] = other.interfaceMap[intf];
}
this.AdvisorChainFactory = other.advisorChainFactory;
this.m_targetSource = targetSource;
// this.cachedProxyType = other.cachedProxyType;
// this.cachedProxyConstructor = other.cachedProxyConstructor;
this.Interfaces = (Type[]) CollectionUtils.ToArray(other.Interfaces, typeof(Type));
foreach (Type intf in other.interfaceMap.Keys)
{
this.interfaceMap[intf] = other.interfaceMap[intf];
}
this._advisors = new ArrayList();
foreach (IAdvisor advisor in other._advisors)
foreach (IAdvisor advisor in advisors)
{
AssertUtils.ArgumentNotNull(advisor, "Advisor must not be null");
AddAdvisor(advisor);
}
this._introductions = new ArrayList();
foreach (IIntroductionAdvisor advisor in other._introductions)
{
foreach (IIntroductionAdvisor advisor in introductions)
{
// TODO (EE): implement
// ValidateIntroductionAdvisor((IIntroductionAdvisor) advisor);
AssertUtils.ArgumentNotNull(advisor, "IntroductionAdvisor must not be null");
AddIntroduction(advisor);
}
UpdateAdvisorsArray();
AdviceChanged();
}
/// <summary>
@@ -1468,33 +1573,10 @@ namespace Spring.Aop.Framework
{
lock (this.SyncRoot)
{
return ToStringInternal();
return ToProxyConfigString();
}
}
/// <summary>
/// A <see cref="System.String"/> that represents the current
/// <see cref="Spring.Aop.Framework.ProxyConfig"/> configuration.
/// </summary>
/// <returns>
/// A <see cref="System.String"/> that represents the current
/// <see cref="Spring.Aop.Framework.ProxyConfig"/> configuration.
/// </returns>
private string ToStringInternal()
{
StringBuilder buffer = new StringBuilder(this.GetType().FullName + ":\n");
buffer.Append(this.interfaceMap.Count + " interfaces=[");
this.InterfacesToString(buffer);
buffer.Append("];\n");
buffer.Append(this._advisors.Count + " pointcuts=[");
this.AdvisorsToString(buffer);
buffer.Append("];\n");
buffer.Append("targetSource=[" + this.m_targetSource + "];\n");
buffer.Append("advisorChainFactory=" + this.advisorChainFactory + ";\n");
buffer.Append(base.ToString());
return buffer.ToString();
}
/// <summary>
/// Helper method that adds the names of all of the proxied interfaces
/// to the buffer of the supplied <see cref="System.Text.StringBuilder"/>.
@@ -1568,7 +1650,7 @@ namespace Spring.Aop.Framework
{
throw new AopConfigException("Can't proxy null object");
}
return ReflectionUtils.GetInterfaces(target.GetType());
return ReflectionUtils.GetInterfaces(target is Type ? (Type)target : target.GetType());
}
}
}

View File

@@ -55,8 +55,30 @@ namespace Spring.Aop.Framework.DynamicProxy
/// </summary>
private static readonly ILog logger = LogManager.GetLogger(typeof(CachedAopProxyFactory));
private static Hashtable typeCache = new Hashtable();
private static readonly Hashtable typeCache = new Hashtable();
/// <summary>
/// Returns the number of proxy types in the cache
/// </summary>
public static int CountCachedTypes
{
get { return typeCache.Count; }
}
/// <summary>
/// Clears the type cache
/// </summary>
public static void ClearCache()
{
typeCache.Clear();
}
/// <summary>
/// Creates a new instance
/// </summary>
public CachedAopProxyFactory()
{}
/// <summary>
/// Generates the proxy type and caches the <see cref="System.Type"/>
/// instance against the base type and the interfaces to proxy.

View File

@@ -169,7 +169,7 @@ namespace Spring.Aop.Framework
/// </remarks>
public virtual bool IsFrozen
{
get { return frozen; }
get { return this.frozen; }
set { this.frozen = value; }
}

View File

@@ -42,7 +42,7 @@ namespace Spring.Aop.Framework
[Serializable]
public class ProxyFactory : AdvisedSupport
{
/// <summary>
/// <summary>
/// Creates a new instance of the <see cref="Spring.Aop.Framework.ProxyFactory"/>
/// class.
/// </summary>
@@ -59,9 +59,8 @@ namespace Spring.Aop.Framework
/// <exception cref="AopConfigException">
/// If the <paramref name="target"/> is <cref lang="null"/>.
/// </exception>
public ProxyFactory(object target) : base(GetInterfaces(target))
public ProxyFactory(object target) : base(target)
{
Target = target;
}
/// <summary>
@@ -74,7 +73,9 @@ namespace Spring.Aop.Framework
/// </p>
/// </remarks>
/// <param name="interfaces">The interfaces to implement.</param>
public ProxyFactory(Type[] interfaces) : base(interfaces) {}
public ProxyFactory(Type[] interfaces) : base(interfaces)
{
}
/// <summary>
/// Creates a new proxy according to the settings in this factory.

File diff suppressed because it is too large Load Diff

View File

@@ -221,7 +221,24 @@ namespace Spring.Aop.Target
#endregion
#region Fields
#region Fields
/// <summary>
/// Returns a textual representation of this target source instance.
/// This implementation returns <see cref="GetDescription"/>
/// </summary>
public override string ToString()
{
return GetDescription();
}
/// <summary>
/// Returns a textual representation of this target source instance
/// </summary>
protected virtual string GetDescription()
{
return string.Format("[{0}:{1}]", this.GetType().Name, this.TargetObjectName);
}
/// <summary>
/// The shared <see cref="Common.Logging.ILog"/> instance for this class (and derived classes).

View File

@@ -415,6 +415,14 @@ namespace Spring.Context.Support
{
}
/// <summary>
/// Template method which can be overridden to add context-specific
/// work before the underlying object factory gets refreshed.
/// </summary>
protected virtual void OnPreRefresh()
{
}
/// <summary>
/// Template method which can be overridden to add context-specific
/// refresh work.
@@ -429,6 +437,15 @@ namespace Spring.Context.Support
{
}
/// <summary>
/// Template method which can be overridden to add context-specific
/// work after the context was refreshed but before the <see cref="ContextEventArgs.ContextEvent.Refreshed"/>
/// event gets raised.
/// </summary>
protected virtual void OnPostRefresh()
{
}
/// <summary>
/// Instantiate and invoke all registered
/// <see cref="Spring.Objects.Factory.Config.IObjectFactoryPostProcessor"/>
@@ -761,20 +778,58 @@ namespace Spring.Context.Support
/// <exception cref="Spring.Objects.ObjectsException">
/// If the object factory could not be initialized.
/// </exception>
public virtual void Refresh()
public void Refresh()
{
lock (SyncRoot)
{
_startupDate = DateTime.Now;
OnPreRefresh();
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(string.Format("ApplicationContext Refresh: Refreshing object factory "));
}
#endregion
RefreshObjectFactory();
IConfigurableListableObjectFactory objectFactory = ObjectFactory;
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(string.Format("ApplicationContext Refresh: Registering well-known processors and objects"));
}
#endregion
PrepareObjectFactory(objectFactory);
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(string.Format("ApplicationContext Refresh: Custom post processing object factory"));
}
#endregion
PostProcessObjectFactory(objectFactory);
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(string.Format("ApplicationContext Refresh: Post processing object factory using pre-registered processors"));
}
#endregion
foreach (IObjectFactoryPostProcessor factoryProcessor in ObjectFactoryPostProcessors)
{
factoryProcessor.PostProcessObjectFactory(objectFactory);
@@ -793,21 +848,57 @@ namespace Spring.Context.Support
#endregion
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(string.Format("ApplicationContext Refresh: Post processing object factory using defined processors"));
}
#endregion
InvokeObjectFactoryPostProcessors();
RegisterObjectPostProcessors(objectFactory);
InitEventRegistry();
InitMessageSource();
OnRefresh();
RefreshApplicationEventListeners();
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(string.Format("ApplicationContext Refresh: Preinstantiating singletons"));
}
#endregion
objectFactory.PreInstantiateSingletons();
OnPostRefresh();
new DefensiveEventRaiser().Raise(
ContextEvent, this,
new ContextEventArgs(ContextEventArgs.ContextEvent.Refreshed));
#region Instrumentation
if (log.IsInfoEnabled)
{
log.Info(string.Format("ApplicationContext Refresh: Completed"));
}
#endregion
}
}
/// <summary>
/// Registers well-known <see cref="IObjectPostProcessor"/>s and
/// preregisters well-known dependencies using <see cref="IConfigurableListableObjectFactory.RegisterResolvableDependency"/>
/// </summary>
/// <param name="objectFactory">the raw object factory as returned from <see cref="RefreshObjectFactory"/></param>
private void PrepareObjectFactory(IConfigurableListableObjectFactory objectFactory)
{
EnsureKnownObjectPostProcessors(objectFactory);
@@ -819,7 +910,6 @@ namespace Spring.Context.Support
objectFactory.RegisterResolvableDependency(typeof(IApplicationEventPublisher), this);
objectFactory.RegisterResolvableDependency(typeof(IApplicationContext), this);
objectFactory.RegisterResolvableDependency(typeof(IEventRegistry), this);
}
/// <summary>

View File

@@ -1810,7 +1810,7 @@ namespace Spring.Objects.Factory.Support
if (log.IsDebugEnabled)
{
log.Debug(string.Format("configuring object '{0}' using definition '{1}'", instance, name));
log.Debug(string.Format("Configuring object using definition '{1}'", instance, name));
}
#endregion

View File

@@ -759,7 +759,7 @@ namespace Spring.Objects.Factory.Support
{
// don't let calling code try to dereference the
// object factory if the object isn't a factory
if (IsFactoryDereference(name) && !(ObjectUtils.IsAssignable(typeof (IFactoryObject), instance)))
if (IsFactoryDereference(name) && !(ObjectUtils.IsAssignable(typeof(IFactoryObject), instance)))
{
throw new ObjectIsNotAFactoryException(canonicalName, instance);
}
@@ -770,7 +770,7 @@ namespace Spring.Objects.Factory.Support
// it's a normal object ?
if (!ObjectUtils.IsAssignable(typeof (IFactoryObject), instance))
if (!ObjectUtils.IsAssignable(typeof(IFactoryObject), instance))
{
#region Instrumentation
@@ -785,7 +785,7 @@ namespace Spring.Objects.Factory.Support
}
// the user wants the factory itself ?
if (!ObjectUtils.IsAssignable(typeof (IFactoryObject), instance) || IsFactoryDereference(name))
if (!ObjectUtils.IsAssignable(typeof(IFactoryObject), instance) || IsFactoryDereference(name))
{
#region Instrumentation
@@ -819,8 +819,15 @@ namespace Spring.Objects.Factory.Support
if (resultInstance == null)
{
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(string.Format("Dereferencing Object with name '{0}'", canonicalName));
}
#endregion
// return object instance from factory...
IFactoryObject factory = (IFactoryObject) instance;
IFactoryObject factory = (IFactoryObject)instance;
if (rod == null && ContainsObjectDefinition(canonicalName))
{
@@ -854,6 +861,15 @@ namespace Spring.Objects.Factory.Support
+ "circular object reference.");
}
}
else
{
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(string.Format("Returning factory product from cache for Object with name '{0}'", canonicalName));
}
#endregion
}
return resultInstance;
}
@@ -1873,89 +1889,122 @@ namespace Spring.Objects.Factory.Support
/// <seealso cref="Spring.Objects.Factory.IObjectFactory.GetObject(string, Type, object[])"/>
protected object GetObjectInternal(string name, Type requiredType, object[] arguments, bool suppressConfigure)
{
string objectName = TransformedObjectName(name);
object instance = null;
// those are cases, where singleton cache can be used
if (arguments == null && !suppressConfigure)
const int INDENT = 3;
bool hasErrors = false;
try
{
// eagerly check singleton cache for manually registered singletons...
object sharedInstance = GetSingleton(objectName);
string objectName = TransformedObjectName(name);
if (sharedInstance != null)
#region Instrumentation
if (log.IsDebugEnabled)
{
#region Instrumentation
log.Debug(string.Format("{2}GetObjectInternal: obtaining instance for name {0} => canonical name {1}", name, objectName, new String(' ', nestingCount * INDENT)));
nestingCount++;
}
#endregion
if (IsSingletonCurrentlyInCreation(objectName))
object instance = null;
// those are cases, where singleton cache can be used
if (arguments == null && !suppressConfigure)
{
// eagerly check singleton cache for manually registered singletons...
object sharedInstance = GetSingleton(objectName);
if (sharedInstance != null)
{
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug("Returning eagerly cached instance of singleton object '" + objectName +
"' that is not fully initialized yet - a consequence of a circular reference");
if (IsSingletonCurrentlyInCreation(objectName))
{
log.Debug("Returning eagerly cached instance of singleton object '" + objectName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else
{
log.Debug(string.Format("Returning cached instance of singleton object '{0}'.", objectName));
}
}
#endregion
instance = GetObjectForInstance(sharedInstance, name, objectName, null);
return EnsureObjectIsOfRequiredType(name, instance, requiredType);
}
else
}
// check if object definition exists
RootObjectDefinition mergedObjectDefinition = null;
mergedObjectDefinition = GetMergedObjectDefinition(objectName, false);
if (mergedObjectDefinition == null)
{
if (ParentObjectFactory != null)
{
if (log.IsDebugEnabled)
{
log.Debug(string.Format("Returning cached instance of singleton object '{0}'.", objectName));
}
return ParentObjectFactory.GetObject(name, requiredType, arguments);
}
#endregion
instance = GetObjectForInstance(sharedInstance, name, objectName, null);
return EnsureObjectIsOfRequiredType(name, instance, requiredType);
throw new NoSuchObjectDefinitionException(name, "Cannot find definition for object [" + name + "]");
}
}
// check if object definition exists
RootObjectDefinition mergedObjectDefinition = null;
mergedObjectDefinition = GetMergedObjectDefinition(objectName, false);
if (mergedObjectDefinition == null)
{
if (ParentObjectFactory != null)
if (arguments != null
|| suppressConfigure)
{
return ParentObjectFactory.GetObject(name, requiredType, arguments);
// Clone ObjectDefinition
mergedObjectDefinition = CreateRootObjectDefinition(mergedObjectDefinition);
mergedObjectDefinition.IsSingleton = false;
if (arguments != null)
{
// Override constructor values and configure as a prototype if arguments are specified
mergedObjectDefinition.ConstructorArgumentValues = null;
}
}
throw new NoSuchObjectDefinitionException(name, "Cannot find definition for object [" + name + "]");
}
if (arguments != null
|| suppressConfigure)
{
// Clone ObjectDefinition
mergedObjectDefinition = CreateRootObjectDefinition(mergedObjectDefinition);
mergedObjectDefinition.IsSingleton = false;
if (arguments != null)
CheckMergedObjectDefinition(mergedObjectDefinition, objectName, requiredType, arguments);
// return IObjectDefinition instance itself for an abstract object-definition
if (mergedObjectDefinition.IsAbstract)
{
// Override constructor values and configure as a prototype if arguments are specified
mergedObjectDefinition.ConstructorArgumentValues = null;
instance = mergedObjectDefinition;
}
else if (mergedObjectDefinition.IsSingleton)
{
// create object instance...
object sharedInstance = CreateAndCacheSingletonInstance(objectName, mergedObjectDefinition, arguments);
instance = GetObjectForInstance(sharedInstance, name, objectName, mergedObjectDefinition);
}
else
{
// it's a prototype, so create a new instance...
instance = InstantiateObject(name, mergedObjectDefinition, arguments, true, suppressConfigure);
}
}
CheckMergedObjectDefinition(mergedObjectDefinition, objectName, requiredType, arguments);
// return IObjectDefinition instance itself for an abstract object-definition
if (mergedObjectDefinition.IsAbstract)
{
instance = mergedObjectDefinition;
return EnsureObjectIsOfRequiredType(name, instance, requiredType);
}
else if (mergedObjectDefinition.IsSingleton)
catch
{
// create object instance...
object sharedInstance = CreateAndCacheSingletonInstance(objectName, mergedObjectDefinition, arguments);
instance = GetObjectForInstance(sharedInstance, name, objectName, mergedObjectDefinition);
#region Instrumentation
if (log.IsErrorEnabled)
{
hasErrors = true;
nestingCount--;
log.Error(string.Format("{1}GetObjectInternal: error obtaining object {0}", name, new String(' ', nestingCount * INDENT)));
}
#endregion
throw;
}
else
finally
{
// it's a prototype, so create a new instance...
instance = InstantiateObject(name, mergedObjectDefinition, arguments, true, suppressConfigure);
#region Instrumentation
if (log.IsDebugEnabled && !hasErrors)
{
nestingCount--;
log.Debug(string.Format("{1}GetObjectInternal: returning instance for objectname {0}", name, new String(' ', nestingCount * INDENT)));
}
#endregion
}
return EnsureObjectIsOfRequiredType(name, instance, requiredType);
}
[ThreadStatic]
private int nestingCount;
/// <summary>
/// Checks, if the passed instance is of the required type.
/// </summary>
@@ -2001,12 +2050,10 @@ namespace Spring.Objects.Factory.Support
if (sharedInstance == null)
{
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug("Creating shared instance of singleton object '" + objectName + "'");
log.Debug(string.Format("Creating shared instance of singleton object '{0}'", objectName));
}
#endregion
BeforeSingletonCreation(objectName);
@@ -2019,6 +2066,13 @@ namespace Spring.Objects.Factory.Support
AfterSingletonCreation(objectName);
}
AddSingleton(objectName, sharedInstance);
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(string.Format("Cached shared instance of singleton object '{0}'", objectName));
}
#endregion
}
return sharedInstance;
}
@@ -2138,19 +2192,19 @@ namespace Spring.Objects.Factory.Support
{
if (objectPostProcessor is IObjectFactoryAware)
{
((IObjectFactoryAware) objectPostProcessor).ObjectFactory = this;
((IObjectFactoryAware)objectPostProcessor).ObjectFactory = this;
}
// ensure the same instance doesn't get registered twice
if (!ObjectPostProcessors.Contains( objectPostProcessor ))
if (!ObjectPostProcessors.Contains(objectPostProcessor))
{
ObjectPostProcessors.Add( objectPostProcessor );
ObjectPostProcessors.Add(objectPostProcessor);
}
if (typeof( IInstantiationAwareObjectPostProcessor ).IsInstanceOfType( objectPostProcessor ))
if (typeof(IInstantiationAwareObjectPostProcessor).IsInstanceOfType(objectPostProcessor))
{
hasInstantiationAwareBeanPostProcessors = true;
}
if (typeof( IDestructionAwareObjectPostProcessor ).IsInstanceOfType( objectPostProcessor ))
if (typeof(IDestructionAwareObjectPostProcessor).IsInstanceOfType(objectPostProcessor))
{
hasDestructionAwareBeanPostProcessors = true;
}
@@ -2206,6 +2260,19 @@ namespace Spring.Objects.Factory.Support
}
}
/// <summary>
/// Register the given custom <see cref="System.ComponentModel.TypeConverter"/>
/// for all properties of the given <see cref="System.Type"/>.
/// </summary>
/// <seealso cref="Spring.Objects.Factory.Config.IConfigurableObjectFactory.RegisterCustomConverter"/>.
public void RegisterCustomConverter(Type requiredType, TypeConverter converter)
{
AssertUtils.ArgumentNotNull(requiredType, "requiredType");
TypeConverterRegistry.RegisterConverter(requiredType, converter);
}
#region ISingletonObjectRegistry Members
/// <summary>
/// Register the given existing object as singleton in the object factory,
/// under the given object name.
@@ -2228,17 +2295,6 @@ namespace Spring.Objects.Factory.Support
}
}
/// <summary>
/// Register the given custom <see cref="System.ComponentModel.TypeConverter"/>
/// for all properties of the given <see cref="System.Type"/>.
/// </summary>
/// <seealso cref="Spring.Objects.Factory.Config.IConfigurableObjectFactory.RegisterCustomConverter"/>.
public void RegisterCustomConverter(Type requiredType, TypeConverter converter)
{
AssertUtils.ArgumentNotNull(requiredType, "requiredType");
TypeConverterRegistry.RegisterConverter(requiredType, converter);
}
/// <summary>
/// Does this object factory contains a singleton instance with the
/// supplied <paramref name="name"/>?
@@ -2253,9 +2309,6 @@ namespace Spring.Objects.Factory.Support
}
}
#region ISingletonObjectRegistry Members
/// <summary>
/// Gets the names of singleton objects registered in this registry.
/// </summary>

View File

@@ -147,16 +147,16 @@ namespace Spring.Objects.Factory.Support
if (resolvedValues != null)
{
UnsatisfiedDependencyExceptionData unsatisfiedDependencyExceptionData = null;
UnsatisfiedDependencyExceptionData unsatisfiedDependencyExceptionData = null;
// Try to resolve arguments for current constructor
//need to check for null as indicator of no ctor arg match instead of using exceptions for flow
//control as in the Java implementation
args = CreateArgumentArray(objectName, rod, resolvedValues, wrapper, paramTypes, candidate,
autowiring, out unsatisfiedDependencyExceptionData);
if (args == null)
{
if (i == candidates.Length -1 && constructorToUse == null)
if (i == candidates.Length - 1 && constructorToUse == null)
{
throw new UnsatisfiedDependencyException(rod.ResourceDescription,
objectName,
@@ -167,7 +167,8 @@ namespace Spring.Objects.Factory.Support
// try next constructor...
continue;
}
} else
}
else
{
// Explicit arguments given -> arguments length must match exactly
if (paramTypes.Length != explicitArgs.Length)
@@ -243,7 +244,7 @@ namespace Spring.Objects.Factory.Support
public virtual IObjectWrapper InstantiateUsingFactoryMethod(string name, RootObjectDefinition definition, object[] arguments)
{
ObjectWrapper wrapper = new ObjectWrapper();
Type factoryClass = null;
Type factoryClass = null;
bool isStatic = true;
@@ -263,7 +264,7 @@ namespace Spring.Objects.Factory.Support
// if we have constructor args, don't need to resolve them...
expectedArgCount = arguments.Length;
}
if (StringUtils.HasText(definition.FactoryObjectName))
{
@@ -277,73 +278,69 @@ namespace Spring.Objects.Factory.Support
factoryClass = definition.ObjectType;
}
bool autowiring = (definition.AutowireMode == AutoWiringMode.Constructor);
#if NET_2_0
GenericArgumentsHolder genericArgsInfo = new GenericArgumentsHolder(definition.FactoryMethodName);
MethodInfo[] factoryMethodCandidates = FindMethods(genericArgsInfo.GenericMethodName, expectedArgCount, isStatic, factoryClass);
#else
MethodInfo[] factoryMethodCandidates = FindMethods(definition.FactoryMethodName, expectedArgCount, isStatic, factoryClass);
#endif
bool autowiring = (definition.AutowireMode == AutoWiringMode.Constructor);
MethodInfo[] factoryMethods = FindMethods(genericArgsInfo.GenericMethodName, expectedArgCount, isStatic, factoryClass);
UnsatisfiedDependencyExceptionData unsatisfiedDependencyExceptionData = null;
// try all matching methods to see if they match the constructor arguments...
for (int i = 0; i < factoryMethods.Length; i++)
for (int i = 0; i < factoryMethodCandidates.Length; i++)
{
unsatisfiedDependencyExceptionData = null;
MethodInfo factoryMethod = factoryMethods[i];
Type[] paramTypes = new Type[] { };
MethodInfo factoryMethodCandidate = factoryMethodCandidates[i];
#if NET_2_0
if (genericArgsInfo.ContainsGenericArguments)
{
string[] unresolvedGenericArgs = genericArgsInfo.GetGenericArguments();
if (factoryMethod.GetGenericArguments().Length != unresolvedGenericArgs.Length)
if (factoryMethodCandidate.GetGenericArguments().Length != unresolvedGenericArgs.Length)
continue;
paramTypes = new Type[unresolvedGenericArgs.Length];
Type[] paramTypes = new Type[unresolvedGenericArgs.Length];
for (int j = 0; j < unresolvedGenericArgs.Length; j++)
{
paramTypes[j] = TypeResolutionUtils.ResolveType(unresolvedGenericArgs[j]);
}
factoryMethod = factoryMethod.MakeGenericMethod(paramTypes);
factoryMethodCandidate = factoryMethodCandidate.MakeGenericMethod(paramTypes);
}
#else
MethodInfo[] factoryMethods = FindMethods(definition.FactoryMethodName, expectedArgCount, isStatic, factoryClass);
UnsatisfiedDependencyExceptionData unsatisfiedDependencyExceptionData = null;
// try all matching methods to see if they match the constructor arguments...
foreach(MethodInfo factoryMethod in factoryMethods)
{
Type[] paramTypes = new Type[] { };
#endif
if (arguments == null || arguments.Length == 0)
{
paramTypes = ReflectionUtils.GetParameterTypes(factoryMethod.GetParameters());
Type[] paramTypes = ReflectionUtils.GetParameterTypes(factoryMethodCandidate.GetParameters());
// try to create the required arguments...
ArgumentsHolder args = CreateArgumentArray(name, definition, resolvedValues, wrapper,
paramTypes, factoryMethod, autowiring, out unsatisfiedDependencyExceptionData);
UnsatisfiedDependencyExceptionData unsatisfiedDependencyExceptionData = null;
ArgumentsHolder args = CreateArgumentArray(name, definition, resolvedValues, wrapper, paramTypes,
factoryMethodCandidate, autowiring, out unsatisfiedDependencyExceptionData);
if (args == null)
{
arguments = null;
// if we failed to match this method, keep
// trying new overloaded factory methods...
continue;
}
}
else
{
arguments = args.arguments;
}
}
// if we get here, we found a factory method...
// if we get here, we found a usable candidate factory method - check, if arguments match
//arguments = (arguments.Length == 0 ? null : arguments);
if (ReflectionUtils.GetMethodByArgumentValues(new MethodInfo[] { factoryMethod }, arguments) == null)
if (ReflectionUtils.GetMethodByArgumentValues(new MethodInfo[] { factoryMethodCandidate }, arguments) == null)
{
continue;
}
object objectInstance = instantiationStrategy.Instantiate(definition, name, objectFactory, factoryMethod, arguments);
object objectInstance = instantiationStrategy.Instantiate(definition, name, objectFactory, factoryMethodCandidate, arguments);
wrapper.WrappedInstance = objectInstance;
#region Instrumentation
if (log.IsDebugEnabled)
{
log.Debug(string.Format(CultureInfo.InvariantCulture, "Object '{0}' instantiated via factory method [{1}].", name, factoryMethod));
log.Debug(string.Format(CultureInfo.InvariantCulture, "Object '{0}' instantiated via factory method [{1}].", name, factoryMethodCandidate));
}
#endregion
@@ -412,10 +409,11 @@ namespace Spring.Objects.Factory.Support
object originalValue = valueHolder.Value;
object convertedValue = TypeConversionUtils.ConvertValueIfNecessary(paramType, originalValue, null);
args.arguments[paramIndex] = convertedValue;
//?
args.preparedArguments[paramIndex] = convertedValue;
} catch (TypeMismatchException ex)
}
catch (TypeMismatchException ex)
{
//To avoid using exceptions for flow control, this is not a cost in Java as stack trace is lazily created.
string errorMessage = String.Format(CultureInfo.InvariantCulture,
@@ -425,7 +423,8 @@ namespace Spring.Objects.Factory.Support
unsatisfiedDependencyExceptionData = new UnsatisfiedDependencyExceptionData(paramIndex, paramType, errorMessage);
return null;
}
} else
}
else
{
// No explicit match found: we're either supposed to autowire or
// have to fail creating an argument array for the given constructor.
@@ -447,25 +446,26 @@ namespace Spring.Objects.Factory.Support
args.arguments[paramIndex] = autowiredArgument;
args.preparedArguments[paramIndex] = new AutowiredArgumentMarker();
resolveNecessary = true;
} catch (ObjectsException ex)
}
catch (ObjectsException ex)
{
unsatisfiedDependencyExceptionData = new UnsatisfiedDependencyExceptionData(paramIndex, paramType, ex.Message);
return null;
}
}
}
foreach (string autowiredObjectName in autowiredObjectNames)
{
if (log.IsDebugEnabled)
{
log.Debug("Autowiring by type from object name '" + objectName +
"' via " + methodType + " to object named '" + autowiredObjectName + "'");
}
if (log.IsDebugEnabled)
{
log.Debug("Autowiring by type from object name '" + objectName +
"' via " + methodType + " to object named '" + autowiredObjectName + "'");
}
}
return args;
}
@@ -533,7 +533,7 @@ namespace Spring.Objects.Factory.Support
minNrOfArgs = index + 1;
}
ConstructorArgumentValues.ValueHolder valueHolder =
(ConstructorArgumentValues.ValueHolder) entry.Value;
(ConstructorArgumentValues.ValueHolder)entry.Value;
string argName = "constructor argument with index " + index;
object resolvedValue =
valueResolver.ResolveValueIfNecessary(objectName, definition, argName, valueHolder.Value);
@@ -557,10 +557,10 @@ namespace Spring.Objects.Factory.Support
}
foreach (DictionaryEntry namedArgumentEntry in definition.ConstructorArgumentValues.NamedArgumentValues)
{
string argumentName = (string) namedArgumentEntry.Key;
string argumentName = (string)namedArgumentEntry.Key;
string syntheticArgumentName = "constructor argument with name " + argumentName;
ConstructorArgumentValues.ValueHolder valueHolder =
(ConstructorArgumentValues.ValueHolder) namedArgumentEntry.Value;
(ConstructorArgumentValues.ValueHolder)namedArgumentEntry.Value;
object resolvedValue =
valueResolver.ResolveValueIfNecessary(objectName, definition, syntheticArgumentName, valueHolder.Value);
resolvedValues.AddNamedArgumentValue(argumentName, resolvedValue);
@@ -625,9 +625,9 @@ namespace Spring.Objects.Factory.Support
public int GetTypeDifferenceWeight(Type[] paramTypes)
{
// If valid arguments found, determine type difference weight.
// Try type difference weight on both the converted arguments and
// the raw arguments. If the raw weight is better, use it.
// Decrease raw weight by 1024 to prefer it over equal converted weight.
// Try type difference weight on both the converted arguments and
// the raw arguments. If the raw weight is better, use it.
// Decrease raw weight by 1024 to prefer it over equal converted weight.
int typeDiffWeight = AutowireUtils.GetTypeDifferenceWeight(paramTypes, this.arguments);
int rawTypeDiffWeight = AutowireUtils.GetTypeDifferenceWeight(paramTypes, this.rawArguments) - 1024;
return (rawTypeDiffWeight < typeDiffWeight ? rawTypeDiffWeight : typeDiffWeight);

View File

@@ -266,8 +266,8 @@ namespace Spring.Objects.Factory.Support
protected override object CreateAndCacheSingletonInstance(
string objectName, RootObjectDefinition objectDefinition, object[] arguments)
{
if (objectDefinition is IWebObjectDefinition
&& ((IWebObjectDefinition)objectDefinition).Scope != ObjectScope.Application)
if (IsWebScopedSingleton(objectDefinition)
)
{
ObjectScope scope = ((IWebObjectDefinition)objectDefinition).Scope;

View File

@@ -222,9 +222,9 @@ namespace Spring.Aop.Framework
private ITestObject CreateProxy(object target, IAdvice interceptor, bool exposeProxy)
{
ProxyFactory pf = new ProxyFactory();
ProxyFactory pf = new ProxyFactory(target);
pf.ExposeProxy = exposeProxy;
pf.Target = target;
// pf.Target = target;
pf.AddAdvice(interceptor);
return pf.GetProxy() as ITestObject;

View File

@@ -96,14 +96,6 @@ namespace Spring.Aop.Framework.AutoProxy
ProxyAssertions(testObject, 1);
}
[Test]
public void DecoratorProxyWithWildcardMatch()
{
ITestObject testObject = (ITestObject)ctx.GetObject("decoratorProxy");
DecoratorProxyAssertions(testObject);
Assert.AreEqual("decoratorProxy", testObject.Name);
}
[Test]
public void FrozenProxy()
{
@@ -141,6 +133,14 @@ namespace Spring.Aop.Framework.AutoProxy
Assert.AreEqual(2*nopInterceptorCount, nop.Count);
}
[Test]
public void DecoratorProxyWithWildcardMatch()
{
ITestObject testObject = (ITestObject)ctx.GetObject("decoratorProxy");
DecoratorProxyAssertions(testObject);
Assert.AreEqual("decoratorProxy", testObject.Name);
}
private void DecoratorProxyAssertions(ITestObject testObject)
{
CountingBeforeAdvice cba = (CountingBeforeAdvice) ctx.GetObject("countingBeforeAdvice");

View File

@@ -459,15 +459,13 @@ namespace Spring.Aop.Framework.DynamicProxy
ITestObject target = new TestObject();
target.Age = 26;
AdvisedSupport advised = new AdvisedSupport();
advised.Target = target;
AdvisedSupport advised = new AdvisedSupport(target);
advised.AddAdvice(new NopInterceptor());
IAopProxy aop = CreateAopProxy(advised);
ITestObject proxy1 = (ITestObject)aop.GetProxy();
Assert.AreEqual(target.Age, proxy1.Age, "Incorrect age");
advised = new AdvisedSupport();
advised.Target = proxy1;
advised = new AdvisedSupport(proxy1);
advised.AddAdvice(new NopInterceptor());
aop = CreateAopProxy(advised);
ITestObject proxy2 = (ITestObject)aop.GetProxy();
@@ -483,14 +481,12 @@ namespace Spring.Aop.Framework.DynamicProxy
TheCommand target = new TheCommand();
// proxy
AdvisedSupport advised = new AdvisedSupport();
advised.Target = target;
AdvisedSupport advised = new AdvisedSupport(target);
advised.AddAdvice(new NopInterceptor());
object proxy = CreateProxy(advised);
// proxy again
advised = new AdvisedSupport();
advised.Target = proxy;
advised = new AdvisedSupport(proxy);
advised.AddAdvice(new NopInterceptor());
proxy = CreateAopProxy(advised);
@@ -844,8 +840,7 @@ namespace Spring.Aop.Framework.DynamicProxy
NopInterceptor ni = new NopInterceptor();
AdvisedSupport advised = new AdvisedSupport();
advised.TargetSource = mockTargetSource;
AdvisedSupport advised = new AdvisedSupport(mockTargetSource);
advised.AddAdvice(ni);
AbstractProxyTypeBuilderTests.InterfaceWithGenericMethod proxy =
@@ -884,8 +879,7 @@ namespace Spring.Aop.Framework.DynamicProxy
NopInterceptor ni = new NopInterceptor();
AdvisedSupport advised = new AdvisedSupport();
advised.TargetSource = mockTargetSource;
AdvisedSupport advised = new AdvisedSupport(mockTargetSource);
advised.AddAdvice(ni);
AbstractProxyTypeBuilderTests.GenericInterface<TestObject> proxy =
@@ -927,8 +921,7 @@ namespace Spring.Aop.Framework.DynamicProxy
TestObject target = new TestObject();
target.Age = 26;
AdvisedSupport advised = new AdvisedSupport();
advised.Target = target;
AdvisedSupport advised = new AdvisedSupport(target);
advised.AddAdvice(new NopInterceptor());
ITestObject proxy = CreateProxy(advised) as ITestObject;
@@ -1716,8 +1709,7 @@ namespace Spring.Aop.Framework.DynamicProxy
public void CanCastProxyToIAdvised()
{
TestObject to = new TestObject();
AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.Target = to;
AdvisedSupport advisedSupport = new AdvisedSupport(to);
NopInterceptor ni = new NopInterceptor();
advisedSupport.AddAdvice(0, ni);

View File

@@ -39,8 +39,9 @@ namespace Spring.Aop.Framework.DynamicProxy
[TestFixture]
public sealed class CachedAopProxyFactoryTests : DefaultAopProxyFactoryTests
{
protected override IAopProxy CreateAopProxy(AdvisedSupport advisedSupport)
protected override IAopProxy CreateAopProxy(ProxyFactory advisedSupport)
{
// return (IAopProxy) advisedSupport.GetProxy();
IAopProxyFactory apf = new CachedAopProxyFactory();
return apf.CreateAopProxy(advisedSupport);
}
@@ -48,24 +49,20 @@ namespace Spring.Aop.Framework.DynamicProxy
[SetUp]
public void SetUp()
{
// Clear Aop proxy type cache
Assert.IsNotNull(TypeCacheField);
TypeCacheField.SetValue(null, new Hashtable());
CachedAopProxyFactory.ClearCache();
}
[Test]
public void DoesNotCacheWithDifferentBaseType()
{
// Decorated-based proxy (BaseType == TargetType)
AdvisedSupport advisedSupport = new AdvisedSupport();
ProxyFactory advisedSupport = new ProxyFactory(new TestObject());
advisedSupport.ProxyTargetType = true;
advisedSupport.Target = new TestObject();
CreateAopProxy(advisedSupport);
// Composition-based proxy (BaseType = BaseCompositionAopProxy)
advisedSupport = new AdvisedSupport();
advisedSupport = new ProxyFactory(new TestObject());
advisedSupport.ProxyTargetType = false;
advisedSupport.Target = new TestObject();
CreateAopProxy(advisedSupport);
AssertAopProxyTypeCacheCount(2);
@@ -74,12 +71,10 @@ namespace Spring.Aop.Framework.DynamicProxy
[Test]
public void DoesNotCacheWithDifferentTargetType()
{
AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.Target = new BadCommand();
ProxyFactory advisedSupport = new ProxyFactory(new BadCommand());
CreateAopProxy(advisedSupport);
advisedSupport = new AdvisedSupport();
advisedSupport.Target = new GoodCommand();
advisedSupport = new ProxyFactory(new GoodCommand());
CreateAopProxy(advisedSupport);
AssertAopProxyTypeCacheCount(2);
@@ -88,20 +83,17 @@ namespace Spring.Aop.Framework.DynamicProxy
[Test]
public void DoesNotCacheWithDifferentInterfaces()
{
AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.Target = new TestObject();
ProxyFactory advisedSupport = new ProxyFactory(new TestObject());
CreateAopProxy(advisedSupport);
advisedSupport = new AdvisedSupport();
advisedSupport.Target = new TestObject();
advisedSupport = new ProxyFactory(new TestObject());
advisedSupport.AddInterface(typeof(IPerson));
CreateAopProxy(advisedSupport);
AssertAopProxyTypeCacheCount(2);
// Same with Introductions
advisedSupport = new AdvisedSupport();
advisedSupport.Target = new TestObject();
advisedSupport = new ProxyFactory(new TestObject());
TimestampIntroductionInterceptor ti = new TimestampIntroductionInterceptor();
ti.TimeStamp = new DateTime(666L);
IIntroductionAdvisor introduction = new DefaultIntroductionAdvisor(ti, typeof(ITimeStamped));
@@ -114,14 +106,12 @@ namespace Spring.Aop.Framework.DynamicProxy
[Test]
public void DoesCacheWithTwoDecoratorBasedProxy()
{
AdvisedSupport advisedSupport = new AdvisedSupport();
ProxyFactory advisedSupport = new ProxyFactory(new TestObject());
advisedSupport.ProxyTargetType = true;
advisedSupport.Target = new TestObject();
CreateAopProxy(advisedSupport);
advisedSupport = new AdvisedSupport();
advisedSupport = new ProxyFactory(new TestObject());
advisedSupport.ProxyTargetType = true;
advisedSupport.Target = new TestObject();
CreateAopProxy(advisedSupport);
AssertAopProxyTypeCacheCount(1);
@@ -130,27 +120,18 @@ namespace Spring.Aop.Framework.DynamicProxy
[Test]
public void DoesCacheWithTwoCompositionBasedProxy()
{
AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.Target = new TestObject();
ProxyFactory advisedSupport = new ProxyFactory(new TestObject());
CreateAopProxy(advisedSupport);
advisedSupport = new AdvisedSupport();
advisedSupport.Target = new TestObject();
advisedSupport = new ProxyFactory(new TestObject());
CreateAopProxy(advisedSupport);
AssertAopProxyTypeCacheCount(1);
}
private static readonly FieldInfo TypeCacheField =
typeof(CachedAopProxyFactory).GetField("typeCache", BindingFlags.Static | BindingFlags.NonPublic);
private void AssertAopProxyTypeCacheCount(int count)
{
Assert.IsNotNull(TypeCacheField);
Hashtable cache = TypeCacheField.GetValue(null) as Hashtable;
Assert.IsNotNull(cache);
Assert.AreEqual(count, cache.Count);
Assert.AreEqual(count, CachedAopProxyFactory.CountCachedTypes);
}
#region Helper classes definitions

View File

@@ -209,8 +209,7 @@ namespace Spring.Aop.Framework.DynamicProxy
NopInterceptor ni = new NopInterceptor();
AdvisedSupport advised = new AdvisedSupport();
advised.TargetSource = mockTargetSource;
AdvisedSupport advised = new AdvisedSupport(mockTargetSource);
advised.AddAdvice(ni);
// Cast to the interface that method belongs to

View File

@@ -36,8 +36,9 @@ namespace Spring.Aop.Framework.DynamicProxy
[TestFixture]
public class DefaultAopProxyFactoryTests
{
protected virtual IAopProxy CreateAopProxy(AdvisedSupport advisedSupport)
protected virtual IAopProxy CreateAopProxy(ProxyFactory advisedSupport)
{
// return (IAopProxy) advisedSupport.GetProxy();
IAopProxyFactory apf = new DefaultAopProxyFactory();
return apf.CreateAopProxy(advisedSupport);
}
@@ -46,21 +47,23 @@ namespace Spring.Aop.Framework.DynamicProxy
[ExpectedException(typeof(AopConfigException), ExpectedMessage="Cannot create IAopProxy with null ProxyConfig")]
public void NullConfig()
{
CreateAopProxy(null);
IAopProxyFactory apf = new DefaultAopProxyFactory();
apf.CreateAopProxy(null);
}
[Test]
[ExpectedException(typeof(AopConfigException), ExpectedMessage="Cannot create IAopProxy with no advisors and no target source")]
public void NoInterceptorsAndNoTarget()
{
AdvisedSupport advisedSupport = new AdvisedSupport(new Type[] { typeof(ITestObject) });
ProxyFactory advisedSupport = new ProxyFactory(new Type[] { typeof(ITestObject) });
CreateAopProxy(advisedSupport);
}
[Test]
public void TargetDoesNotImplementAnyInterfaces()
{
AdvisedSupport advisedSupport = new AdvisedSupport();
ProxyFactory advisedSupport = new ProxyFactory();
advisedSupport.AopProxyFactory = new DefaultAopProxyFactory();
advisedSupport.ProxyTargetType = false;
advisedSupport.Target = new DoesNotImplementAnyInterfacesTestObject();
@@ -72,9 +75,7 @@ namespace Spring.Aop.Framework.DynamicProxy
[Test]
public void TargetImplementsAnInterface()
{
AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.Target = new TestObject();
ProxyFactory advisedSupport = new ProxyFactory(new TestObject());
IAopProxy aopProxy = CreateAopProxy(advisedSupport);
Assert.IsNotNull(aopProxy);
@@ -84,7 +85,7 @@ namespace Spring.Aop.Framework.DynamicProxy
[Test]
public void TargetImplementsAnInterfaceWithProxyTargetTypeSetToTrue()
{
AdvisedSupport advisedSupport = new AdvisedSupport();
ProxyFactory advisedSupport = new ProxyFactory();
advisedSupport.ProxyTargetType = true;
advisedSupport.Target = new TestObject();

View File

@@ -230,8 +230,7 @@ namespace Spring.Aop.Framework.DynamicProxy
{
NopInterceptor ni = new NopInterceptor();
AdvisedSupport advised = new AdvisedSupport();
advised.Target = new InheritanceTestObject();
AdvisedSupport advised = new AdvisedSupport(new InheritanceTestObject());
advised.AddAdvice(ni);
object proxy = CreateProxy(advised);
@@ -253,8 +252,7 @@ namespace Spring.Aop.Framework.DynamicProxy
{
NopInterceptor ni = new NopInterceptor();
AdvisedSupport advised = new AdvisedSupport();
advised.Target = new InheritanceTestObject();
AdvisedSupport advised = new AdvisedSupport(new InheritanceTestObject());
advised.AddAdvice(ni);
object proxy = CreateProxy(advised);
@@ -277,8 +275,7 @@ namespace Spring.Aop.Framework.DynamicProxy
{
NopInterceptor ni = new NopInterceptor();
AdvisedSupport advised = new AdvisedSupport();
advised.Target = new InheritanceTestObject();
AdvisedSupport advised = new AdvisedSupport(new InheritanceTestObject());
advised.AddAdvice(ni);
object proxy = CreateProxy(advised);
@@ -296,8 +293,7 @@ namespace Spring.Aop.Framework.DynamicProxy
{
NopInterceptor ni = new NopInterceptor();
AdvisedSupport advised = new AdvisedSupport();
advised.Target = new InheritanceTestObject();
AdvisedSupport advised = new AdvisedSupport(new InheritanceTestObject());
advised.AddAdvice(ni);
object proxy = CreateProxy(advised);
@@ -314,8 +310,7 @@ namespace Spring.Aop.Framework.DynamicProxy
{
NopInterceptor ni = new NopInterceptor();
AdvisedSupport advised = new AdvisedSupport();
advised.Target = new InheritanceTestObject();
AdvisedSupport advised = new AdvisedSupport(new InheritanceTestObject());
advised.AddAdvice(ni);
object proxy = CreateProxy(advised);

View File

@@ -32,9 +32,7 @@ using System.Web;
using AopAlliance.Aop;
using AopAlliance.Intercept;
using NUnit.Framework;
using Rhino.Mocks;
using Spring.Aop.Advice;
using Spring.Aop.Framework.Adapter;
using Spring.Aop.Interceptor;
@@ -164,7 +162,7 @@ namespace Spring.Aop.Framework
Assert.AreEqual(di.Count, 0);
test1.Age = (5);
Assert.AreEqual(test1_1.Age, test1.Age);
Assert.AreEqual(di.Count, 3);
Assert.AreEqual(3, di.Count);
}
[Test]
@@ -180,7 +178,7 @@ namespace Spring.Aop.Framework
public void PrototypeInstancesAreIndependent()
{
IObjectFactory objectFactory = new XmlObjectFactory(new ReadOnlyXmlTestResource("prototypeTests.xml", GetType()));
// Initial count value set in object factory XML
// Initial count value set in object factory XML
int INITIAL_COUNT = 10;
@@ -222,7 +220,7 @@ namespace Spring.Aop.Framework
public void CanGetFactoryReferenceAndManipulate()
{
ITestObject to = (ITestObject)factory.GetObject("test1");
// no exception
// no exception
string dummy = to.Name;
IAdvised config = (IAdvised)to;
@@ -246,7 +244,7 @@ namespace Spring.Aop.Framework
}
/// <summary>
/// Must see effect immediately on behaviour.
/// Must see effect immediately on behaviour.
/// TODO (EE): Note that we can't add or remove interfaces without reconfiguring the singleton.
/// </summary>
[Test, Ignore("change according to ProxyFactoryBeanTests.canAddAndRemoveAdvicesOnSingleton")]
@@ -376,7 +374,7 @@ namespace Spring.Aop.Framework
/// <summary>
/// Note that we can't add or remove interfaces without reconfiguring the
/// singleton.
/// singleton.
/// </summary>
[Test]
public void CanAddAndRemoveAspectInterfacesOnSingletonByCasting()
@@ -463,6 +461,7 @@ namespace Spring.Aop.Framework
Assert.IsTrue(agi.GlobalsAdded == -1);
ProxyFactoryObject pfb = (ProxyFactoryObject)factory.GetObject("&validGlobals");
pfb.GetObject(); // for creation
Assert.AreEqual(2, pfb.Advisors.Length, "Proxy should have 1 global and 1 explicit advisor");
Assert.AreEqual(1, pfb.Introductions.Length, "Proxy should have 1 global introduction");
@@ -519,20 +518,34 @@ namespace Spring.Aop.Framework
mocks.VerifyAll();
}
[Test]
[ExpectedException(typeof(AopConfigException))]
public void AddAdvisorWhenConfigIsFrozen()
private ProxyFactoryObject CreateFrozenProxyFactory()
{
ProxyFactoryObject fac = new ProxyFactoryObject();
fac.AddInterface(typeof(ITestObject));
fac.IsFrozen = true;
fac.AddAdvisor(new PointcutForVoid());
fac.AddAdvisor(new PointcutForVoid()); // this is ok, no proxy created yet
fac.GetObject();
return fac;
}
[Test]
public void AddAdvisorWhenConfigIsFrozen()
{
ProxyFactoryObject fac = CreateFrozenProxyFactory();
try
{
fac.AddAdvisor(new PointcutForVoid()); // not ok
Assert.Fail("changing a frozen config must throw AopConfigException");
}
catch (AopConfigException)
{}
}
[Test]
[ExpectedException(typeof(AopConfigException))]
public void RemoveAdvisorWhenConfigIsFrozen()
{
ProxyFactoryObject fac = new ProxyFactoryObject();
ProxyFactoryObject fac = CreateFrozenProxyFactory();
fac.IsFrozen = true;
fac.RemoveAdvisor(new PointcutForVoid());
}
@@ -541,7 +554,7 @@ namespace Spring.Aop.Framework
[ExpectedException(typeof(AopConfigException))]
public void ReplaceAdvisorWhenConfigIsFrozen()
{
ProxyFactoryObject fac = new ProxyFactoryObject();
ProxyFactoryObject fac = CreateFrozenProxyFactory();
fac.IsFrozen = true;
fac.ReplaceAdvisor(new PointcutForVoid(), new PointcutForVoid());
}
@@ -581,22 +594,31 @@ namespace Spring.Aop.Framework
GoodCommand target = new GoodCommand();
NopInterceptor advice = new NopInterceptor();
IObjectFactory mock = (IObjectFactory)mocks.CreateMock(typeof(IObjectFactory));
Expect.Call(mock.IsSingleton("advice")).Return(true); // advice is a singleton...
Expect.Call(mock.GetObject("advice")).Return(advice);
Expect.Call(mock.GetType("prototype")).Return(typeof(GoodCommand));
Expect.Call(mock.GetObject("advice")).Return(advice);
Expect.Call(mock.GetObject("prototype")).Return(target);
mocks.ReplayAll();
MockRepository mocks = new MockRepository();
IObjectFactory factory = (IObjectFactory) mocks.CreateMock(typeof(IObjectFactory));
ProxyFactoryObject fac = new ProxyFactoryObject();
fac.ProxyInterfaces = new string[] { typeof(ICommand).FullName };
fac.IsSingleton = false;
fac.InterceptorNames = new string[] { "advice", "prototype" };
fac.ObjectFactory = mock;
fac.ObjectFactory = factory;
fac.GetObject();
// using (mocks.Record())
{
using (mocks.Unordered())
{
Expect.Call(factory.IsSingleton("advice")).Return(true);
Expect.Call(factory.GetObject("advice")).Return(advice);
Expect.Call(factory.GetType("prototype")).Return(target.GetType());
Expect.Call(factory.GetObject("prototype")).Return(target);
}
}
mocks.ReplayAll();
// using(mocks.Playback())
{
fac.GetObject();
}
mocks.VerifyAll();
}
@@ -633,7 +655,7 @@ namespace Spring.Aop.Framework
}
[Test]
public void SingletonProxyWithPrototypeTarget()
public void SingletonProxyWithPrototypeTargetCreatesTargetOnlyOnce()
{
try
{
@@ -651,7 +673,7 @@ namespace Spring.Aop.Framework
fac.InterceptorNames = new string[] { "advice", "prototype" };
fac.ObjectFactory = ctx;
Assert.AreEqual(1, InstantiationCountingCommand.NumberOfInstantiations, "First Call");
Assert.AreEqual(0, InstantiationCountingCommand.NumberOfInstantiations, "First Call");
fac.GetObject();
Assert.AreEqual(1, InstantiationCountingCommand.NumberOfInstantiations, "Second Call");
fac.GetObject();
@@ -685,8 +707,7 @@ namespace Spring.Aop.Framework
}
[Test]
[ExpectedException(typeof(AopConfigException))]
public void NullNameInInterceptorNamesArray()
public void NullNameInInterceptorNamesArrayThrowAopConfigException()
{
IObjectFactory factory = (IObjectFactory) mocks.CreateMock(typeof(IObjectFactory));
@@ -695,6 +716,13 @@ namespace Spring.Aop.Framework
fac.IsSingleton = false;
fac.InterceptorNames = new string[] { null, null };
fac.ObjectFactory = factory;
try
{
fac.GetObject();
Assert.Fail();
}
catch (AopConfigException)
{}
}
[Test]
@@ -843,7 +871,7 @@ namespace Spring.Aop.Framework
XmlObjectFactory objectFactory = new XmlObjectFactory(resource, null);
HelperInterface2 hc = (HelperInterface2)objectFactory.GetObject("MyProxy");
Console.WriteLine(hc.SecondDoSomething());
Console.WriteLine(hc.SecondDoSomething());
}
[Test]
@@ -899,7 +927,7 @@ namespace Spring.Aop.Framework
{
ProxyFactoryObject factoryObject = (ProxyFactoryObject) this.factory.GetObject( "&concurrentPrototype" );
Type testObjectType1 = factoryObject.GetObject().GetType();
factoryObject.Interfaces = new Type[] {};
Type testObjectType2 = factoryObject.GetObject().GetType();
@@ -1032,7 +1060,7 @@ namespace Spring.Aop.Framework
int GlobalsAdded { get; set; }
}
/// <summary> Use as a global interceptor. Checks that
/// <summary> Use as a global interceptor. Checks that
/// global interceptors can add aspect interfaces.
/// NB: Add only via global interceptors in XML file.
/// </summary>

View File

@@ -26,6 +26,7 @@ using AopAlliance.Aop;
using AopAlliance.Intercept;
using DotNetMock.Dynamic;
using NUnit.Framework;
using Rhino.Mocks;
using Spring.Aop.Interceptor;
using Spring.Aop.Support;
using Spring.Objects;

View File

@@ -25,7 +25,6 @@ using AopAlliance.Intercept;
using Spring.Aop.Framework.Adapter;
#endregion
namespace Spring.Aop
{
/// <summary>
@@ -33,6 +32,7 @@ namespace Spring.Aop
/// </summary>
/// <author>Dmitriy Kopylenko</author>
/// <author>Simon White (.NET)</author>
[Serializable]
public class SimpleBeforeAdviceAdapter : IAdvisorAdapter
{
#region IAdvisorAdapter Members