spring学习笔记(19)mysql读写分离后端AOP控制实例

简介: <div class="markdown_views"> <p>在这里,我们接上一篇文章,利用JNDI访问应用服务器配置的两个数据源来模拟同时操作不同的数据库如同时操作mysql和oracle等。实际上,上个例子可能用来模拟mysql数据库主从配置读写分离更贴切些。既然如此,在本例中,我们就完成读写分离的模拟在web端的配置实例。</p> <p>续上次的例子,关于JNDI数据
+关注继续查看

在这里,我们接上一篇文章,利用JNDI访问应用服务器配置的两个数据源来模拟同时操作不同的数据库如同时操作mysql和oracle等。实际上,上个例子可能用来模拟mysql数据库主从配置读写分离更贴切些。既然如此,在本例中,我们就完成读写分离的模拟在web端的配置实例。

续上次的例子,关于JNDI数据源的配置和spring datasource的配置这里不再重复。下面着重加入AOP实现DAO层动态分库调用。可先看上篇文章《spring学习笔记(18)使用JNDI模拟访问应用服务器多数据源实例 》

1. DAO层设计

/***************接口设计************/
public interface MyBaseDao {
    SessionFactory getSessionFactory();
    <E> E add(Object object);
    <E>E queryUnique(Class<E> clazz, Integer entityId);
    void setSourceType(Integer sourceType);
}
/****************实现类设计******************/
@Repository
public class MyBaseDaoImpl implements MyBaseDao{
    //由于本类是单例了,考虑到线程安全问题,这是使用ThreadLocal作为判断调用哪个数据源的依据
    private ThreadLocal<Integer> sourceType = new ThreadLocal<Integer>();
    @Autowired
    @Qualifier("sessionFactory")
    private SessionFactory sessionFactory;

    @Autowired
    @Qualifier("sessionFactory2")
    private SessionFactory sessionFactory2;

    @Override
    public SessionFactory getSessionFactory() {
        if(sourceType.get() == null){//如果没有值则默认使用数据源1
            sourceType.set(1);
        }
        switch (sourceType.get()) {
        case 1://使用数据源1,本例中这里是主库,主要负责写
            return sessionFactory;
        case 2: //使用数据源2,本例中这里是从库,主要负责读
            return sessionFactory2;
        default:
            throw new IllegalArgumentException("unknown sourceType");
        }
    }
    @Override//模拟一个写的操作,要让主库数据源调用
    public <E> E add(Object object) {
        return (E) getSessionFactory().openSession().save(object);
    }
    @Override//模拟一个读的操作,要让从库数据源调用
    public <E> E queryUnique(Class<E> clazz, Integer entityId) {
        return (E) getSessionFactory().openSession().get(clazz, entityId);
    }
    @Override//共AOP增强类修改数据源类型
    public void setSourceType(Integer sourceType) {
        this.sourceType.set(sourceType);
    }
}

2. AOP类设计

@Aspect
public class DataSourceSelector {//使用前置增强
    @Before("execution( * com.yc.dao.MyBaseDaoImpl.add*(..))")//写操作
    public void before1(JoinPoint joinPoint){
        ((MyBaseDao)joinPoint.getTarget()).setSourceType(1);//切换到主库
    }

    @Before("execution( * com.yc.dao.MyBaseDaoImpl.query*(..))")//读操作
    public void before2(JoinPoint joinPoint){
        ((MyBaseDao)joinPoint.getTarget()).setSourceType(2);//切换到从库
    }
}

关于AOP的配置教程,可移步参考本系列前面AOP部分的文章。然后我们还需要在IOC容器中注册我们的切面。

<aop:aspectj-autoproxy />   <!-- 使@AspectJ注解生效 -->
<bean class="com.yc.aop.DataSourceSelector" /><!-- 注册切面 -->

3. 修改控制器

针对上一篇文章的控制器,作如下修改:

@Controller
public class JNDITestController {

    @Autowired
    private MyBaseDao myBaseDao;

    @RequestMapping("testJNDI")
    @ResponseBody
    public Object testJNDI(){
        User user = new User();
        user.setName("new_user_fron_yc1");
        Integer newId = myBaseDao.add(user);
        System.out.println("new UserId = " + newId);//获取我们新插入的id
        System.out.println("is new User here? " + myBaseDao.queryUnique(com.yc.model2.User.class, newId));
        return newId;
    }
}

