天天看點

AOP 還在配置嗎改用打标簽模式吧!

為什麼我喜歡打标簽來配置AOP

1. 配置多很混亂,代碼裡面很難分辨出來哪些是AOP容器(比如屬性注入)

2. 對于代碼生成器生成的代碼裡面還需要手動加到配置裡面

3. 連java spring現在都是清一色的注解來代替xml,這個就是趨勢所在

我基于Autofac開發了一個基于标簽來配置AOP的擴充

NUGET :Install-Package Autofac.Annotation

開源位址:

https://github.com/yuzd/Autofac.Annotation

幫忙點個star 謝謝!

特色

1.打個Bean标簽就能注入到AOP

2.打個Autowired标簽自動裝配注入

3.打個Value标簽自動注入配置值(Soure标簽配合使用)具體使用方法看下面的例子

4.支援攔截器

5.更多等你發現

如何使用

var builder = new ContainerBuilder();

// 注冊autofac打标簽模式
builder.RegisterModule(new AutofacAnnotationModule(typeof(AnotationTest).Assembly));
//如果需要開啟支援循環注入
//builder.RegisterModule(new AutofacAnnotationModule(typeof(AnotationTest).Assembly).SetAllowCircularDependencies(true));
var container = builder.Build();
var serviceB = container.Resolve<B>();      

AutofacAnnotationModule有兩種構造方法

  1. 可以傳一個Assebly清單 (這種方式會注冊傳入的Assebly裡面打了标簽的類)
  2. 可以傳一個AsseblyName清單 (這種方式是先會根據AsseblyName查找Assebly 然後在注冊)

支援的标簽說明

Bean标簽

說明:隻能打在class上面 把某個類注冊到autofac容器 例如:

1.無構造方法的方式 等同于 builder.RegisterType();

//把class A 注冊到容器
[Bean]
public class A
{
    public string Name { get; set; }
}      

2.指定Scope [需要指定AutofacScope屬性 如果不指定為則預設為AutofacScope.InstancePerDependency]

[Bean(AutofacScope = AutofacScope.SingleInstance)]
    public class A
    {
        public string Name { get; set; }
    }      

3.指定類型注冊 等同于 builder.RegisterType().As()

public class B
    {

    }
    //将class A6以父類B注冊到容器
    [Bean(typeof(B))]
    public class A6:B
    {

    }      

4.指定名字注冊 等同于 builder.RegisterType().Keyed("a4")

[Bean("a4")]//注冊A4到容器 并給他起了一個名字叫a4 假設容器有多個A4被注冊就可以用這個名字來差別自動裝配
    public class A4
    {
        public string School { get; set; } = "測試2";
    }      

5.其他屬性說明

  • InjectProperties 是否預設裝配屬性 【預設為true】
  • InjectPropertyType 屬性自動裝配的類型
  1. Autowired 【預設值】代表打了Autowired标簽的才會自動裝配
  2. ALL 代表會裝配所有 等同于 builder.RegisterType().PropertiesAutowired()
  • AutoActivate 【預設為false】 如果為true代表autofac build完成後會自動建立 具體請參考 autofac官方文檔
  • Ownership 【預設為空】 具體請參考 autofac官方文檔
  • Interceptor 【預設為空】指定攔截器的Type
  • InterceptorType 攔截器類型 攔截器必須實作 Castle.DynamicProxy的 IInterceptor 接口, 有以下兩種
  1. Interface 【預設值】代表是接口型
  2. Class 代表是class類型 這種的話是需要将要攔截的方法标virtual
  • InterceptorKey 如果同一個類型的攔截器有多個 可以指定Key
  • InitMethod 當執行個體被建立後執行的方法名稱 類似Spring的init-method 可以是有參數(隻能1個參數類型是IComponentContext)和無參數的方法
  • DestroyMetnod 當執行個體被Release時執行的方法 類似Spring的destroy-method 必須是無參數的方法
[Bean(InitMethod = "start",DestroyMetnod = "destroy")]
    public class A30
    {
        [Value("aaaaa")]
        public string Test { get; set; }

        public A29 a29;

        void start(IComponentContext context)
        {
            this.Test = "bbbb";
            a29 = context.Resolve<A29>();
        }

        void destroy()
        {
            this.Test = null;
            a29.Test = null;
        }
    }
          
public class B
    {

    }
    
    [Bean(typeof(B),"a5")]
    public class A5:B
    {
        public string School { get; set; } = "測試a5";
        public override string GetSchool()
        {
            return this.School;
        }
    }      

Autowired 自動裝配

可以打在Field Property 構造方法的Parameter上面 其中Field 和 Property 支援在父類

[Bean]
    public class A16
    {
    public A16([Autowired]A21 a21)
        {
            Name = name;
            A21 = a21;
        }
        
        [Autowired("A13")]
        public B b1;


        [Autowired]
        public B B { get; set; }
        
    //Required預設為true 如果裝載錯誤會抛異常出來。如果指定為false則不抛異常
    [Autowired("adadada",Required = false)]
        public B b1;
    }      

Value 和 PropertySource

PropertySource類似Spring裡面的PropertySource 可以指定資料源 支援 xml json格式 支援内嵌資源

1.json格式的檔案

{
  "a10": "aaaaaaaaa1",
  "list": [ 1, 2, 3 ],
  "dic": {
    "name": "name1"
  },
  "testInitField": 1,
  "testInitProperty": 1,
}      
[Bean]
    [PropertySource("/file/appsettings1.json")]
    public class A10
    {
        public A10([Value("#{a10}")]string school,[Value("#{list}")]List<int> list,[Value("#{dic}")]Dictionary<string,string> dic)
        {
            this.School = school;
            this.list = list;
            this.dic = dic;

        }
        public string School { get; set; }
        public List<int> list { get; set; } 
        public Dictionary<string,string> dic { get; set; } 
        
    [Value("#{testInitField}")]
        public int test;
        
    [Value("#{testInitProperty}")]
        public int test2 { get; set; }
        
    //可以直接指定值
    [Value("2")]
    public int test3 { get; set; }
    }      

2. xml格式的檔案

<?xml version="1.0" encoding="utf-8" ?>
<autofac>
  <a11>aaaaaaaaa1</a11>
  <list name="0">1</list>
  <list name="1">2</list>
  <list name="2">3</list>
  <dic name="name">name1</dic>
</autofac>      
[Bean]
    [PropertySource("/file/appsettings1.xml")]
    public class A11
    {
        public A11([Value("#{a11}")]string school,[Value("#{list}")]List<int> list,[Value("#{dic}")]Dictionary<string,string> dic)
        {
            this.School = school;
            this.list = list;
            this.dic = dic;

        }
        public string School { get; set; }
        public List<int> list { get; set; } 
        public Dictionary<string,string> dic { get; set; } 
    }      

3.不指定PropertySource的話會預設從工程目錄的 appsettings.json擷取值

如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”将是我最大的寫作動力!歡迎各位轉載,轉載文章之後須在文章頁面明顯位置給出作者和原文連接配接,謝謝。