@Service are constructed twice
Solution 1:
In addition to @GaryF's answer, there is a following beautiful solution for this problem (used in projects generated by 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>
EDIT:
Removing <context:component-scan>
from myapp-config.xml
means, that all your autodiscovered annotated beans are registered in DispatcherServlet
's context (that is, the context loaded from myapp-servlet.xml
).
However the recommended approach is to use servlet's context for presentation-specific things (such as controllers), and use the root context (myapp-config.xml
) for the core services of your application. The solution above make this approach easy.
Regarding the practical considerations, when your core services are placed in servlet's application context, they can't be accessed from outside the scope of that servlet, for example, from another servlets (you may need to use another servlets to implement another access technologies) or filters (such as Spring Security
filters). That's the reason for having core services in the root application context.
Solution 2:
As an addition to the answer @axtavt gave, I’d like to give the matching Spring JavaConfig here.
In RootConfig.java
:
@ComponentScan(basePackages = { "com.myapp" },
excludeFilters = @Filter({Controller.class, Configuration.class}))
In WebMvcConfig.java
:
@ComponentScan(basePackages = { "com.myapp" },
useDefaultFilters = false, includeFilters = @Filter(Controller.class))
Solution 3:
You're doing two separate component-scans over the same base-package. Remove one of them.