@RefreshScope加数据库实现动态Bean刷新

1,466 阅读2分钟

在 Spring Boot 应用中,通常我们会通过配置文件来进行一些数据初始化,例如数据库连接、Redis 等配置。这些设置一般在应用启动时加载完成,通常在运行期间不会进行更改。但是,在某些特殊情况下,我们可能需要动态更改这些配置,这时涉及到 Spring Boot 中 Bean 的重新刷新问题。

      通常情况下,Spring Boot 的 Bean 在初始化时就注册完毕,其内部的配置信息在生命周期内不会再发生变更。然而,当我们需要修改这些配置信息并使其生效时,如何刷新相关的 Bean 成为了一个需要解决的问题。尽管实现这一目标的方法有很多,但本文将基于 @RefreshScope 和数据库配置来实现手动刷新 Bean,从而支持配置的动态变更。

     @RefreshScope 是 Spring Cloud 提供的一个功能注解,用于使被注解的 Bean 在运行时可以动态刷新配置。对于不熟悉 @RefreshScope 的同学,请自行查阅相关资料,这里不再详细解释。

      直接上例子,本例子是从数据库动态读取LDAP的连接配置,也适用于DB,Redeis等连接配置

@Bean
@RefreshScope
public LdapContextSource contextSource() {
    //从数据库查询配置
    LambdaQueryWrapper<SystemConfig> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.eq(SystemConfig::getConfigType, "ldap");
    List<SystemConfig> systemConfigList = systemConfigMapper.selectList(queryWrapper);
    Map<String, Object> dictMap = systemConfigList.stream().collect(HashMap::new, (map, item) -> map.put(item.getConfigName(), item.getConfigValue()), HashMap::putAll);
    //配置LDAP连接属性
    LdapContextSource contextSource = new LdapContextSource();
    Map<String, Object> config = new HashMap();
    contextSource.setUrl(dictMap.get("url").toString());
    contextSource.setBase(dictMap.get("base").toString());
    contextSource.setUserDn(dictMap.get("username").toString());
    contextSource.setPassword(dictMap.get("password").toString());

    //  解决乱码
    config.put("java.naming.ldap.attributes.binary", "objectGUID");

    //关闭ldap pooling
    contextSource.setPooled(false);
    contextSource.setBaseEnvironmentProperties(config);
    return contextSource;
}

//创建ldap的连接bean
@Bean
public LdapTemplate ldapTemplate() {
    return new LdapTemplate(contextSource());
}

      上述代码,我们从数据库读取配置,并且在初始化的时候将ldap连接进行注册。

下面是手动出发bean刷新的代码

@Component
public class RefreshService {

    private final RefreshScope refreshScope;

    @Autowired
    public RefreshService(RefreshScope refreshScope) {
        this.refreshScope = refreshScope;
    }

    public void refreshMyBean() {
        // 这里 "contextSource,userRepository" 是 @RefreshScope Bean 的名称
        refreshScope.refresh("contextSource");
        refreshScope.refresh("userRepository");
    }
}

      通过调用上述refreshMyBean()方法即可刷新bean

      因为题主需求是从页面进行配置,配置完毕即可手动触发,进行刷新,如果需要自动刷新,请参考其他方案。

//在需要触发的地方进行注入
@Resource
private RefreshService refreshService;

//直接调用即可动态从数据库读取配置,进行刷新
refreshService.refreshMyBean();