在 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();