I think I found now a pretty nice project layout:
rootpackage.web.WebAppInitializer (see below)
rootpackage.web.SecurityWebAppInitializer (creates "springSecurityFilterChain")
rootpackage.web.WebMvcConfig (scans for everything in its own package and subpackages)
rootpackage.web.SecurityConfig (Spring Security config)
rootpackage.web.moduleA.SomeAController
rootpackage.web.moduleB.SomeBController
rootpackage.service.ServiceConfig (scans for everything in its own package and subpackages)
rootpackage.service.moduleA.AService
rootpackage.service.moduleA.AServiceImpl
rootpackage.service.moduleB.BService
rootpackage.service.moduleB.BServiceImpl
rootpackage.service.security.UserDetailsServiceImpl (for Spring Security)
rootpackage.model.DatabaseConfig (scans for everything in its own package and subpackages)
rootpackage.model.moduleA.SomeADomainObject
rootpackage.model.moduleB.SomeBDomainObject
WebAppInitializer:
@Order(2)
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] {
SecurityConfig.class,
ServiceConfig.class,
DatabaseConfig.class
};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebMvcConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
SecurityWebAppInitializer:
@Order(1) // should always be registered in first place (= before WebAppInitializer)
public class SecurityWebAppInitializer extends AbstractSecurityWebApplicationInitializer {
/* ... */
}
WebMvcConfig:
@Configuration
@EnableWebMvc
@ComponentScan // scans for everything in its own package and subpackages
// so it only finds SomeAController.class and SomeBController.class
public class WebMvcConfig extends WebMvcConfigurerAdapter {
/* ... */
}
SecurityConfig:
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/* ... */
}
ServiceConfig:
@Configuration
@ComponentScan // scans for everything in its own package and subpackages
// so it only finds AServiceImpl.class and BServiceImpl.class
public class ServiceConfig {
/* ... */
}
I put some "System.out.println" inside the constructor of all those classes in order to see how often they get registered/loaded. Each constructor is getting executed exactly once!
What do you think about this? Any improvements?