@Service构造了两次

Ste*_*eve 28 spring spring-mvc

我的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>
Run Code Online (Sandbox Code Playgroud)

MYAPP-servlet.xml中

<context:component-scan base-package="com.myapp" annotation-config="true" />
<mvc:annotation-driven />
Run Code Online (Sandbox Code Playgroud)

MYAPP-config.xml中

<context:component-scan base-package="com.myapp" annotation-config="true" />
<context:annotation-config />
Run Code Online (Sandbox Code Playgroud)

axt*_*avt 34

除了@ GaryF的答案之外,还有一个针对此问题的以下漂亮解决方案(用于生成的项目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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

编辑:

<context:component-scan>myapp-config.xml平均值中删除所有自动发现的带注释的bean都在DispatcherServlet上下文中注册(即从中加载的上下文myapp-servlet.xml).

但是,建议的方法是将servlet的上下文用于特定于表示的事物(例如控制器),并将根上下文(myapp-config.xml)用于应用程序的核心服务.上述解决方案使这种方法变得简单.

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


Mic*_*fel 15

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

RootConfig.java:

@ComponentScan(basePackages = { "com.myapp" },
    excludeFilters = @Filter({Controller.class, Configuration.class}))
Run Code Online (Sandbox Code Playgroud)

WebMvcConfig.java:

@ComponentScan(basePackages = { "com.myapp" },
    useDefaultFilters = false, includeFilters = @Filter(Controller.class))
Run Code Online (Sandbox Code Playgroud)


Gar*_*ryF 9

您正在同一个基础包上进行两次单独的组件扫描.删除其中一个.

  • @Abhijeet - 是的,他们是同一个环境中的单身人士(默认情况下).这是两个离散的上下文. (2认同)