package com.goms.database.annotion;
import com.goms.database.DataSourceContextHolder;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Author : XiaoTanTongXie
* Date : 2019/6/20 10:38
* DESC : 数据源定制注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface DynamicDataSourceAnnotation {
//dataSource 自定义注解的参数
String dataSource() default DataSourceContextHolder.DATA_SOURCE_MAIN;
}
package com.goms.database;
/**
* Author : XiaoTanTongXie
* Date : 2019/6/20 10:29
* DESC : 数据源管理
*/
public class DataSourceContextHolder {
public static final String DATA_SOURCE_MAIN = "wtceosDataSource";
public static final String DATA_SOURCE_BACKUP = "backupWtceosDataSource";
// 线程本地环境
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
// 设置数据源类型
public static void setDbType(String dbType) {
contextHolder.set(dbType);
}
// 获取数据源类型
public static String getDbType() {
return (contextHolder.get());
}
// 清除数据源类型
public static void clearDbType() {
contextHolder.remove();
}
}
package com.goms.database;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* Author : XiaoTanTongXie
* Date : 2019/6/20 10:32
* DESC : 动态数据源
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDbType();
}
}
package com.goms.database;
import com.goms.database.annotion.DynamicDataSourceAnnotation;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* Author : XiaoTanTongXie
* Date : 2019/6/20 10:39
* DESC : 数据源切面
*/
@Aspect
@Component
@Order(1)
public class DynamicDataSourceAspect {
private static final Logger logger = Logger.getLogger(DynamicDataSourceAspect.class.getName());
@Before("@annotation(com.goms.database.annotion.DynamicDataSourceAnnotation)") //前置通知
public void before(JoinPoint point){
//获得当前访问的class
Class<?> className = point.getTarget().getClass();
//获得访问的方法名
String methodName = point.getSignature().getName();
//得到方法的参数的类型
Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes();
String dataSource = DataSourceContextHolder.DATA_SOURCE_MAIN;
try {
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("数据源加载失败" , e);
}
DataSourceContextHolder.setDbType(dataSource);
}
@After("@annotation(com.goms.database.annotion.DynamicDataSourceAnnotation)") //前置通知
public void after(JoinPoint point){
//获得当前访问的class
Class<?> className = point.getTarget().getClass();
//获得访问的方法名
String methodName = point.getSignature().getName();
//得到方法的参数的类型
Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes();
String dataSource = DataSourceContextHolder.DATA_SOURCE_MAIN;
try {
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("数据源加载失败" , e);
}
if(dataSource != null && !DataSourceContextHolder.DATA_SOURCE_MAIN.equals(dataSource)) DataSourceContextHolder.clearDbType();
}
}
配置文件核心代码:
<bean id="wtceosDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass">
<value>${jdbc.driverClass}</value>
</property>
<property name="jdbcUrl">
<value>${jdbc.url}</value>
</property>
<property name="user">
<value>${jdbc.user}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
<property name="maxPoolSize">
<value>10</value>
</property>
<property name="minPoolSize">
<value>2</value>
</property>
<property name="initialPoolSize">
<value>2</value>
</property>
<property name="maxIdleTime">
<value>5000</value>
</property>
</bean>
<bean id="backUpWtceosDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass">
<value>${backup.jdbc.driverClass}</value>
</property>
<property name="jdbcUrl">
<value>${backup.jdbc.url}</value>
</property>
<property name="user">
<value>${backup.jdbc.user}</value>
</property>
<property name="password">
<value>${backup.jdbc.password}</value>
</property>
<property name="maxPoolSize">
<value>10</value>
</property>
<property name="minPoolSize">
<value>2</value>
</property>
<property name="initialPoolSize">
<value>2</value>
</property>
<property name="maxIdleTime">
<value>5000</value>
</property>
</bean>
<!-- 多数据源配置 -->
<bean id="dynamicDataSource" class="com.eos.wms.database.DynamicDataSource">
<!-- 默认使用dataSourceA的数据源 -->
<property name="defaultTargetDataSource" ref="wtceosDataSource"></property>
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry value-ref="wtceosDataSource" key="wtceosDataSource"></entry>
<entry value-ref="backUpWtceosDataSource" key="backUpWtceosDataSource"></entry>
</map>
</property>
</bean>
<bean id="wtceosEntitySessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref local="dynamicDataSource" />
</property>
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>
Java Bean使用:
@Override
@Transactional
@DynamicDataSourceAnnotation(dataSource = DataSourceContextHolder.DATA_SOURCE_BACKUP)
public List<WarehouseInventoryVo> listWarehouseInventory(String warehouse, List<String> items) {
return eosInventoryTrackingDao.listWarehouseInventory(warehouse, items);
}