介绍
熟悉Asp.Net Core的都知道,无处可见的依赖注入,可以说是核心.我们的ABP框架也是,依赖注入随处可见.
ABP中默认的依赖注入容器是Castle windsor,在使用ABP后,会在Startup执行过程中默认替换掉.Net Core自带的容器.
ABP默认在它外面又包装了一层.IocManager,为什么要在封装一层呢?. 下面再说
类关系图
分析
IocManager基本实现
IIocManager是继承自IIocRegistrar和IIocResolver,其中 IIocRegistrar 提供了服务注册的功能,
IIocResolver则提供了从容器中获取已注册的服务。IocManager是IIocManager的实现.
public interface IIocManager : IIocRegistrar, IIocResolver, IDisposable
{
IWindsorContainer IocContainer { get; }
new bool IsRegistered(Type type);
new bool IsRegistered<T>();
}
IIocManager中封装了IWindsorContainer,为什么要封装呢。其实主要是为了能够快速替换其他DI框架而不影响代码
public class IocManager : IIocManager
{
// Singletone instance for Castle ProxyGenerator.
private static readonly ProxyGenerator ProxyGeneratorInstance = new ProxyGenerator();
/// <summary>
/// The Singleton instance.
/// </summary>
public static IocManager Instance { get; private set; }
/// <summary>
/// Reference to the Castle Windsor Container.
/// </summary>
public IWindsorContainer IocContainer { get; private set; }
static IocManager()
{
Instance = new IocManager();
}
public IocManager()
{
IocContainer = CreateContainer();
_conventionalRegistrars = new List<IConventionalDependencyRegistrar>();
//Register self!
IocContainer.Register(
Component
.For<IocManager, IIocManager, IIocRegistrar, IIocResolver>()
.Instance(this)
);
}
protected virtual IWindsorContainer CreateContainer()
{
return new WindsorContainer(new DefaultProxyFactory(ProxyGeneratorInstance));
}
public void Register<TType>(DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton) where TType : class
{
IocContainer.Register(ApplyLifestyle(Component.For<TType>(), lifeStyle));
}
}
可以看到我们在调用IocManager.Instance的时候会执行静态构造函数,接着会创建一个WindsorContainer容器
其中Register方法在内部,也是调用的WindsorContainer的注册方法.
IConventionalDependencyRegistrar
这是约定注入,也有说是规约注入,可以看到,在类图中,它有4个默认的实现.
先看看BasicConventionalRegistrar
public class BasicConventionalRegistrar : IConventionalDependencyRegistrar
{
public void RegisterAssembly(IConventionalRegistrationContext context)
{
//Transient
context.IocManager.IocContainer.Register(
Classes.FromAssembly(context.Assembly)
.IncludeNonPublicTypes()
.BasedOn<ITransientDependency>()
.If(type => !type.GetTypeInfo().IsGenericTypeDefinition)
.WithService.Self()
.WithService.DefaultInterfaces()
.LifestyleTransient()
);
//Singleton
context.IocManager.IocContainer.Register(
Classes.FromAssembly(context.Assembly)
.IncludeNonPublicTypes()
.BasedOn<ISingletonDependency>()
.If(type => !type.GetTypeInfo().IsGenericTypeDefinition)
.WithService.Self()
.WithService.DefaultInterfaces()
.LifestyleSingleton()
);
//Windsor Interceptors
context.IocManager.IocContainer.Register(
Classes.FromAssembly(context.Assembly)
.IncludeNonPublicTypes()
.BasedOn<IInterceptor>()
.If(type => !type.GetTypeInfo().IsGenericTypeDefinition)
.WithService.Self()
.LifestyleTransient()
);
}
}
调用了Register方法注册了 我们实现了ISingletonDependency
和ITransientDependency
的服务.
以及实现了IInterceptor
的拦截器.ISingletonDependency
和ITransientDependency
都是标记接口,代表了服务以不同的生命周期注册.
如果对生命周期的实现,以及如何自动注入,感兴趣的话,可以参考我个人的简易版框架(模拟Asp.net Core自带DI的实现方式)
在 IocManager中其实有个List集合字段 _conventionalRegistrars.
private readonly List<IConventionalDependencyRegistrar> _conventionalRegistrars;
这个List存放已经有的规约注册器.那么是什么时候加进去的呢?
public sealed class AbpKernelModule : AbpModule
{
public override void PreInitialize()
{
IocManager.AddConventionalRegistrar(new BasicConventionalRegistrar());
}
}
可以看到,是在AbpKernelModule 也就是第一个模块中的预初始化方法中调用IocManager.AddConventionalRegistrar
方法添加的
其中核心模块的初始化方法还调用了IocManager.RegisterAssemblyByConvention
注册服务, 一般每个模块都会在初始化方法中执行RegisterAssemblyByConvention
方法,注册所有符合约定的服务组件.
public void RegisterAssemblyByConvention(Assembly assembly)
{
RegisterAssemblyByConvention(assembly, new ConventionalRegistrationConfig());
}
public void RegisterAssemblyByConvention(Assembly assembly, ConventionalRegistrationConfig config)
{
var context = new ConventionalRegistrationContext(assembly, this, config);
foreach (var registerer in _conventionalRegistrars)
{
registerer.RegisterAssembly(context);
}
if (config.InstallInstallers)
{
IocContainer.Install(FromAssembly.Instance(assembly));
}
}
以及 每次调用RegisterAssemblyByConvention方法时,都会遍历规约注册器集合,调用里面每个注册器的RegisterAssembly方法
其中重载方法中的入参有个ConventionalRegistrationConfig
,这个对象内部是这样的。
public class ConventionalRegistrationConfig : DictionaryBasedConfig
{
public bool InstallInstallers { get; set; }
public ConventionalRegistrationConfig()
{
InstallInstallers = true;
}
}
里面就一个bool类型的属性,默认设置为了True.
if (config.InstallInstallers)
{
IocContainer.Install(FromAssembly.Instance(assembly));
}
也就是说这里默认是true 会执行 IocContainer.Install(FromAssembly.Instance(assembly));
这里的话会扫码你当前程序集.实现了 IWindsorInstaller
接口的实现类,这里面会批量执行所有Installer的intall方法
通常就是批量注册一些服务.例如AbpCoreInstaller
这里面注册了一些ABP默认的服务. . 且是在AbpBootstraper初始化方法中执行的.
IocManager.IocContainer.Install(new AbpCoreInstaller());
IocManager初始化过程
根据引用可以追溯到AbpBootStrap的构造函数中
private AbpBootstrapper([NotNull] Type startupModule, [CanBeNull] Action<AbpBootstrapperOptions> optionsAction = null)
{
Check.NotNull(startupModule, nameof(startupModule));
var options = new AbpBootstrapperOptions();
optionsAction?.Invoke(options);
if (!typeof(AbpModule).GetTypeInfo().IsAssignableFrom(startupModule))
{
throw new ArgumentException($"{nameof(startupModule)} should be derived from {nameof(AbpModule)}.");
}
StartupModule = startupModule;
IocManager = options.IocManager;
PlugInSources = options.PlugInSources;
_logger = NullLogger.Instance;
if (!options.DisableAllInterceptors)
{
AddInterceptorRegistrars();
}
}
可以看到有个AbpBootstrapperOptions
这个对象的构造函数中直接调用了 IocManager = Abp.Dependency.IocManager.Instance
这里会创建IocManager.然后调用注册方法把自己注入进容器,这样其他服务组件就可以使用了.
例如在asp.net core的startup类中调用的AddABP方法.
public static IServiceProvider AddAbp<TStartupModule>(this IServiceCollection services, [CanBeNull] Action<AbpBootstrapperOptions> optionsAction = null)
where TStartupModule : AbpModule
{
var abpBootstrapper = AddAbpBootstrapper<TStartupModule>(services, optionsAction);
ConfigureAspNetCore(services, abpBootstrapper.IocManager);
return WindsorRegistrationHelper.CreateServiceProvider(abpBootstrapper.IocManager.IocContainer, services);
}
这里返回的就是刚才创建的IocManager.
初始化流程