Abp 源码研读 - 依赖注入

Abp 框架对于依赖注入的实现主要是依赖 Castle.Core ,实际上这一篇更应该归类于 Castle.Core 的应用, 若对 Castle.Core 知识不了解的, 可以先去学习下:Castle.Core 。下面来分析下比较重要的接口/类:

核心接口

IIocManager

定义了对 Ioc 对象, 服务注册,服务解析,服务注册与否的判断,以及对解析对象的释放、

IocManager

实现了 IIocManager 接口, 这里需要特别注意的是:对于长时间运行的程序,比如网站,Windows 服务, 并且需要创建大量的动态代理类, 那此时你就需要保证可以重用相同的 ProxyGenerator , 否则, 将会绕过缓存机制,导致CPU 使用率与内存耗用不断增加。

在程序实现中, 直接将 ProxyGenerator 声明为 static 即可, 另外将 IocManager 作为单例对象使用。

private static readonly ProxyGenerator ProxyGeneratorInstance = new ProxyGenerator();

IocContainer = new WindsorContainer(new DefaultProxyFactory(ProxyGeneratorInstance))

public static IocManager Instance { get; private set; }

static IocManager()
{
    Instance = new IocManager();
}

构造函数中通过静态变量 ProxyGeneratorInstance 初始化了 IWindsorContainer IocContainer , 紧接着,将当前对象(单例):

IocContainer.Register(
                Component
                    .For<IocManager, IIocManager, IIocRegistrar, IIocResolver>()
                    .Instance(this)
            );

进行注册为 IocManager, IIocManager, IIocRegistrar, IIocResolver, 这样, 我们通过 Ioc 解析出来的 这些对象都会返回当前实例。

约定注册

随着项目业务复杂度的提高, 需要注册的服务也会逐渐增多, 此时的管理就会逐渐繁杂。

