数据库动态切换类:
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
System.out.println("===================切换数据源:" + DataSourceSwitcher.getDataSource());
return DataSourceSwitcher.getDataSource();
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
}
AOP切面类,设置数据源:
@Component
@Aspect
@Order(0)
public class DataSourceAdvice {
private static Logger logger = Logger.getLogger(DataSourceAdvice.class);
@Before(("@annotation(com.lot.common.dataSource.DynamicDataSourceAnnotation)"))
public void before(JoinPoint point) {
try {
// 获取数据源
String dataSource = getDataSource(point);
// 设置数据源
logger.info("切换数据源到" + dataSource);
DataSourceSwitcher.setDataSource(dataSource);
} catch (Exception e) {
logger.error("切换数据源失败...");
logger.error(StringHandleUtils.getExceptionInfo(e));
}
}
@After("@annotation(com.lot.common.dataSource.DynamicDataSourceAnnotation)") //后置通知
public void testAfter(JoinPoint point){
try {
// 获取数据源
String dataSource = getDataSource(point);
// 若数据源不是主库,则清空
if(!DataSourceSwitcher.DATA_SOURCE_MASTER.equals(dataSource)) {
logger.error("删除数据源" + dataSource + "成功...");
DataSourceSwitcher.removeDataSource();
}
} catch (Exception e) {
logger.error("删除数据源失败...");
logger.error(StringHandleUtils.getExceptionInfo(e));
}
}
@SuppressWarnings("rawtypes")
private String getDataSource(JoinPoint point) {
String dataSource = DataSourceSwitcher.DATA_SOURCE_MASTER;
try{
Class<?> className = point.getTarget().getClass();
String methodName = point.getSignature().getName();
Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes();
Method method = className.getMethod(methodName, argClass);
if (method.isAnnotationPresent(DynamicDataSourceAnnotation.class)) {
DynamicDataSourceAnnotation annotation = method.getAnnotation(DynamicDataSourceAnnotation.class);
dataSource = annotation.dataSource();
}
}catch(Exception e) {
logger.error("获取数据源失败...");
logger.error(StringHandleUtils.getExceptionInfo(e));
}
return dataSource;
}
}
spring配置:
<!-- master -->
<bean id="master" class="com.lot.common.dataSource.DataSource" parent="commC3p0">
<property name="driver" value="${master.datasource.driverClassName}" />
<property name="driverUrl" value="${master.datasource.url}" />
<property name="user" value="${master.datasource.username}"/>
<property name="password" value="${master.datasource.password}"/>
</bean>
<!-- slave -->
<bean id="slave" class="com.lot.common.dataSource.DataSource" parent="commC3p0">
<property name="driver" value="${slave.datasource.driverClassName}" />
<property name="driverUrl" value="${slave.datasource.url}" />
<property name="user" value="${slave.datasource.username}"/>
<property name="password" value="${slave.datasource.password}"/>
</bean>
<!-- 配置动态数据源 -->
<bean id="dataSource" class="com.lot.common.dataSource.DynamicDataSource">
<property name="defaultTargetDataSource" ref="master"></property>
<property name="targetDataSources">
<map key-type="java.lang.Object">
<entry value-ref="master" key="master"></entry>
<entry value-ref="slave" key="slave"></entry>
</map>
</property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.use_sql_comments">${hibernate.use_sql_comments}</prop>
<prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>
<prop key="hibernate.max_fetch_depth">${hibernate.max_fetch_depth}</prop>
<prop key="hibernate.jdbc.fetch_size">${hibernate.jdbc.fetch_size}</prop>
<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
<prop key="hibernate.cache.provider_class">${hibernate.cache.provider_class}</prop>
<prop key="hibernate.order_updates">${hibernate.order_updates}</prop>
<prop key="hibernate.query.factory_class">${hibernate.query.factory_class}</prop>
<prop key="hibernate.connection.isolation">${hibernate.connection.isolation}</prop>
<!-- 解决与weblogic的冲突 -->
<prop key="hibernate.query.factory_class">${hibernate.query.factory_class}</prop>
<prop key="hibernate.jdbc.batch_size">0</prop>
</props>
</property>
<property name="packagesToScan" value="com.entity"/>
</bean>
<!-- 定义事务管理器(声明式的事务) -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 注解方式配置事务 -->
<aop:aspectj-autoproxy proxy-target-class="true" />
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="false" />
数据源切换时在AOP之前执行了,导致数据源未切换。