4. 测试与结果分析

运行服务器,然后在游览器中输入http://localhost:8090/yc/testJNDI,我们会看到控制台打印信息:

new UserId = 4
is new User here? null

newUserId是我们插入到主库中的,id为4。
但我们紧接着读取,却并未读取到。这说明我们存的数据库和读的数据库并不是同一个,从而简单地实现了读写分离。为了验证这一点,我们所示数据库,如下图所示,显然我们在yc1存进去了我们的测试数据,在yc2中并没有!
这里写图片描述

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
4月前
|
Java 容器 Spring
Spring之Bean的配置与实例(二)
Spring之Bean的配置与实例(二)
|
4月前
|
Java 应用服务中间件 Spring
Spring之Bean的配置与实例(一)
Spring之Bean的配置与实例(一)
|
7月前
|
Java 微服务 Spring
从0到1 手把手搭建spring cloud alibaba 微服务大型应用框架(六)(优化篇)开发篇-如何解决微服务开发环境请求实例转发到别人机器问题
从0到1 手把手搭建spring cloud alibaba 微服务大型应用框架(六)(优化篇)开发篇-如何解决微服务开发环境请求实例转发到别人机器问题
从0到1 手把手搭建spring cloud alibaba 微服务大型应用框架(六)(优化篇)开发篇-如何解决微服务开发环境请求实例转发到别人机器问题
|
7月前
|
负载均衡 前端开发 Java
从0到1 手把手搭建spring cloud alibaba 微服务大型应用框架(六)开发篇-如何解决微服务开发环境请求实例转发到别人机器问题
从0到1 手把手搭建spring cloud alibaba 微服务大型应用框架(六)开发篇-如何解决微服务开发环境请求实例转发到别人机器问题
从0到1 手把手搭建spring cloud alibaba 微服务大型应用框架(六)开发篇-如何解决微服务开发环境请求实例转发到别人机器问题
|
8月前
|
Java Spring
Spring validator 校验实例
Spring validator 校验实例
58 0
|
10月前
|
前端开发 Java Spring
Spring Boot 集成 Thymeleaf 入门及实例
Thymeleaf 是新一代 Java 模板引擎,它类似于 Velocity、FreeMarker 等传统 Java 模板引擎,但是与传统 Java 模板引擎不同的是,Thymeleaf 支持 HTML 原型。 它既可以让前端工程师在浏览器中直接打开查看样式,也可以让后端工程师结合真实数据查看显示效果,同时,SpringBoot 提供了 Thymeleaf 自动化配置解决方案,因此在 SpringBoot 中使用 Thymeleaf 非常方便。
74 0
Spring Boot 集成 Thymeleaf  入门及实例
|
11月前
|
缓存 Java 容器
Spring 源码阅读 30:getBean 方法获取 Bean 实例的过程总结
本文总结了 Spring 容器 getBean 方法获取单例 Bean 实例的原理。更细节的分析,可以看我之前的文章。
142 0
Spring 源码阅读 30:getBean 方法获取 Bean 实例的过程总结
|
11月前
|
XML Java 数据格式
Spring 源码阅读 27:Bean 实例初始化
本文通过阅读源码分析了 Spring 初始化 Bean 实例过程中执行 Bean 初始化方法的过程。
62 0
Spring 源码阅读 27:Bean 实例初始化
|
11月前
|
XML 缓存 Java
Spring 源码阅读 26:Bean 早期实例处理及属性注入
本文分析了从 Spring 创建完早期 Bean 实例,到完成属性注入的过程。其中包括了将早期实例添加到三级缓存和属性自动装配的过程。
83 0
Spring 源码阅读 26:Bean 早期实例处理及属性注入
|
11月前
|
XML 缓存 Java
Spring 源码阅读 25:单例 Bean 实例的创建过程(2)
通过本文的分析,终于走到了 Spring 最终把 Bean 实例创建出来的,这个实例会被一个 BeanWrapper 类型的对象包装,并返回到`doCreateBean`方法中。
69 0
Spring 源码阅读 25:单例 Bean 实例的创建过程(2)
推荐文章
更多
推荐镜像
更多