Castle实践9-在Castle IOC容器中使用AspectSharp(全面剖析AspectSharp Facility)
生活随笔
收集整理的這篇文章主要介紹了
Castle实践9-在Castle IOC容器中使用AspectSharp(全面剖析AspectSharp Facility)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在“Castle實踐8”介紹了A#的使用方法,那么A#如何和Castle IOC容器結合起來使用呢?在Castle的官方falicicies庫中,提供了AspectSharp Facility來讓我們可以很簡單在IOC中使用A#。我把使用方法放在最后,題目說了是要全面剖析這個facility的原理,借助這次分析讓我們對Castle IOC中的Falicity編寫有更深的了解。
??????? 編寫一個facility之前,最重要的就是要明確這個falicity的目的。通過“實踐8”知道,要使用一個aop過的對象,需要調用engine.WrapClass或者engine.WrapInterface來對目的對象包裝,那么得出這個facility的目的就是:當用戶向IOC容器請求組件的時候,根據aop的配置自動包裝組件再交給客戶使用。
??????? 明白了需求,那么就開始分析吧: protected?override?void?Init()
{
????if?(FacilityConfig?==?null)?return;
????//?第一步
????RegisterAspectEngine();
????//?第二步
????RegisterInterceptor();
????//?第三步
????Kernel.ProxyFactory?=?new?AopProxyFactory();
????//?第四步
????_engine?=?(AspectEngine)?Kernel[?typeof(AspectEngine)?];
????//?第五步:向IOC里面加入任何組件的時候,OnComponentRegistered會回調
????Kernel.ComponentRegistered?+=?new?ComponentDataDelegate(OnComponentRegistered);
}
第一步:
private?void?RegisterAspectEngine()
{
????//?獲取當前facility的配置,相當于獲取了a#的配置
????String?contents?=?FacilityConfig.Value;
????//?創建a#的builder
????AspectEngineBuilder?builder?=?new?AspectLanguageEngineBuilder(contents);
????ComponentModel?model?=?
????????new?ComponentModel("aspectsharp.engine",?
????????????typeof(AspectEngine),?typeof(AspectEngine));
????
????//?a#的builder作為擴張屬性
????model.ExtendedProperties.Add("builder",?builder);
????//?engine激活的時候執行AspectEngineActivator
????model.CustomComponentActivator?=?typeof(AspectEngineActivator);
????//?把a#?engine作為組件加入ioc中
????Kernel.AddCustomComponent(?model?);
}
第二步:
private?void?RegisterInterceptor()
{
????//?講AopInterceptor加入IOC中
????Kernel.AddComponent(?"aspectsharp.interceptor",?typeof(AopInterceptor)?);
}
第三步:注冊ioc的proxy工廠 ///?<summary>
///?Specialization?of?<see?cref="Castle.Windsor.Proxy.DefaultProxyFactory"/>
///?that?checks?for?aspects?in?the?model?and?potential?mixins.
///?</summary>
public?class?AopProxyFactory?:?DefaultProxyFactory
{
protected?override?void?CustomizeContext(GeneratorContext?context,?IKernel?kernel,?
????ComponentModel?model,?object[]?arguments)
{
????//?獲取a#的配置
????AspectDefinition?aspect?=?(AspectDefinition)?model.ExtendedProperties["aop.aspect"];
????if?(aspect?==?null)?return;
????//?得到所有mixin
????MixinDefinitionCollection?mixins?=?aspect.Mixins;
????foreach(MixinDefinition?definition?in?mixins)
????{
????????Type?mixinType?=?definition.TypeReference.ResolvedType;
????????
????????try
????????{
????????????//?創建一個minix對象并交給dynamicproxy,dynamicproxy產生proxy的時候會用到
????????????context.AddMixinInstance(?Activator.CreateInstance(?mixinType?)?);
????????}
????????catch(Exception?e)
????????{
????????????throw?new?ApplicationException("Could?not?instantiate?mixin?"?+?mixinType.FullName,?e);
????????}
????}
}
protected?override?void?CustomizeProxy(object?proxy,?GeneratorContext?context,?IKernel?kernel,?ComponentModel?model)
{
????//?獲取在上面的CustomizeContext函數中創建的mixin對象
????object[]?mixins?=?context.MixinsAsArray();
????//?所有實現了IProxyAware的mixin對象,都會把實際的代理set到里面交給客戶處理
????//在“Castle實踐8”中的SecurityMixin就是實現了IProxyAware的,在SecurityMixin類
????//上下文中可以任意使用proxy,這下明白了吧。
????for(int?i=0;?i?<?mixins.Length;?i++)
????{
????????object?mixin?=?mixins[i];
????????
????????if?(mixin?is?IProxyAware)
????????{
????????????(mixin?as?IProxyAware).SetProxy(proxy);
????????}
????}
}
第四步:激活a# engine,導致AspectEngineActivator執行 protected?override?object?InternalCreate()
{
????//?獲取a#的builder
????AspectEngineBuilder?builder?=?(AspectEngineBuilder)?
????????base.Model.ExtendedProperties["builder"];
????System.Diagnostics.Debug.Assert(?builder?!=?null?);
????//?創建engine
????return?builder.Build();
}
第五步:向IOC里面加入任何組件的時候,OnComponentRegistered會回調 private?void?OnComponentRegistered(String?key,?IHandler?handler)
{
????//?檢查a#配置中是否包含組件的“切面”
????//就是當前加入的這個組件是否需要aop(怎么說呢??表達不太清晰,大家應該明白吧。請原諒~~)
????AspectDefinition[]?aspects?=?
????????_engine.AspectMatcher.Match(?handler.ComponentModel.Implementation,?
????????_engine.Configuration.Aspects?);
????if?(aspects.Length?!=?0)
????{
????????//?如果組件需要aop,則合并配置中對此組件的切面定義
????????//并將定義加入到組件的擴張屬性中
????????handler.ComponentModel.ExtendedProperties["aop.aspect"]?=?Union(aspects);
????????//?向組件加入攔截器
????????//當向ioc請求組件對象的時候,攔截器的作用就是根據上面的定義來產生一個組件的proxy
????????handler.ComponentModel.Interceptors.Add(?
????????????new?InterceptorReference(?typeof(AopInterceptor)?)?);
????}
}
private?AspectDefinition?Union(AspectDefinition[]?aspects)
{
????//?這里作用是合并對組件的“切面”配置內容
????//但作者todo了,未完成?
????if?(aspects.Length?==?1)
????{
????????return?aspects[0];
????}
????//?TODO:?Merge?aspects
????return?aspects[0];
}
???????? 這時候回頭來看看,我們的目的是自動包裝,上面的代碼中沒有調用A# engine的WrapClass和WrapInterface的,其實兩個wrap做的是調用DefaultProxyFactory來產生代理的,這里給AopProxyFactory代替了。而真正請求一個組件的時候,產生代理的工作都是在AopInterceptor中處理的。
///?<summary>
///?Summary?description?for?AopInterceptor.
///?</summary>
[Transient]
public?class?AopInterceptor?:?IMethodInterceptor,?IOnBehalfAware
{
????private?IKernel?_kernel;
????private?AspectEngine?_engine;
????private?IInvocationDispatcher?_dispatcher;
????public?AopInterceptor(AspectEngine?engine,?IKernel?kernel)
????{
????????_engine?=?engine;
????????_kernel?=?kernel;
????}
????public?void?SetInterceptedComponentModel(ComponentModel?target)
????{
????????//?獲取組件的aop配置
????????AspectDefinition?aspectDef?=?(AspectDefinition)?
????????????target.ExtendedProperties["aop.aspect"];
????????System.Diagnostics.Debug.Assert(?aspectDef?!=?null?);
????????//?InvocationDispatcher用于proxy的方法分派,ContainerInvocationDispatcher重寫了
????????//ObtainInterceptorInstance方法,唯一的作用是:嘗試從IOC中獲取攔截器對象
????????_dispatcher?=?new?ContainerInvocationDispatcher(aspectDef,?_kernel);
????????_dispatcher.Init(_engine);
????}
????public?object?Intercept(IMethodInvocation?invocation,?params?object[]?args)
????{
????????//?a#內幕:_dispatcher.Intercept會處理客戶的函數調用
????????//Intercept方法會從ObtainInterceptorInstance獲取攔截器實例
????????//(ContainerInvocationDispatcher中重寫的方法起作用了)
????????//?如果沒有攔截器則直接Proceed,有攔截器則在攔截器進行處理
????????//這是a#攔截的一個簡單過程,詳細你可以參考:a#中的DefaultInvocationDispatcher源碼
????????return?_dispatcher.Intercept(?(IInvocation)?invocation,?args);
????}
}
而在ContainerInvocationDispatcher重寫的ObtainInterceptorInstance是這樣的:
///?<summary>
///?獲取攔截器對象
///?</summary>
protected?override?IMethodInterceptor?ObtainInterceptorInstance(Type?adviceType)
{
????if?(_kernel.HasComponent(?adviceType?))
????{
????????//?方式一:從IOC中獲取
????????//如果我們把攔截器注冊進IOC里面,這里就直接獲取
????????try
????????{
????????????return?(IMethodInterceptor)?_kernel[adviceType];
????????}
????????catch(InvalidCastException?ex)
????????{
????????????//?In?this?case,?the?specified?interceptor
????????????//?does?not?implement?the?IMethodInterceptor?from
????????????//?AopAlliance
????????????String?message?=?String.Format("The?interceptor?{0}?does?"?+?
????????????????"not?implement?AopAlliance.Interceptor.IMethodInterceptor",?adviceType.FullName);?
????????????throw?new?ApplicationException(message,?ex);
????????}
????}
????//?方式二:從A#的DefaultInvocationDispatcher中獲取
????//A#中對攔截器對象實例是有緩存處理的(一個HashTable:_type2AdviceInstance)
????return?base.ObtainInterceptorInstance(adviceType);
}
??????? 分析結束啦~ ,最后放上使用方法,很簡單的:
1)配置:
<configuration>
????<facilities>
????????<facility?id="aspectsharp">
<![CDATA[
import?AopDemo.Interceptors
import?AopDemo.Mixins
aspect?log?for?[AopDemo]
????pointcut?method(*)
????????advice(LoggerInterceptor)
????end
end
aspect?Security?for?[AopDemo]
????include?SecurityMixin
????pointcut?method(*)
????????advice(SecurityCheckInterceptor)
????end
end
]]>
????????</facility>
????</facilities>
</configuration>
2)初始化容器:
container?=?new?WindsorContainer(@"../../aspectsharp.ioc.xml");
container.AddFacility("aspectsharp",?new?AspectSharpFacility())?;
container.AddComponent("persondao",?typeof(PersonDao));
3)使用組件:
PersonDao?dao?=?container["persondao"]?as?PersonDao;
dao.Create("AAA");
...
完整demo下載地址:
http://www.wjshome.com/Income/Others/Castle.AspectSharp%20Facility.Demo.rar
bye~
??????? 編寫一個facility之前,最重要的就是要明確這個falicity的目的。通過“實踐8”知道,要使用一個aop過的對象,需要調用engine.WrapClass或者engine.WrapInterface來對目的對象包裝,那么得出這個facility的目的就是:當用戶向IOC容器請求組件的時候,根據aop的配置自動包裝組件再交給客戶使用。
??????? 明白了需求,那么就開始分析吧: protected?override?void?Init()
{
????if?(FacilityConfig?==?null)?return;
????//?第一步
????RegisterAspectEngine();
????//?第二步
????RegisterInterceptor();
????//?第三步
????Kernel.ProxyFactory?=?new?AopProxyFactory();
????//?第四步
????_engine?=?(AspectEngine)?Kernel[?typeof(AspectEngine)?];
????//?第五步:向IOC里面加入任何組件的時候,OnComponentRegistered會回調
????Kernel.ComponentRegistered?+=?new?ComponentDataDelegate(OnComponentRegistered);
}
第一步:
private?void?RegisterAspectEngine()
{
????//?獲取當前facility的配置,相當于獲取了a#的配置
????String?contents?=?FacilityConfig.Value;
????//?創建a#的builder
????AspectEngineBuilder?builder?=?new?AspectLanguageEngineBuilder(contents);
????ComponentModel?model?=?
????????new?ComponentModel("aspectsharp.engine",?
????????????typeof(AspectEngine),?typeof(AspectEngine));
????
????//?a#的builder作為擴張屬性
????model.ExtendedProperties.Add("builder",?builder);
????//?engine激活的時候執行AspectEngineActivator
????model.CustomComponentActivator?=?typeof(AspectEngineActivator);
????//?把a#?engine作為組件加入ioc中
????Kernel.AddCustomComponent(?model?);
}
第二步:
private?void?RegisterInterceptor()
{
????//?講AopInterceptor加入IOC中
????Kernel.AddComponent(?"aspectsharp.interceptor",?typeof(AopInterceptor)?);
}
第三步:注冊ioc的proxy工廠 ///?<summary>
///?Specialization?of?<see?cref="Castle.Windsor.Proxy.DefaultProxyFactory"/>
///?that?checks?for?aspects?in?the?model?and?potential?mixins.
///?</summary>
public?class?AopProxyFactory?:?DefaultProxyFactory
{
protected?override?void?CustomizeContext(GeneratorContext?context,?IKernel?kernel,?
????ComponentModel?model,?object[]?arguments)
{
????//?獲取a#的配置
????AspectDefinition?aspect?=?(AspectDefinition)?model.ExtendedProperties["aop.aspect"];
????if?(aspect?==?null)?return;
????//?得到所有mixin
????MixinDefinitionCollection?mixins?=?aspect.Mixins;
????foreach(MixinDefinition?definition?in?mixins)
????{
????????Type?mixinType?=?definition.TypeReference.ResolvedType;
????????
????????try
????????{
????????????//?創建一個minix對象并交給dynamicproxy,dynamicproxy產生proxy的時候會用到
????????????context.AddMixinInstance(?Activator.CreateInstance(?mixinType?)?);
????????}
????????catch(Exception?e)
????????{
????????????throw?new?ApplicationException("Could?not?instantiate?mixin?"?+?mixinType.FullName,?e);
????????}
????}
}
protected?override?void?CustomizeProxy(object?proxy,?GeneratorContext?context,?IKernel?kernel,?ComponentModel?model)
{
????//?獲取在上面的CustomizeContext函數中創建的mixin對象
????object[]?mixins?=?context.MixinsAsArray();
????//?所有實現了IProxyAware的mixin對象,都會把實際的代理set到里面交給客戶處理
????//在“Castle實踐8”中的SecurityMixin就是實現了IProxyAware的,在SecurityMixin類
????//上下文中可以任意使用proxy,這下明白了吧。
????for(int?i=0;?i?<?mixins.Length;?i++)
????{
????????object?mixin?=?mixins[i];
????????
????????if?(mixin?is?IProxyAware)
????????{
????????????(mixin?as?IProxyAware).SetProxy(proxy);
????????}
????}
}
第四步:激活a# engine,導致AspectEngineActivator執行 protected?override?object?InternalCreate()
{
????//?獲取a#的builder
????AspectEngineBuilder?builder?=?(AspectEngineBuilder)?
????????base.Model.ExtendedProperties["builder"];
????System.Diagnostics.Debug.Assert(?builder?!=?null?);
????//?創建engine
????return?builder.Build();
}
第五步:向IOC里面加入任何組件的時候,OnComponentRegistered會回調 private?void?OnComponentRegistered(String?key,?IHandler?handler)
{
????//?檢查a#配置中是否包含組件的“切面”
????//就是當前加入的這個組件是否需要aop(怎么說呢??表達不太清晰,大家應該明白吧。請原諒~~)
????AspectDefinition[]?aspects?=?
????????_engine.AspectMatcher.Match(?handler.ComponentModel.Implementation,?
????????_engine.Configuration.Aspects?);
????if?(aspects.Length?!=?0)
????{
????????//?如果組件需要aop,則合并配置中對此組件的切面定義
????????//并將定義加入到組件的擴張屬性中
????????handler.ComponentModel.ExtendedProperties["aop.aspect"]?=?Union(aspects);
????????//?向組件加入攔截器
????????//當向ioc請求組件對象的時候,攔截器的作用就是根據上面的定義來產生一個組件的proxy
????????handler.ComponentModel.Interceptors.Add(?
????????????new?InterceptorReference(?typeof(AopInterceptor)?)?);
????}
}
private?AspectDefinition?Union(AspectDefinition[]?aspects)
{
????//?這里作用是合并對組件的“切面”配置內容
????//但作者todo了,未完成?
????if?(aspects.Length?==?1)
????{
????????return?aspects[0];
????}
????//?TODO:?Merge?aspects
????return?aspects[0];
}
???????? 這時候回頭來看看,我們的目的是自動包裝,上面的代碼中沒有調用A# engine的WrapClass和WrapInterface的,其實兩個wrap做的是調用DefaultProxyFactory來產生代理的,這里給AopProxyFactory代替了。而真正請求一個組件的時候,產生代理的工作都是在AopInterceptor中處理的。
///?<summary>
///?Summary?description?for?AopInterceptor.
///?</summary>
[Transient]
public?class?AopInterceptor?:?IMethodInterceptor,?IOnBehalfAware
{
????private?IKernel?_kernel;
????private?AspectEngine?_engine;
????private?IInvocationDispatcher?_dispatcher;
????public?AopInterceptor(AspectEngine?engine,?IKernel?kernel)
????{
????????_engine?=?engine;
????????_kernel?=?kernel;
????}
????public?void?SetInterceptedComponentModel(ComponentModel?target)
????{
????????//?獲取組件的aop配置
????????AspectDefinition?aspectDef?=?(AspectDefinition)?
????????????target.ExtendedProperties["aop.aspect"];
????????System.Diagnostics.Debug.Assert(?aspectDef?!=?null?);
????????//?InvocationDispatcher用于proxy的方法分派,ContainerInvocationDispatcher重寫了
????????//ObtainInterceptorInstance方法,唯一的作用是:嘗試從IOC中獲取攔截器對象
????????_dispatcher?=?new?ContainerInvocationDispatcher(aspectDef,?_kernel);
????????_dispatcher.Init(_engine);
????}
????public?object?Intercept(IMethodInvocation?invocation,?params?object[]?args)
????{
????????//?a#內幕:_dispatcher.Intercept會處理客戶的函數調用
????????//Intercept方法會從ObtainInterceptorInstance獲取攔截器實例
????????//(ContainerInvocationDispatcher中重寫的方法起作用了)
????????//?如果沒有攔截器則直接Proceed,有攔截器則在攔截器進行處理
????????//這是a#攔截的一個簡單過程,詳細你可以參考:a#中的DefaultInvocationDispatcher源碼
????????return?_dispatcher.Intercept(?(IInvocation)?invocation,?args);
????}
}
而在ContainerInvocationDispatcher重寫的ObtainInterceptorInstance是這樣的:
///?<summary>
///?獲取攔截器對象
///?</summary>
protected?override?IMethodInterceptor?ObtainInterceptorInstance(Type?adviceType)
{
????if?(_kernel.HasComponent(?adviceType?))
????{
????????//?方式一:從IOC中獲取
????????//如果我們把攔截器注冊進IOC里面,這里就直接獲取
????????try
????????{
????????????return?(IMethodInterceptor)?_kernel[adviceType];
????????}
????????catch(InvalidCastException?ex)
????????{
????????????//?In?this?case,?the?specified?interceptor
????????????//?does?not?implement?the?IMethodInterceptor?from
????????????//?AopAlliance
????????????String?message?=?String.Format("The?interceptor?{0}?does?"?+?
????????????????"not?implement?AopAlliance.Interceptor.IMethodInterceptor",?adviceType.FullName);?
????????????throw?new?ApplicationException(message,?ex);
????????}
????}
????//?方式二:從A#的DefaultInvocationDispatcher中獲取
????//A#中對攔截器對象實例是有緩存處理的(一個HashTable:_type2AdviceInstance)
????return?base.ObtainInterceptorInstance(adviceType);
}
??????? 分析結束啦~ ,最后放上使用方法,很簡單的:
1)配置:
<configuration>
????<facilities>
????????<facility?id="aspectsharp">
<![CDATA[
import?AopDemo.Interceptors
import?AopDemo.Mixins
aspect?log?for?[AopDemo]
????pointcut?method(*)
????????advice(LoggerInterceptor)
????end
end
aspect?Security?for?[AopDemo]
????include?SecurityMixin
????pointcut?method(*)
????????advice(SecurityCheckInterceptor)
????end
end
]]>
????????</facility>
????</facilities>
</configuration>
2)初始化容器:
container?=?new?WindsorContainer(@"../../aspectsharp.ioc.xml");
container.AddFacility("aspectsharp",?new?AspectSharpFacility())?;
container.AddComponent("persondao",?typeof(PersonDao));
3)使用組件:
PersonDao?dao?=?container["persondao"]?as?PersonDao;
dao.Create("AAA");
...
完整demo下載地址:
http://www.wjshome.com/Income/Others/Castle.AspectSharp%20Facility.Demo.rar
bye~
轉載于:https://www.cnblogs.com/laiwen/archive/2005/09/07/231651.html
總結
以上是生活随笔為你收集整理的Castle实践9-在Castle IOC容器中使用AspectSharp(全面剖析AspectSharp Facility)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Net中如何操作IIS
- 下一篇: CodeProject 工具收藏