Spring Boot怎么实现配置任意数量Mongodb数据源

Spring Boot怎么实现配置任意数量Mongodb数据源

本文会教大家如何按需配置MongoDB数据源,代码写完后,支持配置任意数量的MongDB数据源,只需要根据运维需要手动增加数据源的配置,不需要再修改代码。

如果大家只想了解配置1个或有限数量的多个数据源,可以参考另一篇文章: 【Spring Boot怎么实现配置多个Mongodb数据源】, 里面有简单的示例代码帮助大家理解。

环境介绍

软件名称软件版本
Spring Boot2.5.3
Maven3.6.3
MongoDB4.2.5

多个数据源如何在配置文件中配置

在Java中,能动态存放未知数量元素的容器叫集合,我们使用List来存放MongDB数据源配置,List在配置文件中是以数组的方式进行配置

spring.data.mongodb.xxx[0].uri: mongodb://localhost:27017/Teach"
spring.data.mongodb.xxx[1].uri: mongodb://localhost:27017/Teach1"
                 ...
                 ...
spring.data.mongodb.xxx[n].uri: mongodb://localhost:27017/Teachn"

动态注册Bean

【Spring Boot怎么实现配置多个Mongodb数据源】在这篇文章中介绍了MongoTemplate对象的创建,但使用的是**@Bean注解手工创建Bean**,这种方式只能创建预先定义好的数据源,无法解决动态创建Bean的目的。

BeanDefinitionRegistry介绍

通过Spring Boot源码可以知道,BeanDefinitionRegistry这个类可以通过registerBeanDefinition()方法注册一个BeanDefinition对象

beanDefinitionRegistry.registerBeanDefinition("xxx"+i, mongoTemplateDefinition);

如何构造BeanDefinition

借助BeanDefinitionBuilder这个类genericBeanDefinition()这个方法可以帮助我们比较容易的创建一个BeanDefinition

BeanDefinition mongoTemplateDefinition = BeanDefinitionBuilder
		.genericBeanDefinition(MongoTemplate.class, ()->mongoTemplate)
		.getBeanDefinition();

完整代码

到了这一步,可以看到,只要能构造MongoTemplate对象,就能把整个动态注册Bean的逻辑串起来了,接下来看一下通过读取自定义数据源配置动态注册Bean的完整代码

package com.etomy.teach.mongodb.properties;

import java.util.List;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
import org.springframework.util.CollectionUtils;

@ConditionalOnProperty(name = "spring.data.mongodb.xxx[0].uri")
@Configuration
@ConfigurationProperties(prefix="spring.data.mongodb")
public class MgoConfigurationAny implements InitializingBean {
	
	private @Autowired ConfigurableApplicationContext context;
	
	private List<MongoProperties> xxx;

	public void setXxx(List<MongoProperties> xxx) {
		this.xxx = xxx;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		if(CollectionUtils.isEmpty(xxx)) {
			return;
		}
		
		BeanDefinitionRegistry beanDefinitionRegistry = (BeanDefinitionRegistry) context;

		for(int i=0; i<xxx.size(); ++i) {
			MongoTemplate mongoTemplate = new MongoTemplate(new SimpleMongoClientDatabaseFactory(xxx.get(i).getUri()));
			BeanDefinition mongoTemplateDefinition = BeanDefinitionBuilder
					.genericBeanDefinition(MongoTemplate.class, ()->mongoTemplate)
					.getBeanDefinition();

			String beanName = "xxx"+i+"MongoTemplate";
			beanDefinitionRegistry.registerBeanDefinition(beanName, mongoTemplateDefinition);
		}
	}
}

编写单元测试代码

package com.etomy.teach.mongodb.properties;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.test.context.TestPropertySource;

import com.etomy.teach.mongodb.SpringbootTestBase;

@TestPropertySource(properties = {
		"spring.data.mongodb.xxx[0].uri: mongodb://localhost:27017/Teach1",
		"spring.data.mongodb.xxx[1].uri: mongodb://localhost:27017/Teach2"
})
public class MgoConfigurationAnyTest extends SpringbootTestBase {

	@Qualifier("xxx0MongoTemplate")
	private @Autowired MongoTemplate xxx1MongoTemplate;
	
	@Qualifier("xxx1MongoTemplate")
	private @Autowired MongoTemplate xxx2MongoTemplate;
	
	@Test
	public void testAnyMongodb() {
		xxx1MongoTemplate.insert(buildMgoMessage());
		xxx2MongoTemplate.insert(buildMgoMessage());
	}
}

核对数据

分别连上配置的数据源,然后查看数据是否成功插入

> db.DemoMessage.find().sort({sendTime:-1}).limit(1);
{ "_id" : "eb6a5b12-2b36-4f14-a50f-99275141e651", "from" : "张三", "to" : "李四", "content" : "hello, nice to meet you!", "sendTime" : NumberLong("1628315176800"), "_class" : "com.etomy.teach.mongodb.entity.MgoMessage" }
>

数据插入成功,测试通过。以上就是动态数据源配置的实现。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

太空眼睛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值