• ABP 源码分析汇总之 IOC


    IOC的优点:

    1. 依赖接口,而非实现,如下代码,

        这样的好处就是,客户端根本不知道PersonService的存在,如果我们换一下IPersonService的实现,客户端不用任何修改,

        说的简单一点:就是解耦。

        说的专业一点,就涉及到这三个术语:

        依赖倒置原则(DIP)它转换了依赖,高层模块不依赖于低层模块的实现,而低层模块依赖于高层模块定义的接口 

        控制反转(IoC):它为相互依赖的组件提供抽象,将依赖(低层模块)对象的获得交给第三方(系统)来控制,即依赖对象不在被依赖模块的类中直接通过new来获取

         依赖注入DI:它提供一种机制,将需要依赖(低层模块)对象的引用传递给被依赖(高层模块)对象,常用的注入方法有:构造器注入,属性注入。

        他们三个的关系,总结 一下: DIP是一种设计原则,IOC是一种设计模式,DI 是IoC的一种实现方式,用来反转依赖

        public interface IPersonService
        {
            void Show();
        }
    
        public class PersonService: IPersonService
        {
            public void Show()
            {
                Console.WriteLine("This is PersonService");
            }
        }
    static void Main(string[] args)
            {
    
                WindsorContainer container = WindsorInit.GetContainer();
    
                var instance = container.Resolve<IPersonService>();
                instance.Show();
    
    
    
                Console.ReadKey();
            }

     ABP使用的是IOC框架是Castle Windsor, 例子中使用的也是,

    项目需要引用:

    public class WindsorInit
        {
            private static WindsorContainer _container;
    
            public static WindsorContainer GetContainer()
            {
                if (_container == null)
                {
                    _container = new WindsorContainer();
                    _container.Install(FromAssembly.This());
    
                }
                return _container;
            }
    
            public void CloseContext()
            {
                _container.Dispose();
            }
        }
    public class Installer : IWindsorInstaller
        {
            public void Install(IWindsorContainer container, IConfigurationStore store)
            {
                container.Register(Classes.FromThisAssembly().InNamespace("CastleWindsor").WithService.DefaultInterfaces());
            }
        }

    以上的例子,是基于控制台程序。如果是Asp.Net MVC,该如何做呢?

    是不是要在controller的action中,通过container.Resolve<IPersonService>(); 这样的调用调取服务端方法,这样做是不是太笨了。

    后来看了园子里 大内老A 的文章才明白 文章链接:http://www.cnblogs.com/artech/archive/2012/04/01/controller-activation-031.html

    通过文章的介绍 再结合ABP的源码,再分析一下ABP的IOC是如何实现的:

    首先要做的都是注册,ABP采用模块化设计,在每个模块中,都会对自己的模块内部需要注册的类就是注册:IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());

    [DependsOn(typeof(AuditCoreModule), typeof(AbpAutoMapperModule))]
        public class AuditApplicationModule : AbpModule
        {
            public override void PreInitialize()
            {
                Configuration.UnitOfWork.IsolationLevel = IsolationLevel.ReadCommitted;
    
                AuthorizationInterceptorRegistrar.Initialize(IocManager);
            }
    
            public override void Initialize()
            {
                IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
            }
        }
    /// <summary>
            /// Adds a dependency registrar for conventional registration.
            /// </summary>
            /// <param name="registrar">dependency registrar</param>
            public void AddConventionalRegistrar(IConventionalDependencyRegistrar registrar)
            {
                _conventionalRegistrars.Add(registrar);
            }
    
            /// <summary>
            /// Registers types of given assembly by all conventional registrars. See <see cref="AddConventionalRegistrar"/> method.
            /// </summary>
            /// <param name="assembly">Assembly to register</param>
            public void RegisterAssemblyByConvention(Assembly assembly)
            {
                RegisterAssemblyByConvention(assembly, new ConventionalRegistrationConfig());
            }
    
            /// <summary>
            /// Registers types of given assembly by all conventional registrars. See <see cref="AddConventionalRegistrar"/> method.
            /// </summary>
            /// <param name="assembly">Assembly to register</param>
            /// <param name="config">Additional configuration</param>
            public void RegisterAssemblyByConvention(Assembly assembly, ConventionalRegistrationConfig config)
            {
                var context = new ConventionalRegistrationContext(assembly, this, config);
    
    //你可以通过实现IConventionalRegisterer接口,写你自己的约定注册类,然后在你的模块的预初始化里,调用IocManager.AddConventionalRegisterer方法,添加你的类。
    foreach (var registerer in _conventionalRegistrars) { registerer.RegisterAssembly(context); } if (config.InstallInstallers) { IocContainer.Install(FromAssembly.Instance(assembly)); } }
    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()
                    );
            }
        }

    BasicConventionalRegistrar这个类非常重要,它利用casle windsor的注册方法,将我们实现了ITransientDependency,ISingletonDependency,IInterceptor的类进行注册

    还要注意 DefaultInterfaces方法,看下它的注释:就是说我们注册的PersonService,它的默认接口就是IPersonService,这么当我们通过IOCManager解析IPersonService时,就会返回PersonService的实例。

            //
            // 摘要:
            //     Uses all interfaces that have names matched by implementation type name. Matches
            //     Foo to IFoo, SuperFooExtended to IFoo and IFooExtended etc
            public BasedOnDescriptor DefaultInterfaces();

    以上这个类BasicConventionalRegistrar是通过如下代码,添加到 IocManager.AddConventionalRegistrar(new BasicConventionalRegistrar());

    public sealed class AbpKernelModule : AbpModule
        {
            public override void PreInitialize()
            {
                IocManager.AddConventionalRegistrar(new BasicConventionalRegistrar());
    
                IocManager.Register<IScopedIocResolver, ScopedIocResolver>(DependencyLifeStyle.Transient);
                IocManager.Register(typeof(IAmbientScopeProvider<>), typeof(DataContextAmbientScopeProvider<>), DependencyLifeStyle.Transient);
    
                AddAuditingSelectors();
                AddLocalizationSources();
                AddSettingProviders();
                AddUnitOfWorkFilters();
                ConfigureCaches();
                AddIgnoredTypes();
            }
    .... }

    就这样,ABP自动注册所有 Repositories, Domain Services, Application Services, MVC 控制器和Web API控制器(前提是你都实现ITransientDependency或ISingletonDependency)

    自定义/直接 注册

    如果之前描述的方法还是不足以应对你的情况,你可以使用Castle Windsor注册类和及依赖项。因此,您将拥有Castle Windsor注册的所有能力。

    可以实现IWindsorInstaller接口进行注册。您可以在应用程序中创建一个实现IWindsorInstaller接口的类:

    public class Installer : IWindsorInstaller
        {
            public void Install(IWindsorContainer container, IConfigurationStore store)
            {
                container.Register(Classes.FromThisAssembly().InNamespace("CastleWindsor").WithService.DefaultInterfaces());
            }
        }

    Abp自动发现和执行这个类。最后,你可以通过使用IIocManager.IocContainer属性得到WindsorContaine。

    如果只想注册一个类,又不写这样的installer,可以使用

    public override void Initialize()
            {
                IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
                IocManager.Register(
                    Component.For<IPersonRepository>().ImplementedBy<PersonRepository>().LifestyleTransient(), 
    Component.For
    <IPersonAppService>().ImplementedBy<PersonAppService>().LifestyleTransient() );
    }

    注册的三种方式,就说完了,又回到刚才的问题,我们在controller里是如何获取服务层的实例呢,服务层可以通过属性注入,或者构造器注入,其实在controller层也是通过这两种注册方式获取服务层的实例的,但mvc是如何创建出这个controller,然后通过IOC容器创建出服务层的实例呢?结合老A的文章,能够很快的找个继承DefaultControllerFactory类的 WindsorControllerFactory。 我们看下ABP是如何做的:

    [DependsOn(typeof(AbpWebModule))]
        public class AbpWebMvcModule : AbpModule
        {
            ..............................
            /// <inheritdoc/>
            public override void Initialize()
            {
                IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
    //就是这句 ControllerBuilder.Current.SetControllerFactory(
    new WindsorControllerFactory(IocManager));
    HostingEnvironment.RegisterVirtualPathProvider(IocManager.Resolve
    <EmbeddedResourceVirtualPathProvider>()); } ..................... }
    /// <summary>
        /// This class is used to allow MVC to use dependency injection system while creating MVC controllers.
        /// </summary>
        public class WindsorControllerFactory : DefaultControllerFactory
        {
            /// <summary>
            /// Reference to DI kernel.
            /// </summary>
            private readonly IIocResolver _iocManager;
    
            /// <summary>
            /// Creates a new instance of WindsorControllerFactory.
            /// </summary>
            /// <param name="iocManager">Reference to DI kernel</param>
            public WindsorControllerFactory(IIocResolver iocManager)
            {
                _iocManager = iocManager;
            }
    
            /// <summary>
            /// Called by MVC system and releases/disposes given controller instance.
            /// </summary>
            /// <param name="controller">Controller instance</param>
            public override void ReleaseController(IController controller)
            {
                _iocManager.Release(controller);
            }
    
            /// <summary>
            /// Called by MVC system and creates controller instance for given controller type.
            /// </summary>
            /// <param name="requestContext">Request context</param>
            /// <param name="controllerType">Controller type</param>
            /// <returns></returns>
            protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
            {
                if (controllerType == null)
                {
                    return base.GetControllerInstance(requestContext, controllerType);
                }
    
                return _iocManager.Resolve<IController>(controllerType);
            }
        }
  • 相关阅读:
    【06月18日】A股滚动市净率PB历史新低排名
    沪深300指数的跟踪基金最近1年收益排名
    主要股东近3年净买入排名
    北上资金近1周流入排行榜
    【06月12日】指数估值排名
    最近一月研报推荐次数最多的最热股票
    【06月10日】A股ROE最高排名
    JDK源码阅读-------自学笔记(九)(常用类型Integer初探)
    JDK源码阅读-------自学笔记(八)(数组演示冒泡排序和二分查找)
    JDK源码阅读-------自学笔记(七)(二维数组的浅析)
  • 原文地址:https://www.cnblogs.com/hankuikui/p/7772001.html
Copyright © 2020-2023  润新知