Spring动态切换多数据源解决方案
时间:2015-05-13 16:25:22
收藏:0
阅读:198
本文章摘编、转载需要注明来源 http://blog.csdn.net/shadowsick/article/details/8878448
我们很多项目中业务都需要涉及到多个数据源,最简单的做法就是直接在java代码里面lookup需要的数据源,但是这样的做法很明显耦合度太高了,
而且当逻辑流程不够严谨的时候就会出现各种大家不愿意看到的问题,由于我们现在的大多项目已经离不开spring了,spring也提供各种强大的功能,
很明显这种动态数据源功能也包括在内,具体实现类请看org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource
这里我演示下如何使用spring提供的动态数据源
先写个接口,default设置为null是因为当程序里没有找到相关联的源就会调用默认源
[java] view plaincopyprint?
01./**
02. * 数据源切换接口
03. *
04. * @author shadow
05. * @create 2013.04.03
06. */
07.public interface DataSourceEntry {
08.
09. // 默认数据源
10. public final static String DEFAULT_SOURCE = null;
11.
12. /**
13. * 还原数据源
14. *
15. * @param joinPoint
16. */
17. public void restore(JoinPoint join);
18.
19. /**
20. * 设置数据源
21. *
22. * @param dataSource
23. */
24. public void set(String source);
25.
26. /**
27. * 获取数据源
28. *
29. * @return String
30. */
31. public String get();
32.
33. /**
34. * 清空数据源
35. */
36. public void clear();
37.}
/**
* 数据源切换接口
*
* @author shadow
* @create 2013.04.03
*/
public interface DataSourceEntry {
// 默认数据源
public final static String DEFAULT_SOURCE = null;
/**
* 还原数据源
*
* @param joinPoint
*/
public void restore(JoinPoint join);
/**
* 设置数据源
*
* @param dataSource
*/
public void set(String source);
/**
* 获取数据源
*
* @return String
*/
public String get();
/**
* 清空数据源
*/
public void clear();
}
然后写个实现类,从当前线程里取出对应的数据源名
[java] view plaincopyprint?
01./**
02. * 数据源切换实现类类
03. *
04. * @author shadow
05. * @create 2013.04.03
06. */
07.public class DataSourceEntryImpl implements DynamicTypeEntry {
08.
09. private final static ThreadLocal local = new ThreadLocal();
10.
11. public void clear() {
12. local.remove();
13. }
14.
15. public String get() {
16. return local.get();
17. }
18.
19. public void restore(JoinPoint join) {
20. local.set(DEFAULT_SOURCE);
21. }
22.
23. public void set(String source) {
24. local.set(source);
25. }
26.
27.}
/**
* 数据源切换实现类类
*
* @author shadow
* @create 2013.04.03
*/
public class DataSourceEntryImpl implements DynamicTypeEntry {
private final static ThreadLocal local = new ThreadLocal();
public void clear() {
local.remove();
}
public String get() {
return local.get();
}
public void restore(JoinPoint join) {
local.set(DEFAULT_SOURCE);
}
public void set(String source) {
local.set(source);
}
}
然后写个继承AbstractRoutingDataSource的类,并注入DataSourceEntry,重写determineCurrentLookupKey模版方法
[java] view plaincopyprint?
01./**
02. * 获取数据源(依赖SPRING框架)
03. *
04. * @author shadow
05. * @create 2013.04.03
06. */
07.public class DynamicDataSource extends AbstractRoutingDataSource {
08.
09. private DataSourceEntry dataSourceEntry;
10.
11. @Override
12. protected Object determineCurrentLookupKey() {
13. return this.dataSourceEntry.get();
14. }
15.
16. @Resource
17. public void setDataSourceEntry(DataSourceEntry dataSourceEntry) {
18. this.dataSourceEntry = dataSourceEntry;
19. }
20.
21.}
/**
* 获取数据源(依赖SPRING框架)
*
* @author shadow
* @create 2013.04.03
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
private DataSourceEntry dataSourceEntry;
@Override
protected Object determineCurrentLookupKey() {
return this.dataSourceEntry.get();
}
@Resource
public void setDataSourceEntry(DataSourceEntry dataSourceEntry) {
this.dataSourceEntry = dataSourceEntry;
}
}
最后就是配置下xml文件,以后只需要直接管理dynamicDataSource这个接口就可以了,至于他内部是哪个数据源是不需要关注,写的切面还原是为了保证每次调用完另外的数据源
都会还原成默认数据源,防止有的人忘记设置回默认的,导致其他代码出问题
[java] view plaincopyprint?
01.
02.
04.
05.
06.
07.
08.
10.
11. classpath:properties/jdbc.properties
12.
13.
14.
15.
16.
18.
19.
20.
24.
25.
26.
27.
28.
29.
31.
32. false
33.
34.
35. ${JNDI.template}
36.
37.
38.
39.
40.
42.
43. false
44.
45.
46. ${JNDI.test}
47.
48.
49.
50.
51.
53.
54.
55.
56.
58.
60.
61.
classpath:properties/jdbc.properties
false
${JNDI.template}
false
${JNDI.test}
至于程序里如何变换数据源,你可以在切面上检测哪些方法加入before方法,或者在程序里直接使用DataSourceEntry调用set方法,具体的怎么用不作代码说明了
评论(0)