第九回(hui) Microsoft.Practices.Unity.Interception實現(xian)基于數(shu)據(ju)集的(de)緩存(cun)(針對六,七,八講的(de)具(ju)體(ti)概念(nian)和配(pei)置的(de)解說(shuo))
概念
Microsoft.Practices.Unity.Interception是一(yi)個攔截器,它隸屬于Microsoft.Practices.Unity組成之中,主要(yao)(yao)完成AOP的(de)功能,而實現AOP方(fang)法(fa)攔截(頁向切面)的(de)基(ji)礎就是IoC,我們需要(yao)(yao)配置相關接口或者類型的(de)IoC方(fang)式,然后在生(sheng)(sheng)產對象(xiang)時,使用Unity的(de)方(fang)法(fa)進行(xing)動態(tai)生(sheng)(sheng)產對象(xiang),這時,你的(de)Interception攔截器也會起作用!
相關技術
IoC: 控(kong)制反轉(zhuan)(Inversion of Control,英文(wen)縮寫為(wei)IoC)是一個重要(yao)的(de)的(de)法(fa)則(ze)來(lai)削減計(ji)算機程(cheng)序(xu)的(de)耦(ou)合問題。 控(kong)制反轉(zhuan)一般又(you)被(bei)稱為(wei)依賴注入(Dependency Injection,簡稱)。即將配置中的(de)對(dui)象,動態(tai)注入到項目(mu)程(cheng)序(xu)當中,使(shi)程(cheng)序(xu)的(de)某個功能可(ke)以動態(tai)進行切換(huan)。
AOP: (也叫面(mian)向方面(mian)編程):Aspect Oriented Programming(AOP),是中的一個熱(re)點。利用AOP可以對(dui)業務(wu)邏(luo)輯(ji)的各(ge)(ge)個部分進行隔離(li),從而使得業務(wu)邏(luo)輯(ji)各(ge)(ge)部分之間的降(jiang)低,提(ti)高(gao)程序的可重用性(xing),同(tong)時(shi)提(ti)高(gao)了開(kai)發的效率。
一(yi)般(ban)用(yong)它(ta)來(lai)實現(xian):日志記錄,性(xing)能統計,安全控制,事務處理(li),等(deng)等(deng)。
持久化方式
目前我的Project.UnityCaching組件(jian)支持(chi)Microsoft.Practices.EnterpriseLibrary.Caching和Redis兩種數據持(chi)久化(hua)的方式,前者也是(shi)Microsoft.Practices. EnterpriseLibrary企業庫的一部(bu)分,主(zhu)要(yao)實(shi)現內存持(chi)久化(hua)(也可以實(shi)現文件(jian)持(chi)久化(hua)),主(zhu)要(yao)用(yong)在單(dan)臺WEB服務器上;后者可以單(dan)獨部(bu)署(shu)到一臺或者多臺服務器上,主(zhu)要(yao)實(shi)現分布式緩存,它是(shi)未來(lai)的大數據的一個方向。
鍵名組成
緩存解決方案名_命名空間_方法名,其(qi)中緩存解決方案(an)名(ming)可以(yi)自(zi)己去配置,對(dui)應(ying)config中的CacheProjectName節點,而鍵(jian)對(dui)應(ying)的值采(cai)用字(zi)典(dian)類(lei)型,字(zi)典(dian)的鍵(jian)對(dui)應(ying)方法的各(ge)參數的組合。
涉及到的相關程序集
IoC基礎庫程序集
Redis基礎庫程序集
Project.Frameworks自(zi)封裝程序(xu)集
配置文件中進行對IoC,AoP的配置
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
<section name="cachingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Caching.Configuration.CacheManagerSettings, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
<section name="RedisConfig" type="Redis.Client.RedisConfigInfo, Redis.Client"/>
</configSections>
<RedisConfig WriteServerList="127.0.0.1:6379" ReadServerList="127.0.0.1:6379" MaxWritePoolSize="60" MaxReadPoolSize="60" AutoStart="true" LocalCacheTime="180" RecordeLog="false">
</RedisConfig>
<cachingConfiguration defaultCacheManager="ByteartRetailCacheManager">
<cacheManagers>
<add name="ByteartRetailCacheManager" type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" expirationPollFrequencyInSeconds="600" maximumElementsInCacheBeforeScavenging="1000" numberToRemoveWhenScavenging="10" backingStoreName="NullBackingStore" />
<!--
expirationPollFrequencyInSeconds:過期時(shi)間(seconds)
maximumElementsInCacheBeforeScavenging:緩沖(chong)中的(de)最大元素數(shu)(shu)量
numberToRemoveWhenScavenging:一(yi)次移除(chu)的(de)數(shu)(shu)量
-->
</cacheManagers>
<backingStores>
<add type="Microsoft.Practices.EnterpriseLibrary.Caching.BackingStoreImplementations.NullBackingStore, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="NullBackingStore" />
</backingStores>
</cachingConfiguration>
<unity xmlns="//schemas.microsoft.com/practices/2010/unity">
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration" />
<container>
<!--泛型類型注入,數據倉儲服務注入,可以由ef,linq,ado,memory,file,nosql等方式實現-->
<register type="IRepository.Core.IUnitOfWork,IRepository.Core" mapTo="NLayer_IoC_Demo.Entity.backgroundTestIoCEntities,NLayer_IoC_Demo.Entity" />
<!--使用redis作為持久化存儲-->
<!--<register type="IRepository.Core.IRepository`1,IRepository.Core" mapTo="Redis.Data.Core.RedisRepository`1,Redis.Data.Core" />-->
<!--使用SQLSERVER作為持久化存儲-->
<register type="IRepository.Core.IRepository`1,IRepository.Core" mapTo="NLayer_IoC_Demo.DATA.backgroundRepositoryBase`1,NLayer_IoC_Demo.DATA" />
<register type="IRepository.Core.IExtensionRepository`1,IRepository.Core" mapTo="NLayer_IoC_Demo.DATA.backgroundRepositoryBase`1,NLayer_IoC_Demo.DATA" />
<!-- AOP注入 -->
<extension type="Interception" />
<register type="NLayer_IoC_Demo.BLL.IUserService,NLayer_IoC_Demo.BLL" mapTo="NLayer_IoC_Demo.BLL.UserService,NLayer_IoC_Demo.BLL" >
<!--接口攔截-->
<interceptor type="InterfaceInterceptor" />
<!--緩存注入-->
<interceptionBehavior type="Project.UnityCaching.CachingBehavior,Project.UnityCaching"/>
</register>
<register type="NLayer_IoC_Demo.BLL.OrderService,NLayer_IoC_Demo.BLL" >
<!--接口攔截-->
<interceptor type="VirtualMethodInterceptor" />
<!--虛方法注入,生成派生類進行攔截,讓我們省去了建立接口的時間,不錯的選擇-->
<!--Transparent Proxy Interceptor -->
<!--它是注入所有的virutal method ,method,interface,但它的性能太差了-->
<!--緩存注入-->
<interceptionBehavior type="Project.UnityCaching.CachingBehavior,Project.UnityCaching"/>
</register>
<register type="Project.InterceptionBehaviors.IHandle, Project.InterceptionBehaviors" mapTo="Project.InterceptionBehaviors.StandardHandle, Project.InterceptionBehaviors">
<!--接口攔截-->
<interceptor type="InterfaceInterceptor" />
<interceptionBehavior type="NLayer_IoC_Demo.BLL.AOP.LoggerBehavior,NLayer_IoC_Demo.BLL" />
</register>
</container>
</unity>
<connectionStrings>
<add name="backgroundTestIoCEntities" connectionString="metadata=res://*/background.csdl|res://*/background.ssdl|res://*/background.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=backgroundTestIoC;persist security info=True;user id=sa;password=zzl123;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-NLayer_IoC_Demo-20141024091423;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-NLayer_IoC_Demo-20141024091423.mdf" providerName="System.Data.SqlClient" />
</connectionStrings>
使用時的相關注意要點
- Unity組件中引入了服務定位器ServiceLocator的概念,它可以使我們不引用目標程序集,而自動在bin目錄自動去定位。
- 對于Redis方式的緩存來說,進行緩存的實體類需要被聲明為Serializable特性。
- 實現IoC,AoP時,只引用需要的程序集,而不用將所有Microsoft.Practices.Unity組件都引入,在程序進行編譯時,這些需要的程序集會自動添加到UI項目的BIN目錄。
- 方法攔截這塊有三種,但TransparentProxyInterceptor由于性能太差,我們并不提倡使用,項目中我們主要使用VirtualMethodInterceptor對于虛方法的攔截和InterfaceInterceptor對于接口的攔截,兩種方式各有好處,如果實現方式比較單一,可以直接使用虛方法注入,這樣可以省去寫接口的代碼量。