由於我們系統舊環境沒有用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();
}
}