在之前的项目中,多数据源路由曾采用在接口上使用自定义注解指定数据源的方式实现。直到前几天,有同事反馈使用了自定义注解但是数据源切换没有生效,经过排查后,确认是多接口存在相同方法导致,简化后的部分代码如下,原 DAO 接口定义为:
1 | public interface BizDao { |
而后同事新写了个 DAO 接口并继承了 BizDao
,简化后的代码如下:
1 |
|
DAO 实现类简化后的代码如下:
1 | public class BizDaoImpl implements BizDao, BizAnalyticDao { |
切面中的数据源注解探测部分的代码如下:
1 | Method method = ((MethodSignature) pjp.getSignature()).getMethod(); |
即首先检查接口方法上的 @DataSource
注解,如果接口方法级别上没有该注解,则检查接口上的 @DataSource
注解。同事反馈的问题即为 BizAnalyticDao
中的 queryPage()
没有被路由至指定的 Database.ANALYTIC
数据源。因为很久之前曾看过动态代理的相关文档,看到接口继承后就想到了重复方法的问题,于是在源码中验证了下,确实是根据实现接口的顺序来决定的使用哪一个重复方法,在当前的实现中,如果多个接口中存在重复的方法,使用的为接口声明顺序中首次出现的方法,动态代理生成目标类的源码位于:ProxyGenerator.java at jdk8-b120:
1 | /** |
看到目标类是如何生成的就清楚未被路由的原因了,解决方案也很简单,此处不再赘述。
Reference
Methods Duplicated in Multiple Proxy Interfaces - Dynamic Proxy Classes
What is com.sun.proxy.$Proxy - Stack Overflow