javascript
把Autofac玩的和java Spring一样6
大家好,今天來介紹我開源的一個(gè)autofac.Annotation項(xiàng)目 源碼:https://github.com/yuzd/Autofac.Annotation
本項(xiàng)目是autofa的一個(gè)擴(kuò)展組件,autofac是一個(gè)老牌的DI容器框架 ,支持netframework和netcore
Annotdation是注解的意思,在java項(xiàng)目里面 注解的概念和 csharp里面的 Attribute 的概念是一樣的。
本項(xiàng)目的目的 降低玩DI容器的門檻,快速實(shí)現(xiàn)依賴注入 自動(dòng)裝配 以及攔截器,AOP切面編程
基于參考 Java的 Spring注解方式開發(fā)思想,
所有autofac容器的注冊(cè) 和 裝配 都是依賴標(biāo)簽來完成。
這樣一來 一方面很容易分清楚 哪些是DI 哪些非DI, 哪些是攔截器,哪些需要攔截器,輕松實(shí)現(xiàn)切面編程, 代碼也好看,吸收java的spring框架的優(yōu)越的地方,配合.net語法的優(yōu)越性,編程效率能夠大大提升。
支持的標(biāo)簽一覽
| AutoConfiguration | 打在class上面 | 自動(dòng)裝配class里面帶有Bean標(biāo)簽的方法 |
| Bean | 打在方法上面 | 配合AutoConfiguration標(biāo)簽使用 |
| Component | 打在class上面 | 自動(dòng)注冊(cè) |
| Autowired | 打在構(gòu)造方法的Parameter,類的Property,類的Field | 自動(dòng)裝配 |
| PropertySource | 打在class上面 | 配合Value標(biāo)簽使用,設(shè)置Value的數(shù)據(jù)源,支持json,xml,支持資源內(nèi)嵌 |
| Value | 打在構(gòu)造方法的Parameter,類的Property,類的Field | 靜態(tài)數(shù)據(jù)裝配,支持強(qiáng)大的EL表達(dá)式 |
| Aspect | 打在class上面 | 開啟攔截器,默認(rèn)注冊(cè)為類攔截器,也可以指定為接口型攔截器(和pointcut的區(qū)別是它是打在哪個(gè)class哪個(gè)才會(huì)生效) |
| Pointcut | 打在class上面 | 切面配置,一個(gè)切面攔截N多個(gè)對(duì)象 |
針對(duì)每個(gè)標(biāo)簽的使用文檔 請(qǐng)移步wiki文檔傳送門
https://github.com/yuzd/Autofac.Annotation/wiki
?
下面介紹一下最最常用的功能也就是注冊(cè)和自動(dòng)裝配
?
Componet標(biāo)簽把類型注冊(cè)到DI容器
原理解釋
框架會(huì)掃描打了Componet標(biāo)簽的class。如果Componet標(biāo)簽里面指定了要注冊(cè)的類型,則會(huì)只注冊(cè)為這個(gè)類型到DI容器。如果沒有指定則會(huì)把當(dāng)前class(參考下面的4),以及父類,以及接口都會(huì)注冊(cè)到DI容器(參考下面的1,2和3)。
如何修改這個(gè)默認(rèn)配置呢,比如關(guān)閉自動(dòng)注冊(cè)父類和接口。可以參考 https://github.com/yuzd/Autofac.Annotation/issues/11
Componet有哪些屬性
| Service | Type | 注冊(cè)指定單個(gè)的類型 |
| Key | String | 注冊(cè)指定單個(gè)的key(為了同個(gè)類型注冊(cè)多次避免歧義) |
| Services | Type[] | 注冊(cè)指定多個(gè)的類型 |
| Keys | String[] | 注冊(cè)指定多個(gè)的key(如果指定多個(gè)類型又想避免歧義可以搭配上面一起使用) |
| AutofacScope | Enum | InstancePerDependency(每次都是一個(gè)新實(shí)例,默認(rèn)) SingleInstance(單例) InstancePerLifetimeScope(每個(gè)scope獲取新的實(shí)例) InstancePerRequest(根據(jù)每個(gè)請(qǐng)求一個(gè)實(shí)例) 可以在插件初始化的時(shí)候指定一個(gè)默認(rèn)的 參考下方的截圖說明 |
| AutoActivate | bool | 當(dāng)指定Scope為單例的時(shí)候 默認(rèn)false 當(dāng)DI容器初始化完成后會(huì)自動(dòng)完成實(shí)例化 |
| InitMethod | string | 當(dāng)實(shí)例化后自動(dòng)執(zhí)行的方法名稱 |
| DestroyMethod | string | 當(dāng)實(shí)例會(huì)DI容器回收會(huì)自動(dòng)執(zhí)行的方法名稱 |
| Ownership | Enum | LifetimeScope(DI容器管理自動(dòng)回收策略,默認(rèn))External(自己手動(dòng)管理實(shí)例回收) |
| Interceptor | Type | 指定攔截器類型 |
| InterceptorType | Enum | Interface(使用接口模式) Class(使用class的虛方法模式) |
| InterceptorKey | string | 如果同一個(gè)類型的攔截器有多個(gè) 可以指定Key |
| InjectPropertyType | Enum | 屬性自動(dòng)裝配的類型 ,Autowired(代表打了Autowired標(biāo)簽的才會(huì)裝配),All(代表全部自動(dòng)裝配) |
Componet的常用構(gòu)造方法
默認(rèn)的構(gòu)造方法
注冊(cè)為指定類型
同一個(gè)注冊(cè)類型有多個(gè) 采用Key方式解決歧義
1. 把一個(gè)類型注冊(cè)到DI容器
上面的例子就是把Student類型注冊(cè)到容器
2. 把當(dāng)前類型和父類注冊(cè)到DI容器
上面的例子就是把Student2類型注冊(cè)到容器
并且把Person類型也注冊(cè)到容器根據(jù)Person類型拿到的是Student2的實(shí)體
3. 把當(dāng)前類型和接口注冊(cè)到DI容器
上面的例子就是把Student3類型注冊(cè)到容器
并且把ISay也注冊(cè)到容器根據(jù)ISay類型拿到的是Student3的實(shí)體
4. 當(dāng)繼承了父類或者接口 想要指定注冊(cè)類型怎么辦?
上面的例子就是只能通過ISay拿到Student3的實(shí)體
不能通過Student3類型拿到!!
5. 怎么指定實(shí)例是單例,每次都是新的實(shí)例,還是每個(gè)Scope一個(gè)實(shí)例呢?
如上圖所示 可以指定AutofacScope屬性
如果不指定就是每次獲取的一個(gè)新的實(shí)例
6. 當(dāng)同一個(gè)類型多次注冊(cè),如何區(qū)分得到我想要的?
如上圖 ISay類型有2個(gè)實(shí)現(xiàn)類 Student3 和 Student4 分別指定了 Key的值
通過ISay + “Student3” 可以獲取到 Student3的實(shí)體
通過ISay + “Student4” 可以獲取到 Student4的實(shí)體
7.支持注冊(cè)類型可以自動(dòng)實(shí)例化對(duì)象
如上所示,設(shè)定AutoActivate = true代表是啟動(dòng)自動(dòng)實(shí)例化
AutofacScope = AutofacScope.SingleInstance 代表單例模式
Student5類型會(huì)對(duì)象會(huì)自動(dòng)實(shí)例化 并且以單例的方式存儲(chǔ)在DI容器內(nèi)
8.支持設(shè)置實(shí)例化時(shí)運(yùn)行指定方法
如上所示 設(shè)置 InitMethod 和 DestroyMethod
當(dāng)實(shí)例從DI容器初始化時(shí)就會(huì)調(diào)用 InitMethod
當(dāng)DI容器Dispose的時(shí)候會(huì)觸發(fā)調(diào)用DestroyMethod
另外
InitMethod支持注入
DestroyMethod只能是無參數(shù)方法
Autowired自動(dòng)裝配
Autowired有哪些屬性
| Name | String | 搭配Component指定Key的時(shí)候使用,消除一個(gè)類型被多個(gè)注冊(cè)帶來的歧義 |
| Required | bool | 默認(rèn)裝載失敗會(huì)報(bào)錯(cuò) 設(shè)置為false裝載失敗不會(huì)報(bào)錯(cuò) |
| CircularDependencies | bool | 是否支持循環(huán)注入 默認(rèn)是false 不支持,插件初始化的時(shí)候可以設(shè)置一個(gè)默認(rèn)值 |
?
打在構(gòu)造方法上 屬性
在單例的對(duì)象里面Autowired多實(shí)例
使用ObjectFactory來實(shí)現(xiàn),和Lazy的區(qū)別是 ObjectFactory修飾的每次獲取都是從容器里面獲取一遍。而Lazy只有首次才會(huì)去容器獲取。
延遲自動(dòng)裝配Lazy
[Component] public class TestLazyModel1 {[Autowired]public Lazy<TestAutowiredModal4> TestAutowiredModal4 { get; set; }[Autowired]public TestAutowiredModal3 TestAutowiredModal3 { get; set; } }總結(jié)
以上是生活随笔為你收集整理的把Autofac玩的和java Spring一样6的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 编写第一个 .NET 微服务
- 下一篇: 译 | 将数据从Cosmos DB迁移到