导语:在Java生态中,我们经常直接或者间接的用到动态代理,比如通过动态代理调用远程服务,再比如通过动态代理实现解耦。本文结合京东服务框架JSF,讲述京东使用动态代理进行抽象的一次实践,以达到升级数据库访问层的目的。

刘世杰,京东商城Java高级开发工程师,一直从服务端研发工作,目前主要负责京东海外站商品主数据基础服务。个人喜欢读源码,注重细节,有些许代码洁癖。对高可用、高性能、高并发方面的技术保持持续关注。

1. 背景

最近在做数据库(MySQL)方面的升级改造。现状是数据库同时被多个应用直连,存在了一些问题:

  1. 有大量的重复代码,维护成本较高,也不优雅;

  2. 出现SQL语句质量的问题无法很快定位到是哪个应用导致的;

  3. 数据库调用方过于分散,不便于统一控制,比如部分业务数据的读写、屏蔽等;

  4. 业务的发展,有的表数据量已经到了一定的规模,几百万到几千万不等,数据库存储拆分是必须要进行的事情。

解决问题的方式很简单,就是把各应用中与此业务相关的dao层抽象成为一个单独应用(以下称为internal-rpc-app),进行统一管理。

2. 具体实现

具体的业务应用与internal-rpc-app的内部通信使用公司内部具有服务治理功能的RPC框架JSF,JSF是一款稳定高效的框架,它对服务治理的粒度是接口,接口通过Spring做服务的发布和调用配置。每个接口对应一个数据表的CURD及特殊业务。

2.1 标准版本 1.0

2.1.1. 接口注册申请

注册接口: com.jd.xx.BizRpcService1

注册接口: com.jd.xx.BizRpcService2

注册接口: com.jd.xx.BizRpcService3

......

注册接口: com.jd.xx.BizRpcServiceN

2.1.2. 服务提供方配置

<jsf:provider id="rpc1" interface="com.jd.xx.BizRpcService1"/>

<jsf:provider id="rpc2" interface="com.jd.xx.BizRpcService2"/>

<jsf:provider id="rpc3" interface="com.jd.xx.BizRpcService3"/>

......

<jsf:provider id="rpcN" interface="com.jd.xx.BizRpcServiceN"/>

2.1.3. 客户端调用方配置

<jsf:consumer id="rpc1" interface="com.jd.xx.BizRpcService1"/>

<jsf:consumer id="rpc2" interface="com.jd.xx.BizRpcService2"/>

<jsf:consumer id="rpc3" interface="com.jd.xx.BizRpcService3"/>

......

<jsf:consumer id="rpcN" interface="com.jd.xx.BizRpcServiceN"/>

2.1.4 小结

此版本实现了我们的最初的目的,但是有一个不太好的地方,就是配置的工作量太高,前面有说到JSF框架的治理维度是接口。这也意味着,每次新增接口都要提交申请操作,同时要在consumer和provider做相对应的配置,几个还好,如果数据表有几十个上百个,重复的工作量就很大。同时内部接口也不需要做太细粒度的服务治理。于是有了第二版,主要目的是简化大量重复配置。

2.2 优化调用体验版本2.0

2.2.1 内部实现 - 客户端

首先定义调用API:

BizRpcService1 bizRpcService1 = InternalPrxoyServices.BizRpcService1;

bizRpcService1.method1(param1, param2);

InternalPrxoyServices关键代码:

BizProxyRpcService1关键代码:

BaseProxyService关键代码:

InternalRpcService接口定义:

2.2.2 内部实现-服务端

服务端实现比较简单,直接根据接口传过来当serviceName、methodName、objects即可定位到具体service到方法,直接执行即可。

2.2.3 小结

到这里,我们通过静态代理实现了具体的目标,通过实现具体的接口类。我们不再需要定义过多的配置了,客户端调用也变得简单明了。

那么,结束了吗?并没有,在解决了大量配置的问题的同时,因为要写大量的代理类,又引入了新的工作量。

2.3 最终版本3.0

在这一版,我们很自然的引入了动态生成代理。

2.3.1 客户端具体实现

因为引入了动态代理,所以要重新改写InternalPrxoyServices:

ProxyServiceFactory关键代码:

InternalRpcProxy关键代码:

2.4 小结

至此,已经解决了2.2.3提到的大量创建代理类的问题。当然我们还做了很多文章中没有提及的事情,比如:

  • 通过声明哪些接口可以走动态代理

  • 方法重名、客户端接口合法性等校验

  • 将method存入缓存

3. 总结

