/** * 读取事务管理中的策略 * * @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); // 遍历nameMap for (Map.Entry<String, TransactionAttribute> entry : map.entrySet()) { if (!entry.getValue().isReadOnly()) {// 判断之后定义了ReadOnly的策略才加入到slaveMethodPattern continue; } slaveMethodPattern.add(entry.getKey()); } }
private RootBeanDefinition parseAttributeSource(Element attrEle, ParserContext parserContext) { List<Element> methods = DomUtils.getChildElementsByTagName(attrEle, METHOD_ELEMENT); ManagedMap<TypedStringValue, RuleBasedTransactionAttribute> transactionAttributeMap = new ManagedMap<TypedStringValue, RuleBasedTransactionAttribute>(methods.size()); transactionAttributeMap.setSource(parserContext.extractSource(attrEle)); for (Element methodEle : methods) { String name = methodEle.getAttribute(METHOD_NAME_ATTRIBUTE); TypedStringValue nameHolder = new TypedStringValue(name); nameHolder.setSource(parserContext.extractSource(methodEle)); RuleBasedTransactionAttribute attribute = new RuleBasedTransactionAttribute(); String propagation = methodEle.getAttribute(PROPAGATION_ATTRIBUTE); String isolation = methodEle.getAttribute(ISOLATION_ATTRIBUTE); String timeout = methodEle.getAttribute(TIMEOUT_ATTRIBUTE); String readOnly = methodEle.getAttribute(READ_ONLY_ATTRIBUTE); if (StringUtils.hasText(propagation)) { attribute.setPropagationBehaviorName(RuleBasedTransactionAttribute.PREFIX_PROPAGATION + propagation); } if (StringUtils.hasText(isolation)) { attribute.setIsolationLevelName(RuleBasedTransactionAttribute.PREFIX_ISOLATION + isolation); } if (StringUtils.hasText(timeout)) { try { attribute.setTimeout(Integer.parseInt(timeout)); } catch (NumberFormatException ex) { parserContext.getReaderContext().error("Timeout must be an integer value: [" + timeout + "]", methodEle); } } if (StringUtils.hasText(readOnly)) { attribute.setReadOnly(Boolean.valueOf(methodEle.getAttribute(READ_ONLY_ATTRIBUTE))); } List<RollbackRuleAttribute> rollbackRules = new LinkedList<RollbackRuleAttribute>(); if (methodEle.hasAttribute(ROLLBACK_FOR_ATTRIBUTE)) { String rollbackForValue = methodEle.getAttribute(ROLLBACK_FOR_ATTRIBUTE); addRollbackRuleAttributesTo(rollbackRules,rollbackForValue); } if (methodEle.hasAttribute(NO_ROLLBACK_FOR_ATTRIBUTE)) { String noRollbackForValue = methodEle.getAttribute(NO_ROLLBACK_FOR_ATTRIBUTE); addNoRollbackRuleAttributesTo(rollbackRules,noRollbackForValue); } attribute.setRollbackRules(rollbackRules); transactionAttributeMap.put(nameHolder, attribute); } RootBeanDefinition attributeSourceDefinition = new RootBeanDefinition(NameMatchTransactionAttributeSource.class); attributeSourceDefinition.setSource(parserContext.extractSource(attrEle)); attributeSourceDefinition.getPropertyValues().add("nameMap", transactionAttributeMap); return attributeSourceDefinition; }
@Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if(!(bean instanceof NameMatchTransactionAttributeSource)) { return bean; } try { NameMatchTransactionAttributeSource transactionAttributeSource = (NameMatchTransactionAttributeSource)bean; Field nameMapField = ReflectionUtils.findField(NameMatchTransactionAttributeSource.class, "nameMap"); nameMapField.setAccessible(true); @SuppressWarnings("unchecked") Map<String, TransactionAttribute> nameMap = (Map<String, TransactionAttribute>) nameMapField.get(transactionAttributeSource); for(Entry<String, TransactionAttribute> entry : nameMap.entrySet()) { RuleBasedTransactionAttribute attr = (RuleBasedTransactionAttribute)entry.getValue(); //仅对read-only的处理 if(!attr.isReadOnly()) { continue; } String methodName = entry.getKey(); Boolean isForceChoiceRead = Boolean.FALSE; if(forceChoiceReadWhenWrite) { //不管之前操作是写,默认强制从读库读 (设置为NOT_SUPPORTED即可) //NOT_SUPPORTED会挂起之前的事务 attr.setPropagationBehavior(Propagation.NOT_SUPPORTED.value()); isForceChoiceRead = Boolean.TRUE; } else { //否则 设置为SUPPORTS(这样可以参与到写事务) attr.setPropagationBehavior(Propagation.SUPPORTS.value()); } //logger.debug(arg0);.debug("read/write transaction process method:{} force read:{}", methodName, isForceChoiceRead); readMethodMap.put(methodName, isForceChoiceRead); } } catch (Exception e) { throw new ReadWriteDataSourceTransactionException("process read/write transaction error", e); } return bean; }