集成多数据源和redis后,多数据源能起作用,但是redis缓存不起作用,@Cacheable等标签没有任何作用。调试发现,redis-context.xml配置是挂在spring-mvc.xml配置里的,
但是配置文件里没有加入对service包的扫描。于是在spring-mvc.xml里增加
<context:component-scan base-package="com.musa.app.service" />
重启后能进行缓存了。但是另一个问题又来了,多数据源切换又不起作用了。原来这和web容器加载配置文件,以及配置文件的生效范围有关。
web容器先加载spring上下文配置文件,然后在加载springmvc配置文件。如如下的web.xml配置
<!-- Spring MVC servlet -->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<!-- 此处可以可以配置成*.do,对应struts的后缀习惯 -->
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<!-- Spring和mybatis的配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-*.xml</param-value>
</context-param>
先加载的就是<context-param>中contextConfigLocation里定义的配置文件,然后加载servlet节点中SpringMVC定义的spring-mvc.xml。而且有相同的内容,后加载的会覆盖前面的内容,也就是说,spring-mvc.xml里定义的内容优先级更大。
而redis缓存配置必须要配置在spring-mvc.xml里,因此在spring-mvcl.xml里重新定义了包扫描,因此扫描的时候会将spring上下文里配置的mybatis配置的类扫描信息覆盖掉,因此,多数据源支持就被冲掉了。
为了解决这个问题,只能在spring-mvc.xml里再次importmybatis.xml,让包扫描的时候同时处理缓存标签和多数据源标签。在spring-mvc.xml的末尾加入
<import resource="spring-mybatis.xml"/>
重启之后,发现问题解决了。
这个问题困扰了我半天,今天搜了下,发现篇文章,讲的更清楚。
http://blog.csdn.net/trigl/article/details/52073457
在web.xml中定义的spring的配置文件一般有两个:
1、Spring上下文环境的配置文件:applicationContext.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml
</param-value>
</context-param>
2、SpringMVC配置文件:spring-servlet.xml
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
加载顺序是:首先加载Spring上下文环境配置文件,然后加载SpringMVC配置文件,并且如果配置了相同的内容,SpringMVC配置文件会被优先使用。
所以这里需要注意一个问题,一定要注意SpringMVC配置文件内容不要把Spring上下文环境配置文件内容覆盖掉。
比如在Spring上下文环境配置文件中先引入service层,然后又加入了事务:
<context:component-scan base-package="com.acms.service"></context:component-scan>
<!-- define the transaction manager -->
<bean id="transactionManagerOracle"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSourceOracle" />
</bean>
<tx:annotation-driven transaction-manager="transactionManagerOracle" />
但是在SpringMVC配置文件中却默认引入所有类(当然也包括service层),但是没有加入事务
<context:component-scan base-package="com.acms"></context:component-scan>
那么这时事务功能是无法起作用的,也就是代码中加入@Transactional注解是无效的。
所以为了防止这种问题一般是在Spring上下文配置文件中引入所有的类,并且加上事务:
<context:component-scan base-package="com.acms"></context:component-scan>
<!-- define the transaction manager -->
<bean id="transactionManagerOracle"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSourceOracle" />
</bean>
<tx:annotation-driven transaction-manager="transactionManagerOracle" />
而在SpringMVC配置文件中只引入controller层:
<context:component-scan base-package="com.acms.controller" />
<context:component-scan base-package="com.acms.*.controller" />