无法在 Spring Boot 应用程序中刷新现有的单例 bean

Posted

技术标签:

【中文标题】无法在 Spring Boot 应用程序中刷新现有的单例 bean【英文标题】:Unable to refresh existing singleton bean in Spring boot application 【发布时间】:2021-06-17 13:59:12 【问题描述】:

我在 Spring Boot 应用程序中定义了如下配置:

@Configuration
public class RuleEngineConfiguration 

  private final DatabaseRuleLoader databaseRuleLoader;

  public RuleEngineConfiguration(
      DatabaseRuleLoader databaseRuleLoader) 
    this.databaseRuleLoader = databaseRuleLoader;
  

  @Bean
  public RuleEngineManager ruleEngine() 
    return RuleEngineManagerFactory.getRuleEngineManager(this.databaseRuleLoader);
  

现在我想在我的 Spring Boot 应用程序中刷新 RuleEngineManager bean,以使用如下定义的刷新功能在 DB 中的给定表中创建/更新行:

public void refresh() 
    databaseRuleLoader.refresh(); <---THIS RELOADS ROWS FROM DB
    BeanDefinitionRegistry registry = (BeanDefinitionRegistry) applicationContext
        .getAutowireCapableBeanFactory();
    RuleEngineManager ruleEngineManager = RuleEngineManagerFactory
        .getRuleEngineManager(databaseRuleLoader);
    registry.removeBeanDefinition("ruleEngine");
    ((SingletonBeanRegistry) registry).registerSingleton("ruleEngine", ruleEngineManager);
  

在我的应用程序中,我需要 RuleEngineManager bean,我得到的 bean 如下:

((RuleEngineManager) applicationContext.getBean("ruleEngine"))

即使每次都执行刷新功能,我正在创建/更新数据库中的任何行,但是,我没有看到任何变化。似乎现有的 RuleEnginemanager bean 正在作为依赖项注入。我无法弄清楚我在这里缺少什么。

有人可以帮忙吗?谢谢。

【问题讨论】:

我的意思是,这不是一个解决方案,但是为那个对象创建一个工厂,并使用 DI 注入工厂,这样当你想要这个对象时,你就像factory.generate() 和你有一个新的新鲜对象? (您可以自己实现延迟加载/缓存/刷新逻辑) @AlbertoSinigaglia 感谢您的回复。对不起,我不能理解太多。您能否通过提供一个代码 sn-p 来简要说明一下,我可以从中得到一个想法? 【参考方案1】:

我的建议是使用工厂(设计模式)...例如以这种方式:

// you already have this class
public class RuleEngineManagerFactory 
   private DatabaseRuleLoader databaseRuleLoader;
   private RuleEngineManager ruleEngineManager;
   public RuleEngineManagerFactory(DatabaseRuleLoader databaseRuleLoader) 
     this.databaseRuleLoader = databaseRuleLoader;
   
   public RuleEngineManager getRuleEngineManager()
     if(this.ruleEngineManager == null)
         ruleEngineManager = new RuleEngineManager(this.databaseRuleLoader);
     
     return this.ruleEngineManager;
   
   public void refresh()
      ruleEngineManager = new RuleEngineManager(this.databaseRuleLoader);
   

这样,你将在任何你需要的地方注入RuleEngineManagerFactory,并且你可以刷新RuleEngineManager...所以你必须为经理的工厂有一个单例,而不是经理本身

【讨论】:

以上是关于无法在 Spring Boot 应用程序中刷新现有的单例 bean的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot JMS 侦听器:无法刷新目标的 JMS 连接

Spring Boot 2 重新部署到 Wildfly 10 后无法刷新 JMS 连接

在 Spring Boot Web 应用程序中刷新后的 Whitelabel 错误页面

将 Spring boot 1.5 迁移到 2.x 无法启动应用程序

在 Spring Boot 应用程序中修改活动配置文件并刷新 ApplicationContext 运行时

带有休眠应用程序的 Spring Boot 无法启动