XML 配置多套 DataSource、SqlSessionFactory、TransactionManager、事務代理,從庫增加時配置膨脹,違背「約定優於配置」。
GitHub:bridgeli/practical-util(cn.bridgeli.datasource 包)
AbstractRoutingDataSource,運行期動態切換目標 DataSource。@Before 切面,根據方法名前綴決定走主/從庫。<!-- 主庫 -->
<bean id="masterDataSource" class="com.alibaba.druid.pool.DruidDataSource">...</bean>
<!-- 從庫(父子 Bean 復用通用參數) -->
<bean id="parentSlaveDataSource" class="com.alibaba.druid.pool.DruidDataSource" abstract="true">...</bean>
<bean id="slaveDataSource1" parent="parentSlaveDataSource">
<property name="url" value="${bridgeli_slave1.jdbc.url}"/> ...
</bean>
<!-- 路由 DataSource -->
<bean id="dataSource" class="cn.bridgeli.datasource.MasterSlaveDataSource">
<property name="targetDataSources">
<map>
<entry key-ref="masterDataSource" value-ref="masterDataSource"/>
<entry key-ref="slaveDataSource1" value-ref="slaveDataSource1"/>
</map>
</property>
<property name="defaultTargetDataSource" ref="masterDataSource"/>
<property name="masterSlaveSelector" ref="dataSelector"/>
</bean>
<bean id="dataSelector" class="cn.bridgeli.datasource.MasterSlaveSelectorByPoll">
<property name="masters"><list><ref bean="masterDataSource"/></list></property>
<property name="slaves"><list><ref bean="slaveDataSource1"/></list></property>
<property name="defaultDataSource" ref="masterDataSource"/>
</bean>
<!-- AOP 切面:方法名前綴判斷 -->
<bean id="masterSlaveAspect" class="cn.bridgeli.datasource.MasterSlaveAspect">
<property name="prefixMasters">
<list><value>save</value><value>update</value><value>delete</value></list>
</property>
</bean>
<aop:config>
<aop:aspect id="c" ref="masterSlaveAspect">
<aop:pointcut id="tx" expression="execution(* cn.bridgeli.service..*.*(..))"/>
<aop:before pointcut-ref="tx" method="before"/>
</aop:aspect>
</aop:config>
prefixMasters 添加前綴,**零代碼侵入**,體現「約定優於配置」。Service 代表業務邊界,事務天然在這一層;DAO 層無法感知業務讀寫意圖。