xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
destroy-method="close">
destroy-method="close">
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
org.hibernate.dialect.MySQL5InnoDBDialect
false
true
true
update
true
auto
true
true
org.hibernate.cache.EhCacheProvider
com/dxm/model/Notes.hbm.xml
advice-ref="dataSourceAdvice" />
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
class="org.springframework.transaction.interceptor.TransactionInterceptor">
PROPAGATION_REQUIRED
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
*Impl
transactionInterceptor
package com.dxm.aop;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceSwitcher.getDataSource();
}
}
package com.dxm.aop;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import org.apache.log4j.Logger;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.ThrowsAdvice;
public class DataSourceAdvice implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice {
// 日志
private Logger log = Logger.getLogger(DataSourceAdvice.class);
// 选用主数据库的方法前缀
public static Set masterMethod = new HashSet();
public static Set slaveMethod = new HashSet();
static {
masterMethod.add("add");
masterMethod.add("insert");
masterMethod.add("delete");
masterMethod.add("update");
slaveMethod.add("query");
slaveMethod.add("getByKey");
slaveMethod.add("getAll");
slaveMethod.add("findBySql");
slaveMethod.add("findByHql");
slaveMethod.add("getCount");
}
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
String methodName = method.getName();
log.info("__________________切入点: " + target.getClass().getName() + "类中" + methodName + "方法");
if (masterMethod.contains(methodName)) {
log.info("__________________切换到主数据库");
DataSourceSwitcher.setMaster();
} else if (slaveMethod.contains(methodName)) {
log.info("__________________切换到从数据库");
DataSourceSwitcher.setSlave();
} else {
log.info("__________________没有找到要切换的数据库");
}
}
@Override
public void afterReturning(Object arg0, Method method, Object[] args, Object target) throws Throwable {
}
/**
* 抛出Exception之后被调用
*
* @param method
* @param args
* @param target
* @param ex
* @throws Throwable
*/
public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable {
DataSourceSwitcher.setSlave();
log.info("出现异常,切换到: slave");
}
}
package com.dxm.aop;
import org.springframework.util.Assert;
/**
* 切换数据源
*
* @author dxm
*
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public class DataSourceSwitcher {
private static final ThreadLocal contextHolder = new ThreadLocal();
public static void setMaster() {
contextHolder.remove();
}
public static void setSlave() {
Assert.notNull("slave", "dataSource cannot be null");
contextHolder.set("slave");
}
public static String getDataSource() {
Object source = contextHolder.get();
return (String) source;
}
}