注解方式实现读写分离
在web应用开发过程中,数据库的压力会越来越大,那么就避免不了,要提供一个比较可行的方案,数据库的读写分离。
读写分离的机制:在从库读取数据,在主库写数据。
1.自定义数据库数据源类型注解:
@Target( ElementType.METHOD) @Retention( RetentionPolicy.RUNTIME) @Inherited public @interface DBProfile { String dbName() default ""; }
2.在方法层面上调用:
@DBProfile(dbName = Constants.SLAVE)3.用ThreadLocal,定义数据源的类型(主,从)
public class DataSourceContextHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); /** * @Description: 设置数据源类型 * @param dataSourceType 数据库类型 * @return void * @throws */ public static void setDataSourceType(String dataSourceType) { contextHolder.set(dataSourceType); } /** * @Description: 获取数据源类型 * @param * @return String * @throws */ public static String getDataSourceType() { return contextHolder.get(); } /** * @Description: 清除数据源类型 * @param * @return void * @throws */ public static void clearDataSourceType() { contextHolder.remove(); } }4.定义动态数据源类
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); } }5.在xml中配置,
DynamicDataSource6.定义切面<bean id="dynamicDataSource" class="com.xx.xx.business.service.DynamicDataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry value-ref="dataSource" key="Master"/> <entry value-ref="dataSource" key="Slave"/> <!-- <entry value-ref="businessDataSourceOther" key="Slave"/> --> </map> </property> <!--默认数据源--> <property name="defaultTargetDataSource" ref="dataSource"/> </bean> <bean id="dataSourceMaster" class="dbcp.xxx"><bean id="dataSourceSlaver" class="dbcp.xxx">
@Component @Aspect public class DynamicDataSourceAspect { @Pointcut( "@annotation(com.xx.xx.xx.common.aspect.DBProfile)" ) public void DynamicDataSource() { } @Before( "DynamicDataSource()" ) public void executeChangeDataSource( JoinPoint point ) { MethodSignature msig = ( MethodSignature )point.getSignature(); Method method = msig.getMethod(); DBProfile dbProfile = ( DBProfile )method.getAnnotation( DBProfile.class ); if( dbProfile != null ) { DataSourceContextHolder.setDataSourceType( dbProfile.dbName() ); } } @After( "DynamicDataSource()" ) public void executeClear( JoinPoint point ) { DataSourceContextHolder.clearDataSourceType(); } }