我刚刚开始了一个新的春季项目,这次我想做“正确”的事情.在上一个项目中,由于多个@ComponentScan注释,我遇到了多个注册某些类的问题. (即所有服务类都已注册两次)
基本上我使用以下布局:
WebAppInitializer:
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class>[] getRootConfigClasses() {
return new Class[] { RootConfig.class };
}
@Override
protected Class>[] getServletConfigClasses() {
return new Class[] { WebMvcConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
RootConfig:
@Configuration
@ComponentScan
public class RootConfig {
/* ... */
}
WebMvcConfig:
@EnableWebMvc
@ComponentScan
public class WebMvcConfig extends WebMvcConfigurerAdapter {
/* ... */
}
DatabaseConfig:
@Configuration
@EnableJpaRepositories("my.base.class.path")
public class DataConfig {
/* ... */
}
第一个基本问题是:哪个类应该扫描哪些类/注释?
是否只有WebMvcConfig扫描@Controller类?哪一个应该扫描@Service以及@Configuration和@Component?
第二个问题是:或者我应该只使用包来缩小扫描路径?
例:
rootpackage
rootpackage.config.RootConfig
rootpackage.config.DatabaseConfig
rootpackage.mvc.WebMvcConfig
然后将所有@Controller类放在rootpackage.mvc下.*?
第三个问题是:让RootConfig扫描DatabaseConfig更常见吗?或者我应该将DatabaseConfig放在WebAppInitializer类的getRootConfigClasses方法中?
最后一个问题是:在一个多模块项目中:你如何组织这些事情?
示例:如果我选择问题二中描述的方式,我可以说,应用程序的每个模块实际上都包含几个不同的模块.比方说,我想创建一个模块X,它将有一个@Service类和一些@Controller类,我可以将它们放在不同的包中.像这样:
Maven模块X服务
rootpackage.services.x.XService
rootpackage.services.x.XServiceImpl
Maven模块X控制器
rootpackage.mvc.controller.x.X1Controller
rootpackage.mvc.controller.x.X2Controller
rootpackage.mvc.controller.x.X3Controller
如果你建议这样做,那么:在哪里放置模型和存储库(用于访问数据库)?我应该为每个模块创建一个新模块吗?
提前致谢!
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 {
/* ... */
}
我在所有这些类的构造函数中放了一些“System.out.println”,以便查看它们注册/加载的频率.每个构造函数都执行一次!
你怎么看待这件事?有什么改进?