Autofac详解

Autofac详解可以在不修改方法的前提下 在方法前后添加公共逻辑 日志 异常 缓存等注入的时候通过构造函数或者属性注入 autofac 上下文实例 再根据名称创建对应实例 作者 李宥小哥来源 CSDN 原文 https blog csdn net liyou article details 版权声明 本文为作者原创文章

Autofac详解

零、文章目录

一、Autofac详解

1、概述

  • Autofac是第三方IOC容器,是当前最流行的IOC容器。
  • 功能强大,比asp.netcore内置容器强大得多,支持属性注入和方法注入,支持AOP。
  • 官网地址:http://autofac.org/
  • 源码下载地址:https://github.com/autofac/Autofac

2、快速开始

(1)Nuget引入程序包

Autofac 基于版本6.3演示,Net5 

(2)容器创建对象

//创建一个容器建造者 ContainerBuilder containerBuilder = new ContainerBuilder(); //注册普通类 containerBuilder.RegisterType 
  
    (); //build一下,得到一个容器 IContainer container = containerBuilder.Build(); //可以基于容器来获取对象的实例 Honer phone = container.Resolve 
   
     (); 
    
  

3、注册的类型

(1)注册普通类

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType 
  
    (); IContainer container = containerBuilder.Build(); Honer phone = container.Resolve 
   
     (); 
    
  

(2)注册抽象与实现

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType 
  
    ().As 
   
     (); IContainer container = containerBuilder.Build(); IPhone phone = container.Resolve 
    
      (); 
     
    
  

(3)注册程序集

  • RegisterAssemblyTypes(程序集数组),程序集必须是public的
  • AsImplementedInterfaces():表示注册的类型,以接口的方式注册
  • PropertiesAutowired():支持属性注入
  • Where:满足条件类型注册
var basePath = AppContext.BaseDirectory; var dll = Path.Combine(basePath, "MyAutofac.dll"); ContainerBuilder containerBuilder = new ContainerBuilder(); var assemblysServices = Assembly.LoadFrom(dll); containerBuilder.RegisterAssemblyTypes(assemblysServices) .Where(t => !t.Name.EndsWith("XXX")) .AsImplementedInterfaces() .PropertiesAutowired(); IContainer container = containerBuilder.Build(); ITeacher teacher = container.Resolve 
  
    (); 
  

image-20220615171348335

4、三种注入方式

(1)构造函数注入

默认支持,无法用特性进行筛选,默认选参数最多的构造函数进行注入

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType 
  
    ().As 
   
     (); containerBuilder.RegisterType 
    
      ().As 
     
       (); containerBuilder.RegisterType 
      
        ().As 
       
         (); IContainer container = containerBuilder.Build(); ITeacher teacher = container.Resolve 
        
          (); 
         
        
       
      
     
    
  

image-20220507144924795

(2)全部属性注入

关键词PropertiesAutowired,这个对象所有属性全部注入

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType 
  
    ().As 
   
     (); containerBuilder.RegisterType 
    
      ().As 
     
       ().PropertiesAutowired(); containerBuilder.RegisterType 
      
        ().As 
       
         (); IContainer container = containerBuilder.Build(); ITeacher teacher = container.Resolve 
        
          (); 
         
        
       
      
     
    
  

image-20220507145543126

(3)标记特性的属性注入

关键词PropertiesAutowired,定义特性选择器CustomPropertySelector

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType 
  
    ().As 
   
     (); containerBuilder.RegisterType 
    
      ().As 
     
       ().PropertiesAutowired(new CustomPropertySelector()); containerBuilder.RegisterType 
      
        ().As 
       
         (); IContainer container = containerBuilder.Build(); ITeacher teacher = container.Resolve 
        
          (); 
         
        
       
      
     
    
  

public class CustomPropertySelector : IPropertySelector { public bool InjectProperty(PropertyInfo propertyInfo, object instance) { var flag = propertyInfo.CustomAttributes.Any(it => it.AttributeType == typeof(SelectPropAttribute)); return flag; } } 

image-20220507151030788

(4)方法注入

关键词OnActivated,指定调用方法

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType 
  
    ().As 
   
     (); containerBuilder.RegisterType 
    
      ().As 
     
       () .OnActivated(p => { p.Instance.SetStudent1(p.Context.Resolve 
      
        ()); }); containerBuilder.RegisterType 
       
         ().As 
        
          (); IContainer container = containerBuilder.Build(); ITeacher teacher = container.Resolve 
         
           (); 
          
         
        
       
      
     
    
  

