多数据源
程序员文章站
2022-07-15 10:10:38
...
下看一下Spring 中如何处理数据源,源代码如下:
public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {
private Map<Object, Object> targetDataSources;
private Object defaultTargetDataSource;
private boolean lenientFallback = true;
private DataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
private Map<Object, DataSource> resolvedDataSources;
private DataSource resolvedDefaultDataSource;
public void setDataSourceLookup(DataSourceLookup dataSourceLookup) {
this.dataSourceLookup = (dataSourceLookup != null ? dataSourceLookup : new JndiDataSourceLookup());
}
protected DataSource determineTargetDataSource() {
Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
Object lookupKey = determineCurrentLookupKey();
DataSource dataSource = this.resolvedDataSources.get(lookupKey);
if (dataSource == null && (this.lenientFallback || lookupKey == null)) {
dataSource = this.resolvedDefaultDataSource;
}
if (dataSource == null) {
throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
}
return dataSource;
}
protected abstract Object determineCurrentLookupKey();
}
Spring中的抽象通用数据源类的部分代码,其中包含determineTargetDataSource()方法,调用本类的抽象方法determineCurrentLookupKey(),得到 lookupKey,通过该值设置数据源。所以可以通过继承该类,然后重写该方法实现数据源的切换。
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import myPath.DataSourceHolder;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
// TODO Auto-generated method stub
return DataSourceHolder.getDataSource();
}
@Override
public void setTargetDataSources(Map<Object, Object> targetDataSources) {
// TODO Auto-generated method stub
super.setTargetDataSources(targetDataSources);
}
}
DataSourceHolder持有当前的数据源,有setter/getter/clear方法
public class DataSourceHolder {
//线程本地环境
private static final ThreadLocal<String> dataSources = new ThreadLocal<String>();
//设置数据源
public static void setDataSource(String customerType) {
dataSources.set(customerType);
}
//获取数据源
public static String getDataSource() {
return (String) dataSources.get();
}
//清除数据源
public static void clearDataSource() {
dataSources.remove();
}
}
定义一个注解,使其完成数据源的切换
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DataChange {
String value()default "";
}
设置切面和切入点
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
//import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import mypath.DataSourceHolder;
@Aspect
@Order(1)
@Component
@Scope("prototype")
public class UseMysql{
@Before("execution(@Class's.Path.DataChange * service.impl.*.*(..))")
public void dataSourceChange() throws Throwable{
DataSourceHolder.setDataSource("dataSourcemy");
/*这里根据用户的类型来更改对应的数据源*/
}
@After("execution(@Class's.Path.DataChange * service.impl.*.*(..))")
public void dataSourceclear() throws Throwable{
DataSourceHolder.clearDataSource();
}
}
使用
@DataChange
public Type method(int id) throws IOException {
return type;
}