Hangfire源码解析-如何实现可扩展IOC的?

一、官方描述

These projects simplify the integration between Hangfire and your favorite IoC Container. They provide custom implementation of JobActivator class as well as registration extensions that allow you to use unit of work pattern or deterministic disposal in your background jobs.

根据上述说明可以简单理解为继承“JobActivator”来实现自定义IOC容器。

二、JobActivator


//抽象Job生命周期
public abstract class JobActivatorScope : IDisposable
{
    ....省略
    //定义抽象方法,获取实例
    public abstract object Resolve(Type type);
    //定义虚方法,摧毁生命周期
    public virtual void DisposeScope()
    {
    }

}

public class JobActivator
{
    ....省略

    //定义虚方法,默认使用反射获取实例
    public virtual object ActivateJob(Type jobType)
    {
        return Activator.CreateInstance(jobType);
    }

    //定义虚方法,创建一个生命周期
    [Obsolete("Please implement/use the BeginScope(JobActivatorContext) method instead. Will be removed in 2.0.0.")]
    public virtual JobActivatorScope BeginScope()
    {
        return new SimpleJobActivatorScope(this);
    }

    //定义虚方法,创建一个生命周期
    public virtual JobActivatorScope BeginScope(JobActivatorContext context)
    {
#pragma warning disable 618
        return BeginScope();
#pragma warning restore 618
    }

    //实现简单的生命周期
    class SimpleJobActivatorScope : JobActivatorScope
    {
        private readonly JobActivator _activator;
        //存储所有需要回收的实例
        private readonly List<IDisposable> _disposables = new List<IDisposable>();

        public SimpleJobActivatorScope([NotNull] JobActivator activator)
        {
            if (activator == null) throw new ArgumentNullException(nameof(activator));
            _activator = activator;
        }

        public override object Resolve(Type type)
        {
            var instance = _activator.ActivateJob(type);
            var disposable = instance as IDisposable;

            if (disposable != null)
            {
                _disposables.Add(disposable);
            }

            return instance;
        }

        public override void DisposeScope()
        {
            foreach (var disposable in _disposables)
            {
                disposable.Dispose();
            }
        }
    }
}

三、.Net Core 原生DI作为IOC容器

Hangfire.AspNetCore源码实现

public class AspNetCoreJobActivator : JobActivator
{
    private readonly IServiceScopeFactory _serviceScopeFactory;
    ....省略

    public override JobActivatorScope BeginScope(JobActivatorContext context)
    {
        return new AspNetCoreJobActivatorScope(_serviceScopeFactory.CreateScope());
    }

#pragma warning disable CS0672 // Member overrides obsolete member
    public override JobActivatorScope BeginScope()
#pragma warning restore CS0672 // Member overrides obsolete member
    {
        return new AspNetCoreJobActivatorScope(_serviceScopeFactory.CreateScope());
    }
}

internal class AspNetCoreJobActivatorScope : JobActivatorScope
{
    private readonly IServiceScope _serviceScope;
    ....省略

    public override object Resolve(Type type)
    {
        //注意:AspNetCore是获取或者创建,意味着实例没有注入也会创建一个新的实例
        return ActivatorUtilities.GetServiceOrCreateInstance(_serviceScope.ServiceProvider, type);
    }

    public override void DisposeScope()
    {
        _serviceScope.Dispose();
    }
}

四、Autofac 作为IOC容器

Hangfire.Autofac源码实现

/// <summary>
/// Hangfire Job Activator based on Autofac IoC Container.
/// </summary>
public class AutofacJobActivator : JobActivator
{
    /// <summary>
    /// Tag used in setting up per-job lifetime scope registrations.
    /// </summary>
    public static readonly object LifetimeScopeTag = "BackgroundJobScope";

    private readonly ILifetimeScope _lifetimeScope;
    private readonly bool _useTaggedLifetimeScope;
    ....省略

    //重写
    public override object ActivateJob(Type jobType)
    {
        return _lifetimeScope.Resolve(jobType);
    }

#if NET45
    //重写
    public override JobActivatorScope BeginScope()
    {
        return new AutofacScope(_useTaggedLifetimeScope
            ? _lifetimeScope.BeginLifetimeScope(LifetimeScopeTag)
            : _lifetimeScope.BeginLifetimeScope());
    }
#else
    //重写
    public override JobActivatorScope BeginScope(JobActivatorContext context)
    {
        return new AutofacScope(_useTaggedLifetimeScope
            ? _lifetimeScope.BeginLifetimeScope(LifetimeScopeTag)
            : _lifetimeScope.BeginLifetimeScope());
    }
#endif

    class AutofacScope : JobActivatorScope
    {
        private readonly ILifetimeScope _lifetimeScope;
        ....省略

        //重写
        public override object Resolve(Type type)
        {
            return _lifetimeScope.Resolve(type);
        }

        //重写
        public override void DisposeScope()
        {
            _lifetimeScope.Dispose();
        }
    }
}

五、使用

在Hangfire源码“CoreBackgroundJobPerformer”类中使用:

