Hangfire源码解析-如何实现可扩展IOC的?
Posted yrinleung
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 IOC 容器源码分析 - getBean调用方法解析 -- Bean的初始化之BeanPostProcessor