首页 > 代码库 > spring实现读写分离aop注解方式
spring实现读写分离aop注解方式
1.场景,实现数据库的读写分离。
2.思路,既然是读写分离,那就是需要切换不同的数据源,一种是静态切换,就是提前配置好两个静态数据库资源,还有一种就是动态的切换资源,这里用到spring,那就要知道spring如何动态的切换数据源。
3.spring提供了动态切换数据源接口AbstractRoutingDataSource,关于AbstractRoutingDataSource这个类我们可以看下它的源码
protected DataSource determineTargetDataSource() { Assert.notNull(this.resolvedDataSources, "DataSource router not initialized"); Object lookupKey = determineCurrentLookupKey(); DataSource dataSource = this.resolvedDataSources.get(lookupKey); if (dataSource == null && (this.lenientFallback || lookupKey == null)) { dataSource = this.resolvedDefaultDataSource; } if (dataSource == null) { throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]"); } return dataSource; }
可以看到会调用determineCurrentLookupKey()这个用方法去获取key,然后根据key去获取对应的数据源,这个时候我们就可以集成这个重写这个方法代码如下:
public class DynamicDataSource extends AbstractRoutingDataSource{ @Override protected Object determineCurrentLookupKey() { // TODO Auto-generated method stub return DynamicDataSourceHolder.getDataSource(); } }
DynamicDataSourceHolder类:
public class DynamicDataSourceHolder { public final static ThreadLocal<String> holder = new ThreadLocal<String>(); public static void putDataSource(String name){ holder.set(name); } public static String getDataSource(){ return holder.get(); } }
使用ThreadLocal是为了防止并发带来的问题,保证每个线程用到的是自己的数据源。
上面获取key的方法会在下面会用。
3.解决了动态获取数据源下面就是,如何实现当我调用读方法时切换到读数据源,实现写操作时切换到写数据源。
这里就可以用到spring aop 面向切面编程,为了方便操作我们可以写一个自定注解使用自定义的注解去注解那个方法是读操作那个方法是写操作
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface DataSource { String value(); }
aop类:
@Component @Aspect public class DaoAspect { @Pointcut("execution(* com.kedacom.aop.service.*.*(..))") public void read(){} @Before("read()") public void beforeRead(JoinPoint point){ Object object = point.getTarget(); //获取方法名称 String methodName = point.getSignature().getName(); Class<?>[] parameterTypes = ((MethodSignature)point.getSignature()).getMethod().getParameterTypes(); try { //获取到方法 Method method = object.getClass().getMethod(methodName, parameterTypes); //获取注解中的值 DataSource dataSource = method.getAnnotation(DataSource.class); //获取主从数据库的key以便切换数据库 String dbKey = dataSource.value(); DynamicDataSourceHolder.putDataSource(dbKey); System.out.println(dbKey); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } }
这里使用 到aop的注解功能。
两个服务了类:
@Service("readService") public class ReadService { @Resource(name="userDao") UserDao userDao; @DataSource(value="slave") public User readUser(String id){ return userDao.getUser(id); } }
@Service("writeService") public class WriteService { @Resource(name="userDao") UserDao userDao; @DataSource(value="master") public void writeDb(User user){ userDao.save(user); } }
测试代码:
public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); // PersonServer bean = (PersonServer)ctx.getBean("personServiceBean"); // bean.save("fasdfa"); WriteService ws = (WriteService)ctx.getBean("writeService"); User user = new User(); user.setId("123"); user.setName("xxx"); user.setPasswd("ok"); ws.writeDb(user); ReadService rs = (ReadService)ctx.getBean("readService"); User u = rs.readUser("1"); System.out.println(u.getId()+"--"+u.getName()+"--"+u.getPasswd()); }
spring的配置:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" 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:dwr="http://www.directwebremoting.org/schema/spring-dwr" xmlns:dwra="http://www.directwebremoting.org/schema/spring-dwr-annotations" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.directwebremoting.org/schema/spring-dwr http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd http://www.directwebremoting.org/schema/spring-dwr-annotations http://www.directwebremoting.org/schema/spring-dwr-annotations.xsd "> <context:annotation-config /> <context:component-scan base-package="com.guo.*,com.kedacom.*" /> <aop:aspectj-autoproxy/> <bean id="personServiceBean" class="com.guo.test.PersonServerBean"/> <!-- <bean id="myInterceptor" class="com.guo.test.MyInterceptor"/> --> <!-- 主数据库源 --> <bean id="masterDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="url" value="http://www.mamicode.com/jdbc:mysql://localhost:3306/maven?useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="http://www.mamicode.com/root"/> <property name="password" value="http://www.mamicode.com/root"/> <property name="driverClassName" value="http://www.mamicode.com/com.mysql.jdbc.Driver"/> </bean> <!-- 从数据库源 --> <bean id="slaveDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="url" value="http://www.mamicode.com/jdbc:mysql://localhost:3306/test_user?useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="http://www.mamicode.com/root"/> <property name="password" value="http://www.mamicode.com/root"/> <property name="driverClassName" value="http://www.mamicode.com/com.mysql.jdbc.Driver"/> </bean> <!-- 配置动态数据源 --> <bean id="dataSource" class="com.kedacom.aop.DynamicDataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <!-- write --> <entry key="master" value-ref="masterDataSource"/> <!-- read --> <entry key="slave" value-ref="slaveDataSource"/> </map> </property> <!-- 默认数据源 --> <property name="defaultTargetDataSource" ref="masterDataSource"/> </bean> <bean id="daoJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource" /> </bean> </beans>
spring实现读写分离aop注解方式
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。