//执行任务
public object Perform(PerformContext context)
{
    //创建一个生命周期
    using (var scope = _activator.BeginScope(
        new JobActivatorContext(context.Connection, context.BackgroundJob, context.CancellationToken)))
    {
        object instance = null;
        ....省略

        //任务是否为静态方法,若是静态方法需要从IOC容器中取出实例
        if (!context.BackgroundJob.Job.Method.IsStatic)
        {
            instance = scope.Resolve(context.BackgroundJob.Job.Type);

            ....省略
        }
        ....省略
    }
}

原文地址:https://www.cnblogs.com/yrinleung/p/10554322.html

时间: 2024-11-04 08:00:02

Hangfire源码解析-如何实现可扩展IOC的?的相关文章

SPRING源码解析-SPRING 核心-IOC

IoC 和 AOP是Spring的核心, 是Spring系统中其他组件模块和应用开发的基础.透过这两个模块的设计和实现可以了解Spring倡导的对企业应用开发所应秉承的思路: 易用性. POJO开发企业应用, 直接依赖于Java语言,而不是容器和框架. 提升程序的可测试性,提高软件质量. 提供一致性编程模型,面向接口的编程 降低应用的负载和框架的侵入性.IoC和AOP实现. 不作为现有解决方案的替代,而是集成现有. IoC和AOP这两个核心组件,特别是IoC容器,使用户在使用Spring完成PO

Hangfire源码解析-任务是如何执行的?

一.Hangfire任务执行的流程 任务创建时: 将任务转换为Type并存储(如:HangFireWebTest.TestTask, HangFireWebTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null) 将参数序列化后存储 任务执行时: 根据Type值判断是否是静态方法,若非静态方法就根据Type从IOC容器中取实例. 反序列化参数 使用反射调用方法:MethodInfo.Invoke 二.Hangfire执行任务 从源码

五.jQuery源码解析之jQuery.extend(),jQuery.fn.extend()

给jQuery做过扩展或者制作过jQuery插件的人这两个方法东西可能不陌生.jQuery.extend([deep],target,object1,,object2...[objectN]) jQuery.fn.extend([deep],target,object1,,object2...[objectN])这两个属性都是用于合并两个或多个对象的属性到target对象.deep是布尔值,表示是否进行深度合并,默认是false,不执行深度合并.通过这种方式可以在jQuery或jQuery.fn

Spring源码解析-applicationContext

Demo uml类图 ApplicationContext ApplicationListener 源码解析 主流程 obtainFreshBeanFactory prepareBeanFactory invokeBeanFactoryPostProcessors registerBeanPostProcessors registerListeners finishRefresh 总结 在已经有BeanFactory可以完成Ioc功能情况下,spring又提供了ApplicationContex

socketserver源码解析和协程版socketserver

来,贴上一段代码让你仰慕一下欧socketserver的魅力,看欧怎么完美实现多并发的魅力 client import socket ip_port = ('127.0.0.1',8009) sk = socket.socket() sk.connect(ip_port) sk.settimeout(5) while True: data = sk.recv(1024) print('receive:',data.decode()) inp = input('please input:') sk

Java 集合系列05之 LinkedList详细介绍(源码解析)和使用示例

概要  前面,我们已经学习了ArrayList,并了解了fail-fast机制.这一章我们接着学习List的实现类——LinkedList.和学习ArrayList一样,接下来呢,我们先对LinkedList有个整体认识,然后再学习它的源码:最后再通过实例来学会使用LinkedList.内容包括:第1部分 LinkedList介绍第2部分 LinkedList数据结构第3部分 LinkedList源码解析(基于JDK1.6.0_45)第4部分 LinkedList遍历方式第5部分 LinkedL

Java 集合系列 04 LinkedList详细介绍(源码解析)和使用示例

java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java 集合系列 04 LinkedList详细介绍(源码解析)和使用示例 概要  和学习ArrayList一样,接下来呢,我们先对LinkedList有个整体认识,然后再学习它的源码:最后再通过实例来学会使用LinkedList.内容包括:第1部分 LinkedList介绍第2部分 LinkedList数

Andfix热修复框架原理及源码解析-上篇

热补丁介绍及Andfix的使用 Andfix热修复框架原理及源码解析-上篇 Andfix热修复框架原理及源码解析-下篇 1.不知道如何使用的同学,建议看看我上一篇写的介绍热补丁和Andfix的使用,这样你才有一个大概的框架.通过使用Andfix,其实我们心中会有一个大概的轮廓,它的工作原理,大概就是,所谓的补丁文件,就是通过打包工具apkpatch比对新的apk和旧的apk之间的差异.然后让我们的旧包运行的时候,就加载它,把以前的一些信息替换掉.我们现在就抱着这个大方向去深入源码探个究竟!!首先

Android 热修复Nuwa的原理及Gradle插件源码解析

现在,热修复的具体实现方案开源的也有很多,原理也大同小异,本篇文章以Nuwa为例,深入剖析. Nuwa的github地址 https://github.com/jasonross/Nuwa 以及用于hotpatch生成的gradle插件地址 https://github.com/jasonross/NuwaGradle 而Nuwa的具体实现是根据QQ空间的热修复方案来实现的.安卓App热补丁动态修复技术介绍.在阅读本篇文章之前,请先阅读该文章. 从QQ空间终端开发团队的文章中可以总结出要进行热更