.NetCore Autofac.Core.DependencyResolutionException: Circular component dependency detected

依赖注入实现类循环引用导致错误

一次拉取代码之后编译、启动未出现错误,服务启动后调用API报错,错误信息如下:

.......
An unandled exception has occurred while executing the request.
Autofac.Core.DependencyResolutionException: An exception was thrown while activating
 UOM.Service.DomainService.MachineDomainService -> 
 UOM.Service.DomainService.ServiceNodeDomainService -> 
 UOM.Service.DomainService.ServiceDomainService.
 ---> Autofac.Core.DependencyResolutionException: Circular component dependency 
 detected: UOM.Service.DomainService.MachineDomainService -> 
 UOM.Service.DomainService.ServiceNodeDomainService -> 
 UOM.Service.DomainService.ServiceDomainService -> 
 UOM.Service.DomainService.ServiceNodeDomainService.
   at Autofac.Core.Resolving.CircularDependencyDetector.CheckForCircularDependency(IComponentRegistration registration, Stack`1 activationStack, Int32 callDepth)
   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)
   at Autofac.Core.Resolving.InstanceLookup.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)
   at Autofac.Core.Activators.Reflection.AutowiringParameter.<>c__DisplayClass0_0.<CanSupplyValue>b__0()
   at Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate()
   at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)
   at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters, Object& decoratorTarget)
   --- End of inner exception stack trace ---
   at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters, Object& decoratorTarget)
   at Autofac.Core.Resolving.InstanceLookup.Execute()
   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)
   at Autofac.Core.Resolving.ResolveOperation.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)
   at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters)
   at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)
......

错误分析

错误信息解读

  1. Autofac.Core.DependencyResolutionException: An exception was thrown while activating
    翻译为激活时抛出异常,意思是无法创建接口的实例
  2. Autofac.Core.DependencyResolutionException: Circular component dependency
    翻译为组件形成循环引用

寻找循环

UOM.Service.DomainService.MachineDemainService -> 
UOM.Service.DomainService.ServiceNodeDomainService -> 
UOM.Service.DomainService.ServiceDomainService -> 
UOM.Service.DomainService.ServiceNodeDomainService.

编号
① MachineDomainService
② ServiceNodeDomainService
③ ServiceDomainService
.NetCore 依赖注入循环引用
查看服务代码后的确是存在循环引用

反思

在此次事件中,由于没有进行评估和详细设计,直接进行编码,从而没有把类的职责划分清楚,所以导致循环引用。实际上可以设置允许循环引用

builder.RegisterType<UserService>()
 .InstancePerLifetimeScope()
 .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies);

这种处理方式只会导致问题变得越来越糟糕,应当解除循环引用和减少耦合度,提高代码的可维护性。如果项目非常紧急可以这样在处理(给自己挖坑)

在实际工作容易出现循环依赖的场景有:

  1. 同一个工程不同模块依赖注入;
  2. 多个过程进行项目;
  3. 多个服务进行通信(Http、MQ、Rpc)等。

保持类、模块、服务的自治性,尽量不要形成依赖。单体服务设计时同一层次不要直接引用,尽量创建自身能够控制的实体,调用方(高层级)将需要依赖的转为该实体传入,降低耦合度。微服务中尽量少用Rpc,避免滥用,如果非要用也必须统一管理。服务数量过多时,是否存在循环依赖则需要进行整体结构的宏观把握,理清楚服务间的关系,进行良好的服务划分,怎么划分服务则需要根据具体业务分析和经验了。

猜你喜欢

转载自blog.csdn.net/yiquan_yang/article/details/107039975