You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot:如何让@Configuration的@Bean方法每次调用都重新执行?

解决Spring中Bean配置实时更新的问题

你的问题根源在于Spring默认将Map<Long,Long>作为单例Bean管理,只会在容器启动时调用一次provideTierConfigurations方法初始化,后续即使TierDAL中的Map更新了,TierCalculator持有的还是初始化时的旧副本。以下是几种可行的解决方式:

方案一:直接注入TierDAL,按需获取最新配置

这是最简单直接的方式,跳过将Map作为Bean的步骤,让TierCalculator直接调用TierDAL的方法获取最新配置:

@Component
public class TierCalculator {

   private final TierDAL tierDAL;

   // 推荐构造注入而非Setter注入
   public TierCalculator(TierDAL tierDAL) {
      this.tierDAL = tierDAL;
   }

   // 每次需要配置时,直接获取最新副本
   public void calculateTier(Long userId) {
       Map<Long, Long> latestTierConfig = tierDAL.getTierConfigurations();
       // 使用最新配置进行计算逻辑
   }
}

这种方式的优势是避免Spring Bean作用域的复杂度,只要TierDAL#getTierConfigurations能返回最新数据,TierCalculator就能拿到最新配置。如果DAL内部已经做了缓存(比如本地缓存或分布式缓存),这种方式的性能开销可以忽略。

方案二:将Map Bean改为原型作用域,用Provider按需获取

如果必须通过Spring Bean来提供配置,可以将Map的作用域改为原型(prototype),这样每次从容器获取该Bean时,都会重新执行provideTierConfigurations方法生成新的实例。配合javax.inject.Provider(或Spring的ObjectProvider)来实现按需获取:

第一步:修改ConfigurationProvider的Bean作用域

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration 
public class ConfigurationProvider {

   @Bean
   @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) // 设置为原型作用域
   Map<Long, Long> provideTierConfigurations(TierDAL dal) {
        return dal.getTierConfigurations();
   }
}

第二步:修改TierCalculator注入Provider

import javax.inject.Provider;
import org.springframework.stereotype.Component;

@Component
public class TierCalculator {

   private final Provider<Map<Long, Long>> tierConfigProvider;

   public TierCalculator(Provider<Map<Long, Long>> tierConfigProvider) {
      this.tierConfigProvider = tierConfigProvider;
   }

   public void calculateTier(Long userId) {
       // 每次调用get()都会获取最新的Map实例
       Map<Long, Long> latestTierConfig = tierConfigProvider.get();
       // 执行计算逻辑
   }
}

注意:原型作用域的Bean每次获取都会生成新实例,这里因为是Map对象,创建和销毁的开销很小,所以可以放心使用。

方案三:定时刷新配置缓存(适合高开销场景)

如果TierDAL#getTierConfigurations的调用开销较大(比如需要远程调用数据库或第三方服务),可以实现一个定时刷新的缓存Holder,平衡实时性和性能:

第一步:创建配置Holder组件

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

@Component
public class TierConfigHolder {

    private final TierDAL tierDAL;
    private final AtomicReference<Map<Long, Long>> configCache;

    public TierConfigHolder(TierDAL tierDAL) {
        this.tierDAL = tierDAL;
        // 初始化缓存
        this.configCache = new AtomicReference<>(tierDAL.getTierConfigurations());
    }

    // 定时刷新缓存,比如每5分钟执行一次(单位:毫秒)
    @Scheduled(fixedRate = 300000)
    public void refreshConfig() {
        Map<Long, Long> newConfig = tierDAL.getTierConfigurations();
        configCache.set(newConfig);
    }

    // 对外提供获取最新配置的方法
    public Map<Long, Long> getLatestConfig() {
        return configCache.get();
    }
}

第二步:修改TierCalculator注入Holder

@Component
public class TierCalculator {

   private final TierConfigHolder tierConfigHolder;

   public TierCalculator(TierConfigHolder tierConfigHolder) {
      this.tierConfigHolder = tierConfigHolder;
   }

   public void calculateTier(Long userId) {
       Map<Long, Long> latestTierConfig = tierConfigHolder.getLatestConfig();
       // 执行计算逻辑
   }
}

这种方式需要开启Spring的定时任务支持,在配置类上添加@EnableScheduling注解即可。


内容的提问来源于stack exchange,提问作者Shvalb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 15:08:19