0

有没有办法自动装配需要经常重新实例化的对象?

我正在使用 Netflix 的 DGS + spring boot 框架,并且基本上将用户身份验证详细信息存储在为每个请求创建的自定义上下文中。由于需要大量重构,我试图避免将上下文添加到方法签名中。

例如

public Result dataFetcher(DataFetchingEnvironment dfe) {
   

   // this context contains user details which is used for authorization
   // instantiated for every request
   setRolesInContext(dfe);
   MyCustomContext context = DgsContext.getCustomContext(dfe);

   // trying to avoid adding context as an extra param e.g. dataFetcherHelper(context)
   dataFetcherHelper(); // this calls other helper methods from other classes
}

我正在考虑使用外观模式,但这不是线程安全的。基本上自动装配RequestContextHolder, 并在setRequestContext每次初始化新上下文时调用。

@Component
@NoArgsConstructor
@Getter
@Setter
public class RequestContextHolder {
    private RequestContext requestContext;
}
4

1 回答 1

0

我不确定你的问题如何:

有没有办法自动装配需要经常重新实例化的对象?

与您在问题中提出的用例有关...

从问题看来,如果您不想向方法中添加参数以通过流传播上下文,您可以考虑使用 ThreadLocals 作为概念上的“替代”来替换请求中各处可用的全局变量。

这仅适用于“每个请求线程”模型,它不适用于反应式系统以及在后端实现业务逻辑时维护不同线程池并切换线程的复杂情况:

因此,要在您建议的上下文持有者中实现“线程安全”,您可以使用:

@Configuration
public class MyConfig {
  @Bean
  public ThreadLocal<MyCustomContext> ctxHolder() {
     return new ThreadLocal<>();
  }
}

然后,再一次,如果您在每个请求线程模型中工作,您可以:

@Component
public class DataFetcherInterceptor {
   @Autowired
   private ThreadLocal<MyCustomContext> ctxHolder;

   public Result dataFetcher(DataFetchingEnvironment dfe) {
   

      // this context contains user details which is used for authorization
      // instantiated for every request
      setRolesInContext(dfe);
      MyCustomContext context = DgsContext.getCustomContext(dfe);
      ctxHolder.set(context);
      dataFetcherHelper(); 
   }
}

dataFetcherHelper任何需要访问上下文的方法中或一般情况下,您都可以:

public class SomeService {
   @Autowired ThreadLocal<MyCustomContext> ctxHolder;

   public void dataFetcherHelper() {
      MyCustomContext ctx = ctxHolder.get();
   }

现在,我看到这dataFetcherHelper只是你从这个“拦截器”类中调用的一个方法,在这种情况下它是一个矫枉过正的方法,但我假设,你打算这实际上是一个属于另一个类的方法,这可能是不同类的调用链中的一个元素。对于这些情况,这可能是一个可行的解决方案。

于 2021-09-01T05:56:09.950 回答