通过建立独立的应用,解决了前面数据库被多应用读写所产生的问题,通过开发了统一接口解决了服务端和客户端配置过多的问题。代码经过一步步抽象后,最终发现实现了一个简单的RPC雏形,只不过通信层是基于公司的JSF框架。这引发了一些框架方面的思考:

  1. 是否应该去掉人工审批类似的流程?

  2. 是否应该允许更灵活的发布服务?比如:根据注解自动扫描发布服务、根据注解自动获取服务。

这不是技术问题,而是怎么权衡的问题。

记一次Java动态代理实践相关推荐

  1. Java 动态代理实践AOP

    2019独角兽企业重金招聘Python工程师标准>>> 大家都知道Spring中AOP是通过Java动态代理实现的,今天就来简单学习下demo. Java动态代理主要有两个核心类,I ...

  2. Java 动态代理机制分析及扩展--转

    http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/#icomments http://www.ibm.com/developerworks/c ...

  3. Java 动态代理机制分析及扩展,第 1 部分

    引言 Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执 ...

  4. Java 动态代理机制分析及扩展

    简介: 本文通过分析 Java 动态代理的机制和特点,解读动态代理类的源代码,并且模拟推演了动态代理类的可能实现,向读者阐述了一个完整的 Java 动态代理运作过程,希望能帮助读者加深对 Java 动 ...

  5. 用Java动态代理实现AOP

    在学习编程的过程中,我觉得不止要获得课本的知识,更多的是通过学习技术知识提高解决问题的能力,这样我们才能走在最前方,本文主要讲述用Java动态代理实现AOP,更多Java专业知识,广州疯狂java培训 ...

  6. java 动态代理实现原理

    上篇讲了:java动态代理浅析  这篇讲讲其内部实现原理. 1.相关的类和接口 1.1 java.lang.reflect.Proxy 这是 Java 动态代理机制的主类,它提供了一组静态方法来为一组 ...

  7. java动态代理【一】

    java动态代理的定义:为其他目标类的方法增加切面的逻辑,即在执行目标类方法的时候,先去执行一段如校验检测的逻辑代码.java通俗一点就是生成一个继承目标类的子类,并在每个调用方法都添加一段逻辑. 应 ...

  8. Java动态代理的实现

    动态代理作为代理模式的一种扩展形式,广泛应用于框架(尤其是基于AOP的框架)的设计与开发,本文将通过实例来讲解Java动态代理的实现过程. 友情提示:本文略有难度,读者需具备代理模式相关基础知识,. ...

  9. Java动态代理与Cglib代理

    为什么80%的码农都做不了架构师?>>>    最近又继续回来死磕Spring源码,以前看的也忘得差不多了,这次先把Spring使用的动态代理cglib看了一下,打好基础知识. cg ...

最新文章

  1. DataGrid删除确认及Item颜色交替
  2. 郭瑞东 | 如何制造更聪明的人工智能?让人工生命在复杂环境中进化
  3. android sdk 更新用的HOSTS
  4. 460. LFU 缓存
  5. struts配置访问后缀为.do,.action,.*
  6. 搭建Struts2开发环境
  7. java笔试面试题(五)
  8. 环境类sci期刊排名一区_这本国产SCI论文期刊今年首破5分,明年或超6分
  9. 电子罗盘的工作原理及校准
  10. 什么是EJB?不再神秘!
  11. Python requests常用的浏览器头部
  12. oracle全量拷贝,oracle数据库expdp异机全量备份
  13. debian上虚拟机安装系统
  14. 03-页面布局[Python]
  15. JWS-Exception
  16. 《我要飞,永远都不会累 》---伤感留言
  17. 聚类之层次聚类、基于划分的聚类(…
  18. Java中间件之介绍
  19. 基于vue的仿饿了么webapp
  20. php框架安装成功,thinkphp框架安装后怎么用?

热门文章

  1. MySQL row_format引发的案例一则
  2. OSGI 面向Java的动态模型系统
  3. 绑定线程到特定CPU处理器
  4. [转载]根据两点的经纬度求方位角和距离,等
  5. 深度神经网络的分布式训练概述:常用方法和技巧全面总结
  6. matlab调用c++生成dll32位与64位对应关系
  7. 两种高性能I/O设计模式(Reactor/Proactor)的比较
  8. OpenCV图像处理——修复失焦模糊的图像
  9. ssh客户端_Mobaxterm-不止是一款好用的SSH客户端软件
  10. 超出网络bios会话限制_?老旧BIOS说再见,拯救者系列设置超简单