MySQL读写分离事务策略实现
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                MySQL读写分离事务策略实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                事務策略
之前的實現,是將通過方法名匹配 
 而不是使用事務策略中的定義
可以使用事務管理策略中的規則匹配 
 需要修改兩個地方
定義切面 
 定義數據源的AOP切面
定義切面
<!-- 定義AOP切面處理器 --> <bean class="cn.itcast.usermanage.spring.DataSourceAspect" id="dataSourceAspect"><!-- 指定事務策略 --><property name="txAdvice" ref="txAdvice" /><!-- 指定slave方法的前綴(非必須) --><property name="slaveMethodStart" value="query,find,get" /> </bean>DataSourceAspect
定義數據源的AOP切面
import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Map;import org.apache.commons.lang3.StringUtils; import org.aspectj.lang.JoinPoint; import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource; import org.springframework.transaction.interceptor.TransactionAttribute; import org.springframework.transaction.interceptor.TransactionAttributeSource; import org.springframework.transaction.interceptor.TransactionInterceptor; import org.springframework.util.PatternMatchUtils; import org.springframework.util.ReflectionUtils;/*** 定義數據源的AOP切面,該類控制了使用Master還是Slave。* * 如果事務管理中配置了事務策略,則采用配置的事務策略中的標記了ReadOnly的方法是用Slave,其它使用Master。* * 如果沒有配置事務管理的策略,則采用方法名匹配的原則,以query、find、get開頭方法用Slave,其它用Master。**/ public class DataSourceAspect {private List<String> slaveMethodPattern = new ArrayList<String>();private static final String[] defaultSlaveMethodStart = new String[]{ "query", "find", "get" };private String[] slaveMethodStart;/*** 讀取事務管理中的策略* * @param txAdvice* @throws Exception*/@SuppressWarnings("unchecked")public void setTxAdvice(TransactionInterceptor txAdvice) throws Exception {if (txAdvice == null) {// 沒有配置事務管理策略return;}//從txAdvice獲取到策略配置信息TransactionAttributeSource transactionAttributeSource = txAdvice.getTransactionAttributeSource();if (!(transactionAttributeSource instanceof NameMatchTransactionAttributeSource)) {return;}//使用反射技術獲取到NameMatchTransactionAttributeSource對象中的nameMap屬性值NameMatchTransactionAttributeSource matchTransactionAttributeSource = (NameMatchTransactionAttributeSource) transactionAttributeSource;Field nameMapField = ReflectionUtils.findField(NameMatchTransactionAttributeSource.class, "nameMap");nameMapField.setAccessible(true); //設置該字段可訪問//獲取nameMap的值Map<String, TransactionAttribute> map = (Map<String, TransactionAttribute>) nameMapField.get(matchTransactionAttributeSource);//遍歷nameMapfor (Map.Entry<String, TransactionAttribute> entry : map.entrySet()) {if (!entry.getValue().isReadOnly()) {//判斷之后定義了ReadOnly的策略才加入到slaveMethodPatterncontinue;}slaveMethodPattern.add(entry.getKey());}}/*** 在進入Service方法之前執行* * @param point 切面對象*/public void before(JoinPoint point) {// 獲取到當前執行的方法名String methodName = point.getSignature().getName();boolean isSlave = false;if (slaveMethodPattern.isEmpty()) {// 當前Spring容器中沒有配置事務策略,采用方法名匹配方式isSlave = isSlave(methodName);} else {// 使用策略規則匹配for (String mappedName : slaveMethodPattern) {if (isMatch(methodName, mappedName)) {isSlave = true;break;}}}if (isSlave) {// 標記為讀庫DynamicDataSourceHolder.markSlave();} else {// 標記為寫庫DynamicDataSourceHolder.markMaster();}}/*** 判斷是否為讀庫* * @param methodName* @return*/private Boolean isSlave(String methodName) {// 方法名以query、find、get開頭的方法名走從庫return StringUtils.startsWithAny(methodName, getSlaveMethodStart());}/*** 通配符匹配* * Return if the given method name matches the mapped name.* <p>* The default implementation checks for "xxx*", "*xxx" and "*xxx*" matches, as well as direct* equality. Can be overridden in subclasses.* * @param methodName the method name of the class* @param mappedName the name in the descriptor* @return if the names match* @see org.springframework.util.PatternMatchUtils#simpleMatch(String, String)*/protected boolean isMatch(String methodName, String mappedName) {return PatternMatchUtils.simpleMatch(mappedName, methodName);}/*** 用戶指定slave的方法名前綴* @param slaveMethodStart*/public void setSlaveMethodStart(String[] slaveMethodStart) {this.slaveMethodStart = slaveMethodStart;}public String[] getSlaveMethodStart() {if(this.slaveMethodStart == null){// 沒有指定,使用默認return defaultSlaveMethodStart;}return slaveMethodStart;} } 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的MySQL读写分离事务策略实现的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: MySQL读写分离应用层实现
- 下一篇: MySQL读写分离一主多从实现
