为什么我喜欢打标签来配置 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 有两种构造方法
可以传一个 Assebly 列表 (这种方式会注册传入的 Assebly 里面打了标签的类)
可以传一个 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 属性自动装配的类型
Autowired [默认值] 代表打了 Autowired 标签的才会自动装配
ALL 代表会装配所有 等同于 builder.RegisterType().PropertiesAutowired()
AutoActivate [默认为 false] 如果为 true 代表 autofac build 完成后会自动创建 具体请参考 autofac 官方文档
Ownership [默认为空] 具体请参考 autofac 官方文档
Interceptor [默认为空] 指定拦截器的 Type
InterceptorType 拦截器类型 拦截器必须实现 Castle.DynamicProxy 的 IInterceptor 接口, 有以下两种
Interface [默认值] 代表是接口型
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 获取值
来源: https://www.cnblogs.com/yudongdong/p/10285392.html