image-20220507154431887

5、对象生命周期

(1)瞬时生命周期

每次获取都是全新的实例,关键词InstancePerDependency,默认的生命周期

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType 
  
    ().As 
   
     ().InstancePerDependency(); IContainer container = containerBuilder.Build(); IPhone phone1 = container.Resolve 
    
      (); IPhone phone2 = container.Resolve 
     
       (); bool isflg1 = object.ReferenceEquals(phone1, phone2); Console.WriteLine($"InstancePerDependency:phone1==phone2=>{isflg1}"); 
      
     
    
  

InstancePerDependency:phone1==phone2=>False 

(2)单例生命周期

同一个进程内都是同一个实例,关键词SingleInstance

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType 
  
    ().As 
   
     ().SingleInstance(); IContainer container = containerBuilder.Build(); IPhone phone1 = container.Resolve 
    
      (); IPhone phone2 = container.Resolve 
     
       (); bool isflg1 = object.ReferenceEquals(phone1, phone2); Console.WriteLine($"SingleInstance:phone1==phone2=>{isflg1}"); using (var scope = container.BeginLifetimeScope()) { IPhone phone3 = scope.Resolve 
      
        (); IPhone phone4 = scope.Resolve 
       
         (); bool isflg2 = object.ReferenceEquals(phone3, phone4); Console.WriteLine($"SingleInstance:phone3==phone4=>{isflg2}"); bool isflg3 = object.ReferenceEquals(phone1, phone3); Console.WriteLine($"SingleInstance:phone1==phone3=>{isflg3}"); } 
        
       
      
     
    
  

SingleInstance:phone1==phone2=>True SingleInstance:phone3==phone4=>True SingleInstance:phone1==phone3=>True 

(3)作用域生命周期

同一个作用域内都是同一个实例,关键词InstancePerLifetimeScope

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType 
  
    ().As 
   
     ().InstancePerLifetimeScope(); IContainer container = containerBuilder.Build(); IPhone phone1 = container.Resolve 
    
      (); IPhone phone2 = container.Resolve 
     
       (); bool isflg1 = object.ReferenceEquals(phone1, phone2); Console.WriteLine($"InstancePerLifetimeScope:phone1==phone2=>{isflg1}"); IPhone phone3 = null; IPhone phone4 = null; using (var scope = container.BeginLifetimeScope()) { phone3 = scope.Resolve 
      
        (); phone4 = scope.Resolve 
       
         (); bool isflg2 = object.ReferenceEquals(phone3, phone4); Console.WriteLine($"InstancePerLifetimeScope:phone3==phone4=>{isflg2}"); bool isflg3 = object.ReferenceEquals(phone1, phone3); Console.WriteLine($"InstancePerLifetimeScope:phone1==phone3=>{isflg3}"); } IPhone phone5 = null; IPhone phone6 = null; using (var scope = container.BeginLifetimeScope()) { phone5 = scope.Resolve 
        
          (); phone6 = scope.Resolve 
         
           (); bool isflg2 = object.ReferenceEquals(phone5, phone6); Console.WriteLine($"InstancePerLifetimeScope:phone5==phone6=>{isflg2}"); bool isflg3 = object.ReferenceEquals(phone1, phone5); Console.WriteLine($"InstancePerLifetimeScope:phone1==phone5=>{isflg3}"); } bool isflg4 = object.ReferenceEquals(phone3, phone5); Console.WriteLine($"InstancePerLifetimeScope:phone3==phone5=>{isflg4}"); 
          
         
        
       
      
     
    
  

InstancePerLifetimeScope:phone1==phone2=>True InstancePerLifetimeScope:phone3==phone4=>True InstancePerLifetimeScope:phone1==phone3=>False InstancePerLifetimeScope:phone5==phone6=>True InstancePerLifetimeScope:phone1==phone5=>False InstancePerLifetimeScope:phone3==phone5=>False 

(4)作用域范围生命周期

