运行 多个 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 作为依赖项

我对开始我的应用程序有一些疑问。

  1. 如何在单个 JVM 中同时启动后端和 Web 服务? (在同一个端口)
  2. 我想在我的后端和网络服务项目中自动连接 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)