网店版重生系列:都是Spring配置中自动注入惹的祸

在对Spring Container管理的bean进行配置时,有一个很好用的功能就是自动注入,可以根据不同规则对bean所依赖的bean进行自动set,相信最常用的就是设置default-autowire="byName"这种方式啦;这样我们在进行配置时就可以减少很多的xml代码、当我们在Java代码中新增或减少bean的注入时就无需再对xml配置进行同步变更(针对采取xml配置的方式,若采用Annotation的方式则不存在该问题),从而提高了编码效率;

一般情况下采取这种自动注入的方式MS也没啥问题,但是在一些特殊情况下可能会导致莫名其妙的问题,从而要花费大量的时间去排错;在最近的一个项目中就被我遇上了;问题大概是这样的:以前的应用基于Oracle单数据源进行开发,Spring配置采取byName自动注入;但由于数据量剧增导致Oracle服务器不堪重负,小型机扩容成本太高,于是我们决定将原有应用改造成基于Mysql的按用户水平划分的分布式DB结构;这样的话,就需要修改DAO层关于datasource相关的一些配置,在调整过程中,问题就产生了;

原有与datasource相关的大致配置如下:

所有的DAO配置中都设置parent="daoDefinition",并在Java实现中extends SqlMapClientDaoSupport;

应用改造时,我们采用了基于Spring的AbstractRoutingDataSource来实现动态数据源的加载,但由于应用中只有部分表的数据能进行分库,所以改造后的系统中将会存在两种类型的数据源,其一仍然为原Oracle主库,通过JNDI访问、其二为新增的Mysql分库,通过动态ds访问;

由于AbstractRoutingDataSource从当前线程中获取绑定的用户信息,而在同一次用户的操作中,可能会存在既访问原来的Oracle主库、又访问Mysql分库的情况,所以动态ds中需要兼容这种情况,并且在每次DB操作完成之后需要清空当前线程中绑定的变量,这样主要是为了避免所有的DAO层都进行变动,但在哪里自动完成当前线程绑定变量的清空操作呢?当然是在SqlMapClientTemplate中,因为所有的DAO操作都是通过这个template封装接口进行访问的,所以需要继承该类并对所有的method进行扩展;新的配置如下:

涉及到访问Mysql分库的DAO均设置parent="ddbDaoDefinition",并在Java实现中extends DdbSqlMapClientDaoSupport;

这样的配置MS没有问题,template中已经明确设置采用动态ds,DAO实现类中也已明确继承新的template类!后来经跟踪代码发现:还是Spring的自动注入惹的祸
原因如下:

SqlMapClientDaoSupport中可以自动注入3个bean:datasource、sqlMapClient、sqlMapClientTemplate;而这3个bean的注入是有先后顺序的,其实datasource、sqlMapClient都是设置到sqlMapClientTemplate中的!问题就出现在这里了;
在我们的配置中,parent中显示设置了sqlMapClientTemplate,而没有设置其他两个属性;按照Spring自动注入的默认规则,首先会将显示set的bean注入,此时的sqlMapClientTemplate是被设置了动态ds的正确的bean,但是显示set注入完成之后,Spring还会根据是否自动注入扫描bean里面的set方法,完成非显示bean的注入,此时问题就出现了,Spring根据默认datasource这个name找到了原有的基于JNDI的那个bean进行注入了,于是sqlMapClientTemplate中的datasource就被覆盖了,也即原来正确的动态ds被替换回了原有的基于JNDI的Oracle主库的datasource!

原因找到之后问题就好解决了,方法很多,比如:

  1. 在ddbDaoDefinition配置中增加显示设置<property name="dataSource" ref="mixedDdbDatasource"/>;
    注意:为保险起见,这个显示datasource的set放在sqlMapClientTemplate之后,因为Spring会按照设置的先后顺序进行注入,若放在sqlMapClientTemplate之前,则会被后者覆盖掉,具体依赖于被注入bean内set方法的实现;
  2. 去掉DAO配置文件中的自动注入;其实DAO层一般不会依赖于其他的bean,都是被依赖的,所以这个自动注入完全没有必要,反而给应用带来隐患;
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值