springboot多資料來源配置

余下的那一页發表於2024-04-15

由於我們系統舊環境沒有用springboot自帶的多資料來源功能,使用了自己配置的多資料來源。

新增自定義資料來源註解

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DynDatasource {
Module value() default Module.DEF;
}

註解掃描

public CheckoutDatasourceAspect() {
}

@Around("@within(com.midea.cloud.dynamicds.aop.anno.DynDatasource)")
public Object checkoutDatasource(ProceedingJoinPoint joinPoint) throws Throwable {
Object var5;
try {
MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
DynDatasource dynDatasource = (DynDatasource)methodSignature.getMethod().getDeclaredAnnotation(DynDatasource.class);
if (dynDatasource == null) {
dynDatasource = (DynDatasource)methodSignature.getDeclaringType().getDeclaredAnnotation(DynDatasource.class);
}

CheckModuleHolder.checkout(dynDatasource.value());
Object object = joinPoint.proceed();
var5 = object;
} catch (Throwable var9) {
throw var9;
} finally {
CheckModuleHolder.release();
}

return var5;
}
}

掃描配置包下的內容,自動載入
@Configuration
@EnableConfigurationProperties({DynamicDatasourceConfigProperties.class})
@ComponentScan({"com.midea.cloud.dynamicds"})
public class DynamicDatasourceAutoConfiguration {
@Autowired
private DynamicDatasourceConfigProperties dynamicDatasourceConfigProperties;

public DynamicDatasourceAutoConfiguration() {
}

@Bean
@ConditionalOnMissingBean
@ConditionalOnClass({DynamicDatasource.class})
public DataSource dataSource() {
DynamicDatasource dynamicDatasource = new DynamicDatasource();
dynamicDatasource.setDynamicDatasourceConfigProperties(this.dynamicDatasourceConfigProperties);
return dynamicDatasource;
}
}

根據啟動註解掃描載入對應的配置資訊
獲取yml檔案中指定的配置資訊
@ConfigurationProperties(
prefix = "cloud.scc.dynamic"
)
public class DynamicDatasourceConfigProperties {
private Module defaultModule;
private Map<Module, Map<String, Object>> datasouces;

public DynamicDatasourceConfigProperties() {
}

public Module getDefaultModule() {
return this.defaultModule;
}

public void setDefaultModule(Module defaultModule) {
this.defaultModule = defaultModule;
}

public Map<Module, Map<String, Object>> getDatasouces() {
return this.datasouces;
}

public void setDatasouces(Map<Module, Map<String, Object>> datasouces) {
this.datasouces = datasouces;
}
}

這裡讀取配置新的詳情,重寫springframework中的AbstractDataSource類,讀取資料庫詳細配置資訊
public abstract class AbstractDataSource implements DataSource {
protected final Log logger = LogFactory.getLog(this.getClass());

public AbstractDataSource() {
}

public int getLoginTimeout() throws SQLException {
return 0;
}

public void setLoginTimeout(int timeout) throws SQLException {
throw new UnsupportedOperationException("setLoginTimeout");
}

public PrintWriter getLogWriter() {
throw new UnsupportedOperationException("getLogWriter");
}

public void setLogWriter(PrintWriter pw) throws SQLException {
throw new UnsupportedOperationException("setLogWriter");
}

public <T> T unwrap(Class<T> iface) throws SQLException {
if (iface.isInstance(this)) {
return this;
} else {
throw new SQLException("DataSource of type [" + this.getClass().getName() + "] cannot be unwrapped as [" + iface.getName() + "]");
}
}

public boolean isWrapperFor(Class<?> iface) throws SQLException {
return iface.isInstance(this);
}

public Logger getParentLogger() {
return Logger.getLogger("global");
}
}

配置啟動類掃描註解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import({DynamicDatasourceAutoConfiguration.class})
public @interface EnableDynamicDatasource {
}

根據註解自動載入對應的資料庫。
public class CheckModuleHolder {
public static ThreadLocal<Module> moduleThreadLocal = new ThreadLocal();

public CheckModuleHolder() {
}

public static void checkout(Module module) {
moduleThreadLocal.set(module);
}

public static void release() {
moduleThreadLocal.remove();
}

public static Module get() {
return (Module)moduleThreadLocal.get();
}
}

相關文章