运行 多个 Spring 在同一 JVM 上启动应用程序
Running multiple Spring boot applications on same JVM
我有一个多 Maven 模块 Spring 引导项目具有以下结构:
parent
|_ pom.xml
|_ webservices
|_ src/main/java
|_ webservices
|_ WebServicesConfig.java
|_ WebServicesStarter.java
|_ GlobalPropertiesLoader.java
|_ pom.xml
|_ backend
|_ src/main/java
|_ backend
|_ BackendStarter.java
|_ pom.xml
|_ commons
|_ src/main/java
|_ commons
|_ GlobalPropertiesDAO.java
|_ GlobalPropertiesRepository.java
|_ CommonsConfig.java;
|_ pom.xml
Web 服务和后端都是单独的 Spring 引导应用程序(它们生成一个我用来启动它们的 jar 文件)并且它们依赖于 commons 模块。所以我在 web 服务和后端 pom.xml.
中包含了 commons 作为依赖项
我对开始我的应用程序有一些疑问。
- 如何在单个 JVM 中同时启动后端和 Web 服务? (在同一个端口)
- 我想在我的后端和网络服务项目中自动连接 GlobalPropertiesRepository(位于公共项目中)。我该怎么做呢?我可以自动连接不同的模块吗?仅仅导入公地是行不通的。它抛出 "no bean definition error"。我认为这是因为如果我导入 GlobalPropertiesRepository,Spring 容器不会启动它。
=============更新=============
为应用程序添加我的配置 classes:
公共应用程序目前有一个空的配置 class,因为我只有我的存储库 class 在那里。下面是空配置 class:
package commons;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CommonsConfig {
}
这是 GlobalPropertiesRepository:
package commons;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface GlobalPropertiesRepository extends CrudRepository<GlobalPropertiesDAO, Long>{
}
以下是 Web 服务应用程序中必需的 classes:
首发class:
package webservices;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
@SpringBootApplication
@EnableJpaRepositories
@ComponentScan({"commons", "webservices"})
public class WebServicesStarter {
public static void main(String[] args) throws Exception {
SpringApplication.run(WebServicesStarter.class, args);
ClassPathScanningCandidateComponentProvider provider =
new ClassPathScanningCandidateComponentProvider(true);
}
}
配置class:
package webservices;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import commons.CommonsConfig;
@Configuration
@Import(CommonsConfig.class)
public class WebServicesConfig {
@Autowired CommonsConfig commonsConfig;
public WebServicesConfig() {
}
}
还有 class 我正在尝试自动装配存储库的地方:
package webservices;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import commons.GlobalPropertiesDAO;
import commons.GlobalPropertiesRepository;
@Component
@Scope("singleton")
public class GlobalPropertiesLoader {
@Autowired
public GlobalPropertiesRepository globalPropertiesRepository;
private GlobalPropertiesDAO globalProperties;
@PostConstruct
public void init(){
globalProperties = globalPropertiesRepository.findOne(1L);
}
public GlobalPropertiesDAO getGlobalProperties(){
return globalProperties;
}
}
这是我得到的错误:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: public commons.GlobalPropertiesRepository webservices.GlobalPropertiesLoader.globalPropertiesRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [commons.GlobalPropertiesRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
谢谢。
我想我知道是什么导致了错误。
在您的应用启动程序 class 中,即使出于某种原因您拥有 @ComponentScan({"commons", "webservices"})
,@Repository
bean 也被忽略了。我认为问题出在 class ClassPathBeanDefinitionScanner 中。根据文档 JavaDoc,它确实声明默认情况下它将扫描所有组件,包括 @Repository
。但是当它识别存储库接口时,它在方法 isCandidateComponent 中的另一次检查失败了。 (如果你查看源代码)
所以当你启用调试时我们会得到这个日志
2015-05-18 11:10:13.399 DEBUG 67917 --- [ main] o.s.c.a.ClassPathBeanDefinitionScanner : Ignored because not a concrete top-level class: file [****/jpa-test/dl/target/classes/commons/GlobalPropertiesRepository.class]
此外,因为EnableJpaRepositories
只扫描声明它的包,仓库没有被初始化。
如果您将 baseClassPackage
(类型安全)属性 设置为 @EnableJpaRepositories(basePackageClasses = GlobalPropertiesRepository.class)
,那么存储库会被初始化。还要确保添加 @EntityScan(basePackageClasses = GlobalPropertiesDAO.class)
我有一个多 Maven 模块 Spring 引导项目具有以下结构:
parent
|_ pom.xml
|_ webservices
|_ src/main/java
|_ webservices
|_ WebServicesConfig.java
|_ WebServicesStarter.java
|_ GlobalPropertiesLoader.java
|_ pom.xml
|_ backend
|_ src/main/java
|_ backend
|_ BackendStarter.java
|_ pom.xml
|_ commons
|_ src/main/java
|_ commons
|_ GlobalPropertiesDAO.java
|_ GlobalPropertiesRepository.java
|_ CommonsConfig.java;
|_ pom.xml
Web 服务和后端都是单独的 Spring 引导应用程序(它们生成一个我用来启动它们的 jar 文件)并且它们依赖于 commons 模块。所以我在 web 服务和后端 pom.xml.
中包含了 commons 作为依赖项我对开始我的应用程序有一些疑问。
- 如何在单个 JVM 中同时启动后端和 Web 服务? (在同一个端口)
- 我想在我的后端和网络服务项目中自动连接 GlobalPropertiesRepository(位于公共项目中)。我该怎么做呢?我可以自动连接不同的模块吗?仅仅导入公地是行不通的。它抛出 "no bean definition error"。我认为这是因为如果我导入 GlobalPropertiesRepository,Spring 容器不会启动它。
=============更新=============
为应用程序添加我的配置 classes:
公共应用程序目前有一个空的配置 class,因为我只有我的存储库 class 在那里。下面是空配置 class:
package commons;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CommonsConfig {
}
这是 GlobalPropertiesRepository:
package commons;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface GlobalPropertiesRepository extends CrudRepository<GlobalPropertiesDAO, Long>{
}
以下是 Web 服务应用程序中必需的 classes:
首发class:
package webservices;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
@SpringBootApplication
@EnableJpaRepositories
@ComponentScan({"commons", "webservices"})
public class WebServicesStarter {
public static void main(String[] args) throws Exception {
SpringApplication.run(WebServicesStarter.class, args);
ClassPathScanningCandidateComponentProvider provider =
new ClassPathScanningCandidateComponentProvider(true);
}
}
配置class:
package webservices;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import commons.CommonsConfig;
@Configuration
@Import(CommonsConfig.class)
public class WebServicesConfig {
@Autowired CommonsConfig commonsConfig;
public WebServicesConfig() {
}
}
还有 class 我正在尝试自动装配存储库的地方:
package webservices;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import commons.GlobalPropertiesDAO;
import commons.GlobalPropertiesRepository;
@Component
@Scope("singleton")
public class GlobalPropertiesLoader {
@Autowired
public GlobalPropertiesRepository globalPropertiesRepository;
private GlobalPropertiesDAO globalProperties;
@PostConstruct
public void init(){
globalProperties = globalPropertiesRepository.findOne(1L);
}
public GlobalPropertiesDAO getGlobalProperties(){
return globalProperties;
}
}
这是我得到的错误:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: public commons.GlobalPropertiesRepository webservices.GlobalPropertiesLoader.globalPropertiesRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [commons.GlobalPropertiesRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
谢谢。
我想我知道是什么导致了错误。
在您的应用启动程序 class 中,即使出于某种原因您拥有 @ComponentScan({"commons", "webservices"})
,@Repository
bean 也被忽略了。我认为问题出在 class ClassPathBeanDefinitionScanner 中。根据文档 JavaDoc,它确实声明默认情况下它将扫描所有组件,包括 @Repository
。但是当它识别存储库接口时,它在方法 isCandidateComponent 中的另一次检查失败了。 (如果你查看源代码)
所以当你启用调试时我们会得到这个日志
2015-05-18 11:10:13.399 DEBUG 67917 --- [ main] o.s.c.a.ClassPathBeanDefinitionScanner : Ignored because not a concrete top-level class: file [****/jpa-test/dl/target/classes/commons/GlobalPropertiesRepository.class]
此外,因为EnableJpaRepositories
只扫描声明它的包,仓库没有被初始化。
如果您将 baseClassPackage
(类型安全)属性 设置为 @EnableJpaRepositories(basePackageClasses = GlobalPropertiesRepository.class)
,那么存储库会被初始化。还要确保添加 @EntityScan(basePackageClasses = GlobalPropertiesDAO.class)