abp vnext 启动,加载module,依赖注入源码分析

  1. Program类 IHostBuilder UseAutofac(this IHostBuilder hostBuilder)扩展方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public static IHostBuilder UseAutofac(this IHostBuilder hostBuilder)
            {
                //创建一个Autofac容器,后面会通过BuildServiceProviderFromFactory方法调AbpAutofacServiceProviderFactory里的CreateBuilder方法替换IOC容器
                var containerBuilder = new ContainerBuilder();
     
                return hostBuilder.ConfigureServices((_, services) =>
                    {
                        services.AddObjectAccessor(containerBuilder);
                    })
                    .UseServiceProviderFactory(new AbpAutofacServiceProviderFactory(containerBuilder));
            }
  2. Startup里services.AddApplication<>();方法

里面调AbpApplicationFactory.Create<TStartupModule>(services, optionsAction);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public static class AbpApplicationFactory
   {
       //控制台应用程序new AbpApplicationWithInternalServiceProvider:AbpApplicationBase
       //apiservice new AbpApplicationWithExternalServiceProvider:AbpApplicationBase
       public static IAbpApplicationWithInternalServiceProvider Create<TStartupModule>(
           [CanBeNull] Action<AbpApplicationCreationOptions> optionsAction = null)
           where TStartupModule : IAbpModule
       {
           return Create(typeof(TStartupModule), optionsAction);
       }
 
       public static IAbpApplicationWithInternalServiceProvider Create(
           [NotNull] Type startupModuleType,
           [CanBeNull] Action<AbpApplicationCreationOptions> optionsAction = null)
       {
           return new AbpApplicationWithInternalServiceProvider(startupModuleType, optionsAction);
       }
 
       public static IAbpApplicationWithExternalServiceProvider Create<TStartupModule>(
           [NotNull] IServiceCollection services,
           [CanBeNull] Action<AbpApplicationCreationOptions> optionsAction = null)
           where TStartupModule : IAbpModule
       {
           return Create(typeof(TStartupModule), services, optionsAction);
       }
 
       public static IAbpApplicationWithExternalServiceProvider Create(
           [NotNull] Type startupModuleType,
           [NotNull] IServiceCollection services,
           [CanBeNull] Action<AbpApplicationCreationOptions> optionsAction = null)
       {
           return new AbpApplicationWithExternalServiceProvider(startupModuleType, services, optionsAction);
       }
   }

  3.AbpApplicationBase里实现的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
