1. Configure the AOP Slice class Datasourceadvice.java
Package Until;import Java.lang.reflect.method;import Org.springframework.aop.afterreturningadvice;import Org.springframework.aop.methodbeforeadvice;import Org.springframework.aop.throwsadvice;public Class Datasourceadvice implements Methodbeforeadvice, Afterreturningadvice, Throwsadvice {//service method executed before public void is called Before (method, object[] args, Object target) throws Throwable {System.out.println ("pointcut:" + target.getclass (). Getn Ame () + "class" + method.getname () + "method"); if (Method.getname (). StartsWith ("add") | | method.getname (). StartsWith ("create") || Method.getname (). StartsWith ("save") | | Method.getname (). StartsWith ("edit") | | Method.getname (). StartsWith ("Update") | | Method.getname (). StartsWith ("delete") | | Method.getname (). StartsWith ("Remove") {System.out.println ("Switch to: Master");D Atasourceswitcher.setmaster (); else {System.out.println ("Switch to: Slave");D Atasourceswitcher.setslave ();}} The service method is invoked after execution of public void Afterreturning (object arg0, method, object[] args, object target) tHrows Throwable {}//thrown Exception after being called public void afterthrowing (method, object[] args, Object target, Exception ex) Throws Throwable {Datasourceswitcher.setslave (); SYSTEM.OUT.PRINTLN ("Exception occurred, switch to: Slave");}}
2. Data source Selection class Datasourceswitcher.java
Package Until;import Org.springframework.util.assert;public class Datasourceswitcher {@SuppressWarnings ("rawtypes") private static final ThreadLocal Contextholder = new ThreadLocal (), @SuppressWarnings ("unchecked") public static void Setdatasource (String dataSource) {assert.notnull (DataSource, "DataSource cannot be null"); Contextholder.set ( DataSource);} public static void Setmaster () {Cleardatasource ();} public static void Setslave () {Setdatasource ("slave");} public static String Getdatasource () {return (String) Contextholder.get ();} public static void Cleardatasource () {contextholder.remove ();}}
3. Dynamicdatasource.java data source Dynamic switch class
Package Until;import Java.sql.sqlfeaturenotsupportedexception;import Java.util.logging.logger;import Org.springframework.jdbc.datasource.lookup.abstractroutingdatasource;public class DynamicDataSource extends Abstractroutingdatasource {@Overrideprotected Object Determinecurrentlookupkey () {return Datasourceswitcher.getdatasource ();}}
4. Configure the spring Applicationcontext.xml file below
<?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:context= "Http://www.springframework.org/schema/context" xmlns:tx= "Http://www.springframework.org/schema/tx" xmlns:aop= "HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP" xsi: schemalocation= "Http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/ Spring-beans-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/txhttp://www.springframework.org/schema/tx/ Spring-tx-2.5.xsd HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP http://www.springframework.org/schema/aop/ Spring-aop-2.5.xsd "><!--dbcp data source--><bean id=" Parentdatasource "class=" Org.apache.commons.dbcp.BasicDataSource "destroy-method=" Close "><!--<property name=" Driverclassname " Value= "Com.mysql.jdbc.Driver"/><property name="url" value= "jdbc:mysql://127.0.0.1:3306/readandwrite_test"/><property name= "username" value= "root"/> <property name= "Password" value= "root"/>--><property name= "InitialSize" value= "ten"/><!--initialize Connection-- ><property name= "Maxidle" value= ""/><!--maximum idle connection--><property name= "Minidle" value= "ten"/><! --Minimum idle connection--><property name= "maxactive" value= "/><!--maximum number of connections--><property name=" logabandoned " Value= "true"/><!--whether to print the connection timeout error when auto-recycle timeout--><property name= "removeabandoned" value= "true"/><!- -whether to automatically reclaim time-out connections--><property name= "removeabandonedtimeout" value= "/><"!--timeout (in seconds)-->< Property Name= "Maxwait" value= "$"/> <!--timeout wait time in milliseconds--><property name= "Testonborrow" value= "false"/ > < When a connection is made!--database connection pool, checking its validity will affect performance--><property name= "Testwhileidle" value= "true"/> <!-- Asynchronously evict a timertask timed thread to control the timing of a link in the thread pool validateobject check--><property name= "TimebetweenevIctionrunsmillis "value=" 25200000 "/><!--fail-over check thread runs at more than 0 hours to open evict check thread--><property name=" Validationquery "value=" Select 1 "/> <!--checksum sql--></bean><!--main data source--><bean id=" Masterdatasource "parent=" Parentdatasource "><property name=" Driverclassname "value=" Com.mysql.jdbc.Driver "/ ><property name= "url" value= "jdbc:mysql://127.0.0.1:3306/readandwrite_test"/><property name= "username "Value=" root "/><property name=" password "value=" root "/></bean><!----><bean id= from the data source" Slavedatasource "parent=" Parentdatasource "><property name=" Driverclassname "value=" Com.mysql.jdbc.Driver "/ ><property name= "url" value= "jdbc:mysql://127.0.0.1:3306/readandwrite_test"/><property name= "username "Value=" root "/><property name=" password "value=" root "/></bean><!--data source dynamically switch--><bean id=" DataSource "class=" until. Dynamicdatasource "><property name=" targetdatasources "><map key-type=" Java.lang.STring "><entry key=" Slave "value-ref=" Slavedatasource "/></map></property><property name=" Defaulttargetdatasource "ref=" Masterdatasource "/></bean><!--configuration sessionfactory--><bean id=" Sessionfactory "class=" Org.springframework.orm.hibernate3.LocalSessionFactoryBean "><property name=" DataSource "ref=" DataSource "></property><property name=" Mappingresources "><list><value >hbm/user.hbm.xml</value></list></property><property name= "HibernateProperties" >< Props><prop key= "Hibernate.dialect" >org.hibernate.dialect.mysqldialect</prop><prop key= " Hibernate.show_sql ">true</prop> </props></property></bean><!--switch Data source--><bean Id= "Datasourceadvice" class= "until. Datasourceadvice "/><aop:config><aop:advisorpointcut=" Execution (* service: *service.* (..)) " advice-ref= "Datasourceadvice"/></aop:config><!--configuration transaction manager--><bean id= "TranSactionmanager "class=" Org.springframework.orm.hibernate3.HibernateTransactionManager "><property name=" Sessionfactory "><ref bean=" sessionfactory "/></property></bean><!--configuration transaction Propagation characteristics--><TX : Advice id= "Txadvice" transaction-manager= "TransactionManager" ><tx:attributes><!--for business support of adding, deleting and modifying methods ><tx:method name= "add*" propagation= "REQUIRED"/><tx:method name= "create*" propagation= "REQUIRED"/> <tx:method name= "save*" propagation= "REQUIRED"/><tx:method name= "edit*" propagation= "REQUIRED"/><tx : Method Name= "update*" propagation= "REQUIRED"/><tx:method name= "delete*" propagation= "REQUIRED"/><TX: Method Name= "remove*" propagation= "REQUIRED"/><!--read-only transaction to the lookup method--><tx:method name= "load*" propagation= " SUPPORTS "read-only=" true "/><!--read-only transaction to other methods--><tx:method name=" * "propagation=" SUPPORTS "read-only=" True "/></tx:attributes></tx:advice><!--which methods of those classes participate in the transaction--><aop:config><aop:advisorpointcut= "Execution (* service: *service.* (..)) " advice-ref= "Txadvice"/><aop:advisorpointcut= "Execution (* service: *serviceimpl.* (..)) " advice-ref= "Txadvice"/></aop:config></beans>
MySQL read-write separation and master-slave database configuration under Spring+hibernate framework