在 Abp 中, 有以下几类 约定注册 的接口: (IConventionalDependencyRegistrar, BasicConventionalRegistrar

  • ITransientDependency
  • ISingletonDependency
  • IInterceptor
  • IConventionalDependencyRegistrar

ITransientDependency

瞬态服务:

Ioc 每次解析瞬态服务的时候都会返回一个新的瞬态服务对象

context.IocManager.IocContainer.Register(
                Classes.FromAssembly(context.Assembly)       //从当前上下文程序集中
                    .IncludeNonPublicTypes()                //包含非公共类型
                    .BasedOn<ITransientDependency>()         //ITransientDependency 的实现类
                    .If(type => !type.GetTypeInfo().IsGenericTypeDefinition)  //排除泛型类型
                    .WithService.Self()                     //使用服务自身
                    .WithService.DefaultInterfaces()         //注册为默认接口
                    .LifestyleTransient()                   //设置生命周期形式为瞬态
                );

ISingletonDependency

单例服务:

字面意思,Ioc 会返回一个单例对象,在依赖注入容器中共享,约定注册的方式与瞬态非常相似:

context.IocManager.IocContainer.Register(
                Classes.FromAssembly(context.Assembly)
                    .IncludeNonPublicTypes()
                    .BasedOn<ISingletonDependency>()
                    .If(type => !type.GetTypeInfo().IsGenericTypeDefinition)
                    .WithService.Self()
                    .WithService.DefaultInterfaces()
                    .LifestyleSingleton()                   // 设置生命周期形式为单例
                );

IInterceptor

拦截器:

对拦截器的注册

 context.IocManager.IocContainer.Register(
                Classes.FromAssembly(context.Assembly)
                    .IncludeNonPublicTypes()
                    .BasedOn<IInterceptor>()
                    .If(type => !type.GetTypeInfo().IsGenericTypeDefinition)
                    .WithService.Self()
                    .LifestyleTransient()
                );

IConventionalDependencyRegistrar

依赖约定注册

/// <summary>
    /// This interface is used to register dependencies by conventions.
    /// </summary>
    /// <remarks>
    /// Implement this interface and register to <see cref="IocManager.AddConventionalRegistrar"/> method to be able
    /// to register classes by your own conventions.
    /// </remarks>
    public interface IConventionalDependencyRegistrar
    {
        /// <summary>
        /// Registers types of given assembly by convention.
        /// </summary>
        /// <param name="context">Registration context</param>
        void RegisterAssembly(IConventionalRegistrationContext context);
    }

在参数 IConventionalRegistrationContext 中包含了当前程序集, IocManager 以及必要的注册配置, 这便于我们可以通过上下文获取到当前容器管理对象, 来完成对当前程序集中遵循约定的类型进行注册。

原文地址:https://www.cnblogs.com/rajesh/p/11122412.html

时间: 2024-11-05 21:43:03

Abp 源码研读 - 依赖注入的相关文章

看laravel源码学习依赖注入

前言 初心 最近在看设计模式中的依赖注入,希望借助设计模式的神奇魔力,能达到一个目的,然后在此学习的过程中,能收获一个bonus.这个目的就是能使得自己设计的系统更简单更容易理解,或者是使得系统设计的结构和代码更简单,而bonus是企图在设计模式上实现概念上的并发.这篇文章是希望把自己这段时间的学习成果作一个记录和总结,然而并不要太期待,因为目前得出的结论并没有达到我的目的,bonus暂时希望也比较渺茫. 在知识网络结构认知上的准备 我们需要提前了解一下依赖倒置原则.控制反转和依赖注入的关系.控

ABP源码分析三十:ABP.RedisCache

ABP 通过StackExchange.Redis类库来操作Redis数据库. AbpRedisCacheModule:完成ABP.RedisCache模块的初始化(完成常规的依赖注入) AbpRedisCacheConfig:定义了connectionStringKey和databaseIdAppSetting的值.这两个值对象redis 在web.config中的key值. ABP.RedisCache模块通过读取web.config来获取redis的配置. IAbpRedisConnect

ABP源码分析四十六:ABP ZERO中的Ldap模块

通过AD作为用户认证的数据源.整个管理用户认证逻辑就在LdapAuthenticationSource类中实现. LdapSettingProvider:定义LDAP的setting和提供DefautValue.主要提供配置访问AD数据库的账号信息. LdapSettings/ILdapSettings:通过settingManager获取LDAP settings AbpZeroLdapModuleConfig/IAbpZeroLdapModuleConfig: 提供激活Ldap认证的配置.

[Abp 源码分析]十二、多租户体系与权限验证

0.简介 承接上篇文章我们会在这篇文章详细解说一下 Abp 是如何结合 IPermissionChecker 与 IFeatureChecker 来实现一个完整的多租户系统的权限校验的. 1.多租户的概念 多租户系统又被称之为 Saas ,比如阿里云就是一个典型的多租户系统,用户本身就是一个租户,可以在上面购买自己的 ECS 实例,并且自己的数据与其他使用者(租户)所隔绝,两者的数据都是不可见的. 那么 Abp 是如何实现数据隔离的呢? 1.1 单部署-单数据库 如果你的软件系统仅部署一个实例,

[Abp 源码分析]十三、多语言(本地化)处理

0.简介 如果你所开发的需要走向世界的话,那么肯定需要针对每一个用户进行不同的本地化处理,有可能你的客户在日本,需要使用日语作为显示文本,也有可能你的客户在美国,需要使用英语作为显示文本.如果你还是一样的写死错误信息,或者描述信息,那么就无法做到多语言适配. Abp 框架本身提供了一套多语言机制来帮助我们实现本地化,基本思路是 Abp 本身维护一个键值对集合.只需要将展示给客户的文字信息处都使用一个语言 Key 来进行填充,当用户登录系统之后,会取得当前用户的区域文化信息进行文本渲染. 0.1

ABP源码分析二十八:ABP.MemoryDB

这个模块简单,且无实际作用.一般实际项目中都有用数据库做持久化,用了数据库就无法用这个MemoryDB 模块了.原因在于ABP限制了UnitOfWork的类型只能有一个(前文以作介绍),一般用了数据库的必然要注入efUnitOfWork. 而注入了efUnitOfWork就不能在注入MemoryDbUnitOfWork了. MemoryDatabase:这是一个单例.ABP通过Dictionary<Type, object>+lock作为数据结构来实现内存数据库.其以entity的类型作为ke

ABP源码分析四十五:ABP ZERO中的EntityFramework模块

AbpZeroDbContext:配置ABP.Zero中定义的entity的Dbset EntityFrameworkModelBuilderExtensions:给PrimitivePropertyConfiguration添加了扩展方法用于创建Index. AbpZeroDbModelBuilderExtensions:给DbModelBuilder添加了扩展方法用于表的重命名. AbpZeroEntityFrameworkModule:很明显Abp Zero模块中的EntityFramew

ABP源码分析二十六:核心框架中的一些其他功能

本文是ABP核心项目源码分析的最后一篇,介绍一些前面遗漏的功能 AbpSession AbpSession: 目前这个和CLR的Session没有什么直接的联系.当然可以自定义的去实现IAbpSession使之与CLR的Session关联 IAbpSession:定义如下图中的四个属性. NullAbpSession:IAbpSession的一个缺省实现,给每个属性都给予null值,无实际作用 ClaimsAbpSession:实现了从ClaimsPrincipal/ClaimsIdentity

搭建Spark源码研读和代码调试的开发环境

转载自https://github.com/linbojin/spark-notes/blob/master/ide-setup.md Table of Contents 源码获取与编译 从Github上获取Spark源码 编译Spark项目 源码导入与代码运行 导入源码到Intellij IDEA 16 运行实例代码 1. 配置运行参数 2. 添加缺失的flume sink源代码 3. 添加运行依赖的jars 4. 成功运行实例代码 单步调试源代码 工欲善其事,必先利其器,第一篇笔记介绍如何搭