internal AbpApplicationBase(
            [NotNull] Type startupModuleType,
            [NotNull] IServiceCollection services,
            [CanBeNull] Action<AbpApplicationCreationOptions> optionsAction)
        {
            Check.NotNull(startupModuleType, nameof(startupModuleType));
            Check.NotNull(services, nameof(services));
 
            StartupModuleType = startupModuleType;
            Services = services;
            //往ObjectAccessor里添加一个IServiceProvider,后面ApplicationInitializationContext.ServiceProvider拿出来用
            services.TryAddObjectAccessor<IServiceProvider>();
 
            //在services.AddApplication<AbpExceptionDemoModule>(option=》{});里赋值AbpApplicationCreationOptions
            var options = new AbpApplicationCreationOptions(services);
            optionsAction?.Invoke(options);
 
            services.AddSingleton<IAbpApplication>(this);
            services.AddSingleton<IModuleContainer>(this);
 
            //注入abp一些基础组件
            services.AddCoreServices();
            //注入模块相关组件
            services.AddCoreAbpServices(this, options);
            //将一些模块添加到集合,先添加[DependsOn]里的模块,再添加里赋值AbpApplicationCreationOptions.PlugInSources里的模块
            Modules = LoadModules(services, options);
            //按顺序加载Modules
            ConfigureServices();
        }

  4.ConfigureServices里实现的内容,遍历Modules执行PreConfigureServices方法,依次遍历Modules执行ConfigureServices,PostConfigureServices后清空ServiceConfigurationContext属性

  5.关于遍历Modules执行ConfigureServices

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//ConfigureServices
            foreach (var module in Modules)
            {
                if (module.Instance is AbpModule abpModule)
                {
                    if (!abpModule.SkipAutoServiceRegistration)
                    {
                        //在这里拉module所在程序集里的接口,类,按规则注入
                        Services.AddAssembly(module.Type.Assembly);
                    }
                }
 
                try
                {
                    module.Instance.ConfigureServices(context);
                }
                catch (Exception ex)
                {
                    throw new AbpInitializationException($"An error occurred during {nameof(IAbpModule.ConfigureServices)} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex);
                }
            }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public abstract class ConventionalRegistrarBase : IConventionalRegistrar
    {
        public virtual void AddAssembly(IServiceCollection services, Assembly assembly)
        {
            //筛选非抽象类,泛型类,在ConventionalRegistrarList(DefaultConventionalRegistrar)里的方法依次执行AddType方法
            var types = AssemblyHelper
                .GetAllTypes(assembly)
                .Where(
                    type => type != null &&
                            type.IsClass &&
                            !type.IsAbstract &&
                            !type.IsGenericType
                ).ToArray();
 
            AddTypes(services, types);
        }
 
        public virtual void AddTypes(IServiceCollection services, params Type[] types)
        {
            foreach (var type in types)
            {
                AddType(services, type);
            }
        }
 
        public abstract void AddType(IServiceCollection services, Type type);

  6.看下DefaultConventionalRegistrar里的AddType方法

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public override void AddType(IServiceCollection services, Type type)
       {
           //判断是否有DisableConventionalRegistrationAttribu特性
           if (IsConventionalRegistrationDisabled(type))
           {
               return;
           }
           //获取DependencyAttribute特性
           var dependencyAttribute = GetDependencyAttributeOrNull(type);
           //dependencyAttribute.Lifetime有值就用dependencyAttribute的注入方式,否则就用ITransientDependency等接口
           var lifeTime = GetLifeTimeOrNull(type, dependencyAttribute);
 
           if (lifeTime == null)
           {
               return;
           }
           // 获得等待注册的类型定义,类型的定义优先使用 ExposeServices 特性指定的类型,如果没有则使用
           // 类型当中接口以 I 开始,后面为实现类型名称的接口。
           var exposedServiceTypes = GetExposedServiceTypes(type);
 
           TriggerServiceExposing(services, type, exposedServiceTypes);
 
           foreach (var exposedServiceType in exposedServiceTypes)
           {
               //创建一个注入描述
               var serviceDescriptor = CreateServiceDescriptor(
                   type,
                   exposedServiceType,
                   exposedServiceTypes,
                   lifeTime.Value
               );
               //判断是替换注入对象还是tryAdd,add
               if (dependencyAttribute?.ReplaceServices == true)
               {
                   services.Replace(serviceDescriptor);
               }
               else if (dependencyAttribute?.TryRegister == true)
               {
                   services.TryAdd(serviceDescriptor);
               }
               else
               {
                   services.Add(serviceDescriptor);
               }
           }
       }

  7.GetExposedServiceTypes方法获取实现类与实现类的接口,后面一起注入IServiceCollection里面

1
2
3
4
5
6
7
8
9
10
public static List<Type> GetExposedServices(Type type)
        {
            return type
                .GetCustomAttributes(true)
                .OfType<IExposedServiceTypesProvider>()//获取type中ExposedService特性里面的types
                .DefaultIfEmpty(DefaultExposeServicesAttribute)
                .SelectMany(p => p.GetExposedServiceTypes(type))//用GetExposedServiceTypes()处理types
                .Distinct()
                .ToList();
        }

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public Type[] GetExposedServiceTypes(Type targetType)
        {
            var serviceList = ServiceTypes.ToList();
 
            if (IncludeDefaults)//目前属性没开放出来,默认true
            {
                foreach (var type in GetDefaultServices(targetType))//获取该接口与实现类除首字母I外是否相等,serviceList添加type
                {
                    serviceList.AddIfNotContains(type);
                }
 
                if (IncludeSelf)//目前属性没开放出来,默认true
                {
                    serviceList.AddIfNotContains(targetType);//添加自己
                }
            }
            else if (IncludeSelf)
            {
                serviceList.AddIfNotContains(targetType);
            }
 
            return serviceList.ToArray();
        }
 
        private static List<Type> GetDefaultServices(Type type)
        {
            var serviceTypes = new List<Type>();
 
            foreach (var interfaceType in type.GetTypeInfo().GetInterfaces())
            {
                var interfaceName = interfaceType.Name;
 
                if (interfaceName.StartsWith("I"))
                {
                    interfaceName = interfaceName.Right(interfaceName.Length - 1);
                }
 
                if (type.Name.EndsWith(interfaceName))
                {
                    serviceTypes.Add(interfaceType);
                }
            }
 
            return serviceTypes;
        }

  8.可以看到GetExposedServices()获取的是:实现类及 除首字母I外name与他相等的接口和IExposedService特性里的types

例:

1
2
3
4
//获取到的ServiceTypes里的内容是IBTestService,ITestService,TestService
//后面会依次注入这3个类型
[ExposeServices(typeof(IBTestService))]
public class TestService: ITestService:IMyTestService

  

 

 参考:https://www.cnblogs.com/zhiyong-ITNote/archive/2019/12/08/12005772.html

 

 

posted @   哈喽哈喽1  阅读(192)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示