-
Notifications
You must be signed in to change notification settings - Fork 8
Description
学习 Spring 源码时,看到王福强老师的下面这篇文章。感觉这个技术方案,我们也可以用。尝试实现一下。
对双数据源互换实现的改进(improve to 2-dataSource swapping) - 扶墙老师说:一个架构士的思考与沉淀
好久没有写blog了,随便找一个话题吧!就从原来的那个双数据源互换的问题说起吧!
下图是当时的实现演示(图片来自SpringIDE的BeanView):
当时是使用了Spring提供的 org.springframework.jdbc.datasource.DelegatingDataSource
类,使他拥有两个数据源的引用,默认的 targetDataSource
指向第一个数据源,当 ThrowsAdvice
捕获异常之后,重新替换掉 targetDataSource
指向的数据源引用。我不确定这种方式是否是最好的,但是好像某些情况下不是很可靠,所以,后来改为了以下的实现形式:
现在我们采用Spring提供的 org.springframework.aop.target.HotSwappableTargetSource
类,构造的时候就直接让其默认为第一个数据源,bean的配置类似于:
<bean id="hotSwapTarget" class="org.springframework.aop.target.HotSwappableTargetSource">
<constructor-arg><ref bean="dataSourcePrimary"/></constructor-arg>
</bean>
有了TargetSource之后,我们就可以使用 ProxyFactoryBean
将其包装起来,给外层引用了,但是在这之前,我们要实现我们的主要功能,即某一个数据源崩溃之后,我们要马上切换到可用的数据源:
targetSource.swap(isPrimaryUsed?slave:primary);
isPrimaryUsed = !isPrimaryUsed;
这样,我们所有需要准备的都ok了,最后要做的就是组装 TargetSource
和 Advice
了。下面就简单得罗列部分配置,或许更能帮助大家了解SpringAop的使用:
<bean id="swapThrowsAdvice" class="com.livedoor.finance.credit.ivr.aspects.SwapSourceThrowsAdvice">
<property name="primary"><ref bean="dataSourcePrimary"/></property>
<property name="slave"><ref bean="dataSourceSecondary"/></property>
<property name="targetSource"><ref bean="hotSwapTarget"/></property>
</bean>
<bean id="swapThrowsAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice"><ref local="swapThrowsAdvice"/></property>
<property name="pattern"><value>.*getConnection.*</value></property>
</bean>
<bean id="dataSource" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetSource">
<ref bean="hotSwapTarget"/>
</property>
<property name="interceptorNames">
<list>
<value>swapThrowsAdvisor</value>
</list>
</property>
</bean>
这样,最终外层所引用的dataSource就可以在某个数据源崩溃之后,直接切换到可用的备用数据源,而这些都在Proxy 内部屏蔽掉了,客户端无需关心这些。
好了,今天就扯这些,呵呵