详解使用spring aop实现业务层mysql 读写分离
程序员文章站
2024-03-08 14:20:06
spring aop , mysql 主从配置 实现读写分离,接下来把自己的配置过程,以及遇到的问题记录下来,方便下次操作,也希望给一些朋友带来帮助。
1.使用spr...
spring aop , mysql 主从配置 实现读写分离,接下来把自己的配置过程,以及遇到的问题记录下来,方便下次操作,也希望给一些朋友带来帮助。
1.使用spring aop 拦截机制现数据源的动态选取。
import java.lang.annotation.elementtype; import java.lang.annotation.target; import java.lang.annotation.retention; import java.lang.annotation.retentionpolicy; /** * runtime * 编译器将把注释记录在类文件中,在运行时 vm 将保留注释,因此可以反射性地读取。 * @author yangguang * */ @retention(retentionpolicy.runtime) @target(elementtype.method) public @interface datasource { string value(); }
3.利用spring的abstractroutingdatasource解决多数据源的问题
import org.springframework.jdbc.datasource.lookup.abstractroutingdatasource; public class choosedatasource extends abstractroutingdatasource { @override protected object determinecurrentlookupkey() { return handledatasource.getdatasource(); } }
4.利用threadlocal解决线程安全问题
public class handledatasource { public static final threadlocal<string> holder = new threadlocal<string>(); public static void putdatasource(string datasource) { holder.set(datasource); } public static string getdatasource() { return holder.get(); } }
5.定义一个数据源切面类,通过aop访问,在spring配置文件中配置了,所以没有使用aop注解。
import java.lang.reflect.method; import org.aspectj.lang.joinpoint; import org.aspectj.lang.annotation.aspect; import org.aspectj.lang.annotation.before; import org.aspectj.lang.annotation.pointcut; import org.aspectj.lang.reflect.methodsignature; import org.springframework.stereotype.component; //@aspect //@component public class datasourceaspect { //@pointcut("execution(* com.apc.cms.service.*.*(..))") public void pointcut(){}; // @before(value = "pointcut()") public void before(joinpoint point) { object target = point.gettarget(); system.out.println(target.tostring()); string method = point.getsignature().getname(); system.out.println(method); class<?>[] classz = target.getclass().getinterfaces(); class<?>[] parametertypes = ((methodsignature) point.getsignature()) .getmethod().getparametertypes(); try { method m = classz[0].getmethod(method, parametertypes); system.out.println(m.getname()); if (m != null && m.isannotationpresent(datasource.class)) { datasource data = m.getannotation(datasource.class); handledatasource.putdatasource(data.value()); } } catch (exception e) { e.printstacktrace(); } } }
6.配置applicationcontext.xml
<!-- 主库数据源 --> <bean id="writedatasource" class="com.jolbox.bonecp.bonecpdatasource" destroy-method="close"> <property name="driverclass" value="com.mysql.jdbc.driver"/> <property name="jdbcurl" value="jdbc:mysql://172.22.14.6:3306/cpp?autoreconnect=true"/> <property name="username" value="root"/> <property name="password" value="root"/> <property name="partitioncount" value="4"/> <property name="releasehelperthreads" value="3"/> <property name="acquireincrement" value="2"/> <property name="maxconnectionsperpartition" value="40"/> <property name="minconnectionsperpartition" value="20"/> <property name="idlemaxageinseconds" value="60"/> <property name="idleconnectiontestperiodinseconds" value="60"/> <property name="poolavailabilitythreshold" value="5"/> </bean> <!-- 从库数据源 --> <bean id="readdatasource" class="com.jolbox.bonecp.bonecpdatasource" destroy-method="close"> <property name="driverclass" value="com.mysql.jdbc.driver"/> <property name="jdbcurl" value="jdbc:mysql://172.22.14.7:3306/cpp?autoreconnect=true"/> <property name="username" value="root"/> <property name="password" value="root"/> <property name="partitioncount" value="4"/> <property name="releasehelperthreads" value="3"/> <property name="acquireincrement" value="2"/> <property name="maxconnectionsperpartition" value="40"/> <property name="minconnectionsperpartition" value="20"/> <property name="idlemaxageinseconds" value="60"/> <property name="idleconnectiontestperiodinseconds" value="60"/> <property name="poolavailabilitythreshold" value="5"/> </bean> <!-- transaction manager, 事务管理 --> <bean id="transactionmanager" class="org.springframework.jdbc.datasource.datasourcetransactionmanager"> <property name="datasource" ref="datasource" /> </bean> <!-- 注解自动载入 --> <context:annotation-config /> <!--enale component scanning (beware that this does not enable mapper scanning!)--> <context:component-scan base-package="com.apc.cms.persistence.rdbms" /> <context:component-scan base-package="com.apc.cms.service"> <context:include-filter type="annotation" expression="org.springframework.stereotype.component" /> </context:component-scan> <context:component-scan base-package="com.apc.cms.auth" /> <!-- enable transaction demarcation with annotations --> <tx:annotation-driven /> <!-- define the sqlsessionfactory --> <bean id="sqlsessionfactory" class="org.mybatis.spring.sqlsessionfactorybean"> <property name="datasource" ref="datasource" /> <property name="typealiasespackage" value="com.apc.cms.model.domain" /> </bean> <!-- scan for mappers and let them be autowired --> <bean class="org.mybatis.spring.mapper.mapperscannerconfigurer"> <property name="basepackage" value="com.apc.cms.persistence" /> <property name="sqlsessionfactory" ref="sqlsessionfactory" /> </bean> <bean id="datasource" class="com.apc.cms.utils.choosedatasource"> <property name="targetdatasources"> <map key-type="java.lang.string"> <!-- write --> <entry key="write" value-ref="writedatasource"/> <!-- read --> <entry key="read" value-ref="readdatasource"/> </map> </property> <property name="defaulttargetdatasource" ref="writedatasource"/> </bean> <!-- 激活自动代理功能 --> <aop:aspectj-autoproxy proxy-target-class="true"/> <!-- 配置数据库注解aop --> <bean id="datasourceaspect" class="com.apc.cms.utils.datasourceaspect" /> <aop:config> <aop:aspect id="c" ref="datasourceaspect"> <aop:pointcut id="tx" expression="execution(* com.apc.cms.service..*.*(..))"/> <aop:before pointcut-ref="tx" method="before"/> </aop:aspect> </aop:config> <!-- 配置数据库注解aop -->
7.使用注解,动态选择数据源,分别走读库和写库。
@datasource("write") public void update(user user) { usermapper.update(user); } @datasource("read") public document getdocbyid(long id) { return documentmapper.getbyid(id); }
测试写操作:可以通过应用修改数据,修改主库数据,发现从库的数据被同步更新了,所以定义的write操作都是走的写库
测试读操作: 后台修改从库数据,查看主库的数据没有被修改,在应用页面中刷新,发现读的是从库的数据,说明读写分离ok。
遇到的问题总结:
问题1:项目是maven工程,用到了spring aop机制,除了spring的核心jar包以为,还需要用到的jar包有aspectj.jar,aspectjweaver.jar,aopalliance.jar查看项目中的pom,发现缺少依赖包,由于本地仓库没有这些jar,查找可以提供下载jar包的maven*库库,配置到maven中,自动更新:
<repository> <id>nexus</id> <name>nexus</name> <url>http://repository.sonatype.org/content/groups/public/</url> <layout>default</layout> </repository>
配置项目依赖的jar,主要是缺少这两个。
<dependency> <groupid>aspectj</groupid> <artifactid>aspectjrt</artifactid> <version>1.5.4</version> </dependency> <dependency> <groupid>aspectj</groupid> <artifactid>aspectjweaver</artifactid> <version>1.5.4</version> lt;/dependency>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。