【问题标题】:@Service are constructed twice@Service 被构造了两次
【发布时间】:2011-05-19 00:24:57
【问题描述】:

我的 Spring 应用程序出现问题,我的 @Service 类在应用程序启动时被创建了两次。我知道这是我的配置有问题,因为我以前经历过,但我到底做错了什么?

我在下面布置配置的方式有什么根本错误吗? (我省略了所有我认为不相关的内容)

web.xml:

<servlet>
    <servlet-name>myapp</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>myapp</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/myapp-config.xml
        /WEB-INF/myapp-security.xml
        /WEB-INF/myapp-mvc.xml
    </param-value>
</context-param>

<listener>
    <listener-class>com.myapp.servlet.MyAppContextListener</listener-class>
</listener>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

myapp-servlet.xml

<context:component-scan base-package="com.myapp" annotation-config="true" />
<mvc:annotation-driven />

myapp-config.xml

<context:component-scan base-package="com.myapp" annotation-config="true" />
<context:annotation-config />

【问题讨论】:

标签: spring spring-mvc


【解决方案1】:

除了@GaryF's answer,还有下面这个问题的漂亮解决方案(用在Spring Roo生成的项目中):

myapp-config.xml

<!-- Load everything except @Controllers -->
<context:component-scan base-package="com.myapp">
    <context:exclude-filter expression="org.springframework.stereotype.Controller"
        type="annotation"/>
</context:component-scan>

myapp-servlet.xml

<!-- Load @Controllers only -->
<context:component-scan base-package="com.myapp" use-default-filters="false">
    <context:include-filter expression="org.springframework.stereotype.Controller" 
        type="annotation"/>
</context:component-scan>

编辑:

myapp-config.xml 中删除&lt;context:component-scan&gt; 意味着,所有自动发现的带注释的bean 都注册在DispatcherServlet 的上下文中(即从myapp-servlet.xml 加载的上下文)。

但是,推荐的方法是使用 servlet 的上下文来处理特定于表示的事物(例如控制器),并将根上下文 (myapp-config.xml) 用于应用程序的核心服务。上面的解决方案使这种方法变得容易。

关于实际考虑,当您的核心服务被放置在 servlet 的应用程序上下文中时,不能从该 servlet 范围之外访问它们,例如,从另一个 servlet(您可能需要使用另一个 servlet 来实现另一个访问技术)或过滤器(例如Spring Security过滤器)。这就是在根应用程序上下文中拥有核心服务的原因。

【讨论】:

  • 现在我在 myapp-config.xml 中根本不使用它,而且一切似乎都正常。您的解决方案有什么好处?
  • 这很好用。对于实现它的其他人,您可能需要在 servlet.xml 中定义 Spring Security 的
  • 这是一个非常聪明的解决方案。
【解决方案2】:

作为@axtavt 给出的答案的补充,我想在这里给出匹配的Spring JavaConfig。

RootConfig.java:

@ComponentScan(basePackages = { "com.myapp" },
    excludeFilters = @Filter({Controller.class, Configuration.class}))

WebMvcConfig.java:

@ComponentScan(basePackages = { "com.myapp" },
    useDefaultFilters = false, includeFilters = @Filter(Controller.class))

【讨论】:

    【解决方案3】:

    您正在对同一个基本包进行两次单独的组件扫描。删除其中一个。

    【讨论】:

    • 看起来我需要在 -servlet 中,否则没有任何效果。我已经从 -config 中删除了它,一切似乎都恢复了正常!
    • 但是实例不是默认由Spring单例创建的吗?还是仅在同一个 ApplicationContext 中为真?
    • @Abhijeet - 是的,它们是同一上下文中的单例(默认情况下)。这是两个离散的上下文。
    猜你喜欢
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-02
    • 1970-01-01
    • 2021-05-16
    • 2012-06-11
    • 2019-05-09
    相关资源
    最近更新 更多