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容器
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);
....省略
}
....省略
}
}
Hangfire源码解析-如何实现可扩展IOC的?的更多相关文章
- Spring源码解析 | 第二篇:Spring IOC容器之XmlBeanFactory启动流程分析和源码解析
一. 前言 Spring容器主要分为两类BeanFactory和ApplicationContext,后者是基于前者的功能扩展,也就是一个基础容器和一个高级容器的区别.本篇就以BeanFactory基 ...
- Hangfire源码解析-任务是如何执行的?
一.Hangfire任务执行的流程 任务创建时: 将任务转换为Type并存储(如:HangFireWebTest.TestTask, HangFireWebTest, Version=1.0.0.0, ...
- 1、Dubbo源码解析--Dubbo如何驱动Spring IOC容器并配合工作的?
首先Spring要注入自己的bean需要在Spring-provider.xml(提供者spring注入文件,名字可能不一样)添加bean注入,其中有dubbo的自定义标签,xml如何识别这些标签?拿 ...
- 设置ZooKeeper服务器地址列表源码解析及扩展
设置ZooKeeper服务器地址列表源码解析及扩展 ZooKeeper zooKeeper = new ZooKeeper("192.168.109.130:2181",SESSI ...
- jQuery2.x源码解析(设计篇)
jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 这一篇笔者主要以设计的角度探索jQuery的源代 ...
- jQuery2.x源码解析(回调篇)
jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 通过艾伦的博客,我们能看出,jQuery的pro ...
- 小学徒成长系列—StringBuilder & StringBuffer关键源码解析
在前面的博文<小学徒成长系列—String关键源码解析>和<小学徒进阶系列—JVM对String的处理>中,我们讲到了关于String的常用方法以及JVM对字符串常量Strin ...
- jQuery整体架构源码解析(转载)
jQuery整体架构源码解析 最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性, ...
- JQuery源码解析(一)
写在前面:本<JQuery源码解析>系列是基于一些前辈们的文章进行进一步的分析.细化.修改而写出来的,在这边感谢那些慷慨提供科普文档的技术大拿们. 要查阅JQ的源文件请下载开发版的JQ.j ...
随机推荐
- 深浅拷贝,原生和JQuery方法实现
7-17: 1:e.target.parentNode.remove();成功,查询一下JS原生的remove方法 2:复习JS DOM的原生操作方法,比如innerHTML(),insertBefo ...
- FTP连接池
我们项目使用的是 Apache的(commons-net-3.2.jar) FTPClient,但是系统偶尔会有异常,趁着刚解决完,总结一下. 日志中提示是类似 java.lang.Exception ...
- spot 状压dp
题目大意:数轴上有n个泥点,共有m个木板,求最少用几个木板可以覆盖全部泥点,并求最优方案数(n,m<=15) 看范围,肯定是状压 f[i][j]表示前i个泥点都被覆盖,使用的木板集合为j 转移: ...
- 如何在ST官网下载STM32固件库
1.首先要注册一个ST账号,下载的时候需要. 2.找到工具与软件 3.进去之后选"产品列表" 4.在产品列表里选STM32微控制器软件,直接点下图标号2,不要点左边的加号 5.进去 ...
- Python学习笔记1 -- TypeError: 'str' object is not callable
Traceback (most recent call last): File "myfirstpython.py", line 39, in <module> pri ...
- Navicat:实现两个数据库结构同步和数据库对比
Navicat版本:Navicat Premium 12 选择 工具 ——> 结构同步 选择源数据库和目标数据库,选择完成后点击右下角对比按钮 要修改的对象:源数据库和目标数据库中都有的 ...
- 基于 HTTP 请求拦截,快速解决跨域和代理 Mock
近几年,随着 Web 开发逐渐成熟,前后端分离的架构设计越来越被众多开发者认可,使得前端和后端可以专注各自的职能,降低沟通成本,提高开发效率. 在前后端分离的开发模式下,前端和后端工程师得以并行工作. ...
- Scrapy爬虫遇到 ‘Forbidden by robots.txt’的问题
今天在爬知乎精华时,出现了‘Forbidden by robots.txt’的问题 了解到到scrapy在爬取设定的url之前,它会先向服务器根目录请求一个txt文件,这个文件规定了爬取范围 scra ...
- Netty源码—七、内存释放
Netty本身在内存分配上支持堆内存和直接内存,我们一般选用直接内存,这也是默认的配置.所以要理解Netty内存的释放我们得先看下直接内存的释放. Java直接内存释放 我们先来看下直接内存是怎么使用 ...
- DSAPI 网页获取本地程序登陆用户
这是一个非常简单的示例,在网页或其他平台获取程序中已经登陆的用户,当然也可以是其他信息. 源码 Imports DSAPI.网络.HTTP监听_DSWebAPI Public Class Form1 ...