Spring AOP dynamic multi-data source instance details, Spring AOP

Source: Internet
Author: User

Spring AOP dynamic multi-data source instance details, Spring AOP

Examples of Spring AOP dynamic multi-data sources

When read/write splitting is used in the project, we will encounter multiple data sources. Multiple data sources are the biggest headache. Instead of configuring multiple data sources, you can flexibly and dynamically switch data sources. For example, in a spring and Mybatis framework project, we usually configure a dataSource in spring configuration to connect to the database and then bind it to sessionFactory, in the dao-Layer Code, specify sessionFactory to perform database operations.

 

As shown in, each part is bound to a dead part. If multiple data sources exist, it can only be in the middle way.

It can be seen that two sessionfactories are written in the Dao-Layer Code. In this way, if there is another data source in the future, you need to change the code to add a SessionFactory. Obviously, this is not in line with the open/closed principle.

The correct method should be:

The code and configuration are as follows:

1. applicationContext-mgr.xml

<? Xml version = "1.0" encoding = "UTF-8"?> <Beans xmlns =" http://www.springframework.org/schema/beans "Xmlns: xsi =" http://www.w3.org/2001/XMLSchema-instance "Xmlns: aop =" http://www.springframework.org/schema/aop "Xmlns: context =" http://www.springframework.org/schema/context "Xmlns: tx =" http://www.springframework.org/schema/tx "Xmlns: p =" http://www.springframework.org/schema/p "Xsi: schemaLocation =" http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans Spring-beans-2.5.xsd http://www.springframework.org/schema/aop Spring-aop-2.5.xsd http://www.springframework.org/schema/context  http://www.springframework.org/schema/context Spring-context-2.5.xsd http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx /Spring-tx-2.5.xsd "> <! -- Use annotation --> <context: annotation-config/> <context: component-scan base-package = "com. carl. o2o. **. mgr "> </context: component-scan> <! -- Master --> <bean id = "master" class = "com. mchange. v2.c3p0. comboPooledDataSource "> <property name =" driverClass "value =" $ {driverClassName_master} "/> <property name =" user "value =" $ {username_master} "/> <property name = "password" value = "$ {password_master}"/> <property name = "jdbcUrl" value = "$ {url_master }? Unicode = true & characterEncoding = UTF-8 & allowMultiQueries = true "/> <property name =" maxPoolSize "value =" 150 "/> <property name =" minPoolSize "value =" 10" /> <property name = "initialPoolSize" value = "20"/> <property name = "maxIdleTime" value = "3600"/> <property name = "acquireIncrement" value =" 10 "/> <property name =" idleConnectionTestPeriod "value =" 1800 "/> </bean> <! -- Slave --> <bean id = "slave" class = "com. mchange. v2.c3p0. comboPooledDataSource "> <property name =" driverClass "value =" $ {driverClassName_slave} "/> <property name =" user "value =" $ {username_slave} "/> <property name = "password" value = "$ {password_slave}"/> <property name = "jdbcUrl" value = "$ {url_slave }? Unicode = true & characterEncoding = UTF-8 "/> <property name =" maxPoolSize "value =" 150 "/> <property name =" minPoolSize "value =" 10 "/> <property name = "initialPoolSize" value = "20"/> <property name = "maxIdleTime" value = "3600"/> <property name = "acquireIncrement" value = "10"/> <property name = "idleConnectionTestPeriod" value = "1800" type = "codeph" text = "codeph"/> </bean> <! -- Spring dynamic data source --> <bean id = "dynamicDataSource" class = "com. carl. dbUtil. dynamicDataSource "> <property name =" targetDataSources "> <map key-type =" java. lang. string "> <entry key =" slave "value-ref =" slave "/> </map> </property> <property name =" defaultTargetDataSource "ref =" master "/> </bean> <! -- Mybatis mapper config --> <bean id = "sqlSessionFactory" class = "org. mybatis. spring. sqlSessionFactoryBean "> <property name =" dataSource "ref =" dynamicDataSource "/> <property name =" configLocation "value =" classpath: o2o_mybatis_config.xml "/> <property name =" mapperLocations "> <list> <value> classpath: sqlMap /*. xml </value> <value> classpath *:/com/carl/o2o /**/*. xml </value> </list> </property> </bean> <bean I D = "sqlSession" class = "org. mybatis. spring. sqlSessionTemplate "> <constructor-arg index =" 0 "ref =" sqlSessionFactory "> </constructor-arg> </bean> <bean class =" org. mybatis. spring. mapper. mapperScannerConfigurer "> <property name =" basePackage "value =" com. carl. o2o. **. mgr. dao "/> </bean> <! -- Multi-data source aop --> <bean id = "ceceaspect" class = "com. carl. dbUtil. performanceaspect "/> <aop: config> <aop: advisor pointcut =" execution (* com. carl. o2o. mgr. *. *(..)) "advice-ref =" DataSourceAspect "/> </aop: config> <! -- Transaction --> <bean name = "transactionManager" class = "org. springframework. jdbc. datasource. dataSourceTransactionManager "> <property name =" dataSource "ref =" dynamicDataSource "> </property> </bean> </beans>

2. DynamicDataSource

DynamicDataSource uses the code in Spring and AOP to implement multi-data source switching.

public class DynamicDataSource extends AbstractRoutingDataSource {  public DynamicDataSource() {  }  protected Object determineCurrentLookupKey() {    return DBContextHolder.getDbType();  }  public Logger getParentLogger() {    return null;  }}

3. DBContextHolder

The auxiliary class of DynamicDataSource for switching multiple data sources.

public class DBContextHolder {  private static ThreadLocal<String> contextHolder = new ThreadLocal();  public static String MASTER = "master";  public static String SLAVE = "slave";  public DBContextHolder() {  }  public static String getDbType() {    String db = (String)contextHolder.get();    if(db == null) {      db = MASTER;    }    return db;  }  public static void setDbType(String str) {    contextHolder.set(str);  }  public static void setMaster() {    contextHolder.set(MASTER);  }  public static void setSlave() {    contextHolder.set(SLAVE);  }  public static void clearDBType() {    contextHolder.remove();  }}

4. performanceaspect

Multi-Data Source AOP aspect programming implementation.

public class DataSourceAspect implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice {  private static final Logger log = LogManager.getLogger(DataSourceAspect.class);  public DataSourceAspect() {  }  public void before(Method m, Object[] args, Object target) throws Throwable {    try {      if(m != null) {        if((m.getName().startsWith("list") || m.getName().startsWith("select") || m.getName().startsWith("get")         || m.getName().startsWith("count")) && !m.getName().contains("FromMaster")) {          DBContextHolder.setDbType("slave");        } else {          DBContextHolder.setDbType("master");        }      }    } catch (Exception var5) {      log.error("data source aspect error.", var5);    }  }  public void after(JoinPoint point) {    log.info("clear db type after method.current id {}", new Object[]{Long.valueOf(Thread.currentThread().getId())});    DBContextHolder.clearDBType();  }  public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {  }  public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable {    log.info("current db type {} when exception", new Object[]{DBContextHolder.getDbType()});    DBContextHolder.setDbType("master");  }}

The above is an example of Spring AOP dynamic multi-data source. If you have any questions, please leave a message or go to the community on this site for discussion. Thank you for reading this article and hope to help you. Thank you for your support for this site!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.