简体   繁体   English

Spring 自定义 Scope,定时刷新 bean

[英]Spring custom Scope with timed refresh of beans

I am working within an environment that changes credentials every several minutes.我在一个每隔几分钟更改一次凭据的环境中工作。 In order for beans that implement clients who depend on these credentials to work, the beans need to be refreshed.为了使实现依赖于这些凭据的客户端的 bean 工作,需要刷新 bean。 I decided that a good approach for that would be implementing a custom scope for it.我决定为它实现自定义范围是一个很好的方法。 After looking around a bit on the documentation I found that the main method for a scope to be implemented is the get method:在查看文档后,我发现要实现的范围的主要方法是get方法:

public class CyberArkScope implements Scope {

  private Map<String, Pair<LocalDateTime, Object>> scopedObjects = new ConcurrentHashMap<>();
  private Map<String, Runnable> destructionCallbacks = new ConcurrentHashMap<>();
  private Integer scopeRefresh;


  public CyberArkScope(Integer scopeRefresh) {
    this.scopeRefresh = scopeRefresh;
  }

  @Override
  public Object get(String name, ObjectFactory<?> objectFactory) {
    if (!scopedObjects.containsKey(name) || scopedObjects.get(name).getKey()
        .isBefore(LocalDateTime.now().minusMinutes(scopeRefresh))) {
      scopedObjects.put(name, Pair.of(LocalDateTime.now(), objectFactory.getObject()));
    }
    return scopedObjects.get(name).getValue();
  }

  @Override
  public Object remove(String name) {
    destructionCallbacks.remove(name);
    return scopedObjects.remove(name);
  }

  @Override
  public void registerDestructionCallback(String name, Runnable runnable) {
    destructionCallbacks.put(name, runnable);
  }

  @Override
  public Object resolveContextualObject(String name) {
    return null;
  }

  @Override
  public String getConversationId() {
    return "CyberArk";
  }
}

@Configuration
@Import(CyberArkScopeConfig.class)
public class TestConfig {
  @Bean
  @Scope(scopeName = "CyberArk")
  public String dateString(){
    return LocalDateTime.now().toString();
  }
}

@RestController
public class HelloWorld {

    @Autowired
    private String dateString;

    @RequestMapping("/")
    public String index() {
        return dateString;
    }
}

When I debug this implemetation with a simple String scope autowired in a controller I see that the get method is only called once in the startup and never again.当我使用控制器中自动装配的简单字符串范围调试此实现时,我看到 get 方法仅在启动时调用一次,再也不会调用。 So this means that the bean is never again refreshed.所以这意味着 bean 永远不会再次刷新。 Is there something wrong in this behaviour or is that how the get method is supposed to work?这种行为是否有问题,或者 get 方法应该如何工作?

It seems you need to also define the proxyMode which injects an AOP proxy instead of a static reference to a string.似乎您还需要定义 proxyMode 来注入 AOP 代理而不是对字符串的静态引用。 Note that the bean class cant be final.请注意,bean 类不能是最终的。 This solved it:这解决了它:

@Configuration
@Import(CyberArkScopeConfig.class)
public class TestConfig {
  @Bean
  @Scope(scopeName = "CyberArk", proxyMode=ScopedProxyMode.TARGET_CLASS)
  public NonFinalString dateString(){
    return new NonFinalString(LocalDateTime.now());
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM