Our Spring MVC web app is trying to follow the recommended style. It uses AppContext (ContextLoaderListener
) to store the DAO's and Services. It uses WebAppContext (DispatcherServlet
) to store Controllers.
The DAO objects are getting into both the AppContext and the WebAppContext. I don't understand why.
The AppContext config is supposed to load everything except the Controllers (and a class that loads code tables into the ServletContext):
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
@EnableTransactionManagement
@EnableScheduling
@ComponentScan(
basePackages = {"blah"},
excludeFilters = {
@Filter(type = FilterType.ANNOTATION, value = {Controller.class}),
@Filter(type = FilterType.ASSIGNABLE_TYPE, value = LoadOnStartup.class)
}
)
public class SpringRootConfiguration {
and the web part is supposed to load the Controllers only:
@Configuration
@EnableWebMvc
@ComponentScan(
basePackages = {"blah"},
includeFilters = @Filter(type = FilterType.ANNOTATION, classes={Controller.class})
)
public class SpringWebConfiguration extends WebMvcConfigurerAdapter {
(The above classes are in a separate package that is a sibling to 'blah'; there's no self-scanning going on).
Of course, the Controllers reference DAO objects. In the Controller, those DAO objects are @Autowired
.
My expectation was that those @Autowired
DAO objects are retrieved from the AppContext, and not created a second time, and placed in the WebAppContext. But I think they are being created a second time. For example, this line appears twice in the log, once for AppContext, and once for WebAppContext:
Creating shared instance of singleton bean 'labelDao'
Am I missing something?
It's as if the parent-child relation between the root context and the web context is missing.
When using an include
filter that doesn't automatically mean that the defaults are disabled. By default @ComponentScan
will detect all @Component
classes, regardless of what yu specify by the include
. So if you want to explicitly to control which annotations to scan you first have to disable the defaults. To do set the useDefaultFilters
attribute of @ComponentScan
to false
.
@ComponentScan(
basePackages = {"blah"},
useDefaultFilters=false,
includeFilters = @Filter(type = FilterType.ANNOTATION, classes={Controller.class})
)
Now it will only detect @Controller
annotated beans.