@Autowired
@Qualifier("writeDataSource")
private DataSource writeDataSource;
@Bean("txManager")
public DataSourceTransactionManager txManager(@Qualifier("roundRobinDataSouceProxy") DataSource roundRobinDataSouceProxy) {
return new DataSourceTransactionManager(roundRobinDataSouceProxy);
}
讀寫路由
/**
* 把所有數據庫都放在路由中
*
* @return
*/
@Bean(name = "roundRobinDataSouceProxy")
public AbstractRoutingDataSource roundRobinDataSouceProxy() {
Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
//把所有數據庫都放在targetDataSources中,注意key值要和determineCurrentLookupKey()中代碼寫的一至,
//否則切換數據源時找不到正確的數據源
targetDataSources.put(DataSourceType.write.getType(), writeDataSource);
targetDataSources.put(DataSourceType.read.getType(), readDataSource);
//路由類,尋找對應的數據源
AbstractRoutingDataSource proxy = new AbstractRoutingDataSource() {
/**
* 這是AbstractRoutingDataSource類中的一個抽象方法,
* 而它的返回值是你所要用的數據源dataSource的key值,有了這個key值,
* targetDataSources就從中取出對應的DataSource,如果找不到,就用配置默認的數據源。
*/
@Override
protected Object determineCurrentLookupKey() {
String typeKey = DataSourceContextHolder.getReadOrWrite();
if (typeKey == null) {
System.err.println("使用數據庫write.............");
return DataSourceType.write.getType();
}
if (typeKey.equals(DataSourceType.write.getType())) {
System.err.println("使用數據庫write.............");
return DataSourceType.write.getType();
}
//讀庫, 簡單負載均衡
System.err.println("使用數據庫read");
return DataSourceType.read.getType();
}
};
//默認庫
proxy.setDefaultTargetDataSource(writeDataSource);
proxy.setTargetDataSources(targetDataSources);
return proxy;
}
/**
* 在service層覺得數據源
*
* 必須在事務AOP之前執行,所以實現Ordered,order的值越小,越先執行
* 如果一旦開始切換到寫庫,則之后的讀都會走寫庫
*
*/
@Aspect
@EnableAspectJAutoProxy(exposeProxy=true,proxyTargetClass=true)
@Component
public class DataSourceAopInService implements PriorityOrdered{
//private static Logger log = LoggerFactory.getLogger(DataSourceAopInService.class);
@Before("execution(* net.vipmro.hades.boss.service..*.find*(..)) "
+ " or execution(* net.vipmro.hades.boss..*.get*(..)) "
+ " or execution(* net.vipmro.hades.boss..*.select*(..)) "
+ " or execution(* net.vipmro.hades.boss..*.search*(..)) "
+ " or execution(* net.vipmro.hades.boss..*.query*(..))")
public void setReadDataSourceType() {
//如果已經開啟寫事務了,那之后的所有讀都從寫庫讀
if(!DataSourceType.write.getType().equals(DataSourceContextHolder.getReadOrWrite())){
DataSourceContextHolder.setRead();
}
}
@Before("execution(* net.vipmro.hades.boss..*.insert*(..)) "
+ " or execution(* net.vipmro.hades.boss..*.update*(..))"
+ " or execution(* net.vipmro.hades.boss..*.save*(..))"
+ " or execution(* net.vipmro.hades.boss..*.del*(..))"
+ " or execution(* net.vipmro.hades.boss..*.add*(..))")
public void setWriteDataSourceType() {
DataSourceContextHolder.setWrite();
}
@Override
public int getOrder() {
/**
* 值越小,越優先執行
* 要優於事務的執行
* 在啟動類中加上了@EnableTransactionManagement(order = 10)
*/
return 1;
}
}