zoukankan      html  css  js  c++  java
  • 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);
            }
        }
  • 相关阅读:
    leetcode33. Search in Rotated Sorted Array
    pycharm 设置sublime text3 monokai主题
    django class Meta
    leetcode30, Substring With Concatenation Of All Words
    Sublime text3修改tab键为缩进为四个空格,
    sublime text3 python打开图像的问题
    安装上imesupport输入法依然不跟随的解决办法,
    sublime text3 的插件冲突弃用问题,
    sublime text3 BracketHighlighter括号匹配的设置
    windows 下wget的使用
  • 原文地址:https://www.cnblogs.com/hankuikui/p/7772001.html
Copyright © 2011-2022 走看看