在作用域范围外无法创建实例,在作用域范围里面,同一个作用域下面的对象是同一个,关键词InstancePerMatchingLifetimeScope

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType 
  
    ().As 
   
     ().InstancePerMatchingLifetimeScope("scope1", "scope2"); IContainer container = containerBuilder.Build(); IPhone phone1 = null; IPhone phone2 = null; using (var scope = container.BeginLifetimeScope("scope1")) { phone1 = scope.Resolve 
    
      (); phone2 = scope.Resolve 
     
       (); bool isflg1 = object.ReferenceEquals(phone1, phone2); Console.WriteLine($"InstancePerMatchingLifetimeScope:phone1==phone2=>{isflg1}"); } IPhone phone3 = null; using (var scope = container.BeginLifetimeScope("scope2")) { phone3 = scope.Resolve 
      
        (); } IPhone phone4 = null; using (var scope = container.BeginLifetimeScope("scope2")) { phone4 = scope.Resolve 
       
         (); } bool isflg2 = object.ReferenceEquals(phone3, phone4); Console.WriteLine($"InstancePerMatchingLifetimeScope:phone3==phone4=>{isflg2}"); bool isflg3 = object.ReferenceEquals(phone1, phone3); Console.WriteLine($"InstancePerMatchingLifetimeScope:phone1==phone3=>{isflg3}"); 
        
       
      
     
    
  

InstancePerMatchingLifetimeScope:phone1==phone2=>True InstancePerMatchingLifetimeScope:phone3==phone4=>False InstancePerMatchingLifetimeScope:phone1==phone3=>False 

(5)一次请求同一个对象

关键词InstancePerRequest,只能在web项目中调试,控制台报错

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType 
  
    ().As 
   
     ().InstancePerRequest(); IContainer container = containerBuilder.Build(); IPhone phone1 = container.Resolve 
    
      (); IPhone phone2 = container.Resolve 
     
       (); bool isflg1 = object.ReferenceEquals(phone1, phone2); Console.WriteLine($"InstancePerRequest:phone1==phone2=>{isflg1}"); 
      
     
    
  

6、支持配置文件注册

(1)nuget引入程序集

Autofac Autofac.Configuration Microsoft.Extensions.Configuration.Json 

(2)配置文件autofac.json,属性->始终复制

{ "components": [ { //实现 "type": "Net5.IOC.Honer,Net5.IOC", //抽象 "services": [ { "type": "Net5.IOC.IPhone,Net5.IOC" } ], //生命周期 "instanceScope": "single-instance", //属性注入 "injectProperties": true } ] } 

(3)通过配置文件注册创建对象

ContainerBuilder containerBuilder = new ContainerBuilder(); IConfigurationBuilder config = new ConfigurationBuilder(); IConfigurationSource autofacJsonConfigSource = new JsonConfigurationSource() { Path = "Autofac/autofac.json", Optional = false,//boolean,默认就是false,可不写 ReloadOnChange = true,//同上 }; config.Add(autofacJsonConfigSource); ConfigurationModule module = new ConfigurationModule(config.Build()); containerBuilder.RegisterModule(module); IContainer container = containerBuilder.Build(); IPhone phone1 = container.Resolve 
  
    (); IPhone phone2 = container.Resolve 
   
     (); bool isflg1 = object.ReferenceEquals(phone1, phone2); Console.WriteLine($"配置文件注册:phone1==phone2=>{isflg1}"); 
    
  

(4)运行结果

配置文件注册:phone1==phone2=>True 

7、支持AOP切面编程

可以在不修改方法的前提下,在方法前后添加公共逻辑,日志,异常,缓存等

(1)nuget引入程序集

Castle.Core Autofac.Extras.DynamicProxy 

(2)自定义一个切面类实现IInterceptor接口

public class CustomInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { Console.WriteLine("方法执行前。。。"); //执行当前方法 invocation.Proceed(); Console.WriteLine("方法执行后。。。"); } } 

(3)在抽象/实现类上添加特性标记

[Intercept(typeof(CustomInterceptor))] public interface IPhone { string ShowName(); } //实现类虚方法 public class Honer : IPhone { public virtual string ShowName() { Console.WriteLine("Honer"); return "Honer"; } } 

(4)在容器中注册关系创建对象

  • EnableInterfaceInterceptors + 特性标记在抽象上,所有实现类都支持AOP
  • EnableInterfaceInterceptors + 特性标记到实现类上,标记的类就支持AOP
  • EnableClassInterceptors,要支持AOP的方法必须要是用virtual虚方法
  • EnableClassInterceptors + 特性标记在抽象上,所有实现类都支持AOP
  • EnableClassInterceptors + 特性标记到实现类上,标记的类就支持AOP
ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType 
  
    ().As 
   
     ().EnableInterfaceInterceptors(); containerBuilder.RegisterType(typeof(CustomInterceptor)); IContainer container = containerBuilder.Build(); IPhone phone = container.Resolve 
    
      (); phone.ShowName(); 
     
    
  

(5)运行结果

方法执行前。。。 Honer 方法执行后。。。 

8、单抽象多实现问题

(1)在容器中注册关系创建对象

ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType 
  
    ().Named 
   
     ("Honer"); containerBuilder.RegisterType 
    
      ().Named 
     
       ("Huawei"); IContainer container = containerBuilder.Build(); IPhone honer = container.ResolveNamed 
      
        ("Honer"); IPhone huawei = container.ResolveNamed 
       
         ("Huawei"); honer.ShowName(); huawei.ShowName(); 
        
       
      
     
    
  

(2)运行结果

Honer Huawei 

9、集成到Asp.NetCore5框架

(1)nuget引入程序集

Autofac Autofac.Extensions.DependencyInjection 

(2)定义实现类和抽象

public class UserService : IUserService { private IUserRepository UserRepositoryCtor { get; set; } public UserService(IUserRepository userRepository) { UserRepositoryCtor = userRepository; } public string Login(string username, string password) { return "登录成功"; } } 

(3)添加控制器和页面

public class FourthController : Controller { private IUserService _userService; public FourthController(IUserService userService) { this._userService = userService; } public IActionResult Index() { object result = this._userService.Login("username", "password"); return View(result); } } 

@model String 

this is fourth index...

@Model

(4)在Program替换容器工厂

public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup 
  
    (); }) .UseServiceProviderFactory(new AutofacServiceProviderFactory()); } 
  

(5)在Startup类的ConfigureServices方法中替换创建控制器的类

//控制器默认是有IControllerActivator创建的,替换成由容器创建 services.Replace(ServiceDescriptor.Transient 
  
    ()); 
  

(6)注册抽象和实现的关系

Startup类中专门增加一个方法ConfigureContainer,用于注册抽象和实现,可以把这些注册信息进行模块化封装到AutofacModule

当抽象类和实现非常多的时候,可以将整个dll注册,特殊的关系可以写在后面覆盖前面的注册关系。

///  /// Autofac专用:注册抽象和细节之间的关系,使用autofac后原来内置注册的关系要注释掉 /// Autofac和ServiceCollection是二者并存的,Autofac会接管ServiceCollection的一切 ///  ///  public void ConfigureContainer(ContainerBuilder builder) { builder.RegisterModule 
   
     (); } 
   

public class AutofacModule : Module { ///  /// 重写Autofac管道中的Load方法,在这里注入注册的内容 ///  ///  protected override void Load(ContainerBuilder builder) { //注册抽象与实现 builder.RegisterType 
   
     ().As 
    
      (); builder.RegisterType 
     
       ().As 
      
        (); //注册所有控制器类 var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes() .Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray(); //实现属性注入,这边无法实现方法注入 builder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired(); } } 
       
      
     
   

(7)运行结果

image-20220617130527205

image-20220509140121017

(8)在StartupConfigure方法中用容器创建对象

using (var container = host.Services.CreateScope()) { IUserService userService = container.ServiceProvider.GetService 
  
    (); } 
  

image-20220617131016831

(9)单抽象多实现集成到框架

注入的时候通过构造函数或者属性注入autofac上下文实例,再根据名称创建对应实例。

定义单抽象和多实例类

//抽象 public interface ITestService { string Show(); } //实现1 public class TestServiceA : ITestService { public string Show() { return "TestServiceA"; } } //实现2 public class TestServiceB : ITestService { public string Show() { return "TestServiceB"; } } 

AutofacModule注册抽象和实现的关系

//单抽象多实现注册 builder.RegisterType 
  
    ().Named 
   
     ("a"); builder.RegisterType 
    
      ().Named 
     
       ("b"); 
      
     
    
  

添加控制器和页面

public class FifthController : Controller { private IComponentContext _componentContext; public FifthController(IComponentContext componentContext) { this._componentContext = componentContext; } public IActionResult Index() { ITestService testServiceA = _componentContext.ResolveNamed 
  
    ("a"); ITestService testServiceB = _componentContext.ResolveNamed 
   
     ("b"); object result = $"{testServiceA.Show()}--{testServiceB.Show()}"; return View(result); } } 
    
  

@model String 

this is Fifth index...

@Model

运行结果

image-20220510102820041

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/207281.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午2:10
下一篇 2026年3月19日 下午2:10


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号