在SpringMVC Action中使用事务需要特别小心的地方

一般的J2EE项目都会使用Hibernate,也同时会用Spring作为IOC的框架以管理Bean,如果同时使用SpringMVC作为MVC框架的话,系统中就会有两个Bean的容器。这是,我们一般在Spring的Bean容器配置中将Controller排除,如下:

<context:component-scan base-package="com.storm">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

同时在SpringMVC的配置文件中将Service排除

<context:component-scan base-package="com.storm">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />
    </context:component-scan>

我们一般会在Action中动态注入一些Service。在SpringMVC的action初始化的过程中,它扫描到一些通过@Autowire或@Resource这些注解标识的Bean,它会优先在mvc的bean容器中寻找,如果没有找到,再到上一层的Spring Bean容器中找。

问题往往就出在这里!!!!!!!

如果我们将Service实现类(XXXServiceImpl)的类注解由@Service改为@Component,这时,在SpringMVC的action初始化的过程中,它扫描到action中调用了一些Component组件,SpringMVC的Bean容器也会加载这个Servcie的实例。但事务是在上一层的Spring Bean容器中,这就导致SpringMVC的Bean容器中的Servcie实例在实际运行中是无法被织入事务的。这样,在整个应用中,就同时存在两个Service的实例,其中一个在SpringMVC容器中的实例没有事务,而在Spring Bean容器中的实例有事务。而action的运行优先采用的是SpringMVC容器中的实例,这就导致具体牵涉到数据库的操作都不会有事务的发生。具体表现在insert,update,delete等操作往往正常执行,但数据库中的数据没有发生变化。

 看到这里,也行有些人会问,如果我在SpringMVC的context:component-scan配置中再加一行

<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Component" />

这样,SpringMVC也就不扫描Component标注的Bean了,不就解决这个问题了?

这样也不行,Component是Controller和Service的基类,如果加了上面一行,所有的Controller组件也都不会被加载,所有的action组件都不会生效了!!!

所以,最好的办法就是将Service的实现类都标注为@Service,以免被SpringMVC的Bean容器所加载!!!

猜你喜欢

转载自blog.csdn.net/longlongriver/article/details/11979161