synced AdvisedSupport with Spring/J
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -169,7 +169,7 @@ namespace Spring.Aop.Framework
|
||||
/// </remarks>
|
||||
public virtual bool IsFrozen
|
||||
{
|
||||
get { return frozen; }
|
||||
get { return this.frozen; }
|
||||
set { this.frozen = value; }
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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).
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user