Java Spring引导-使用其他项目中定义的实现

Java Spring引导-使用其他项目中定义的实现,java,spring,spring-boot,maven,dependency-injection,Java,Spring,Spring Boot,Maven,Dependency Injection,我有两个项目 演示父项目(spring boot应用程序)中定义的所有API契约(接口) 演示子项目(spring boot应用程序)中定义的实现 demo-parent是demo-child的依赖项,在demo-child的pom.xml中定义 在演示父级中: AccessAPI.java public interface AccessAPI { void call(); } @SpringBootApplication public class SpringDemoParen

我有两个项目

  • 演示父项目(spring boot应用程序)中定义的所有API契约(接口)
  • 演示子项目(spring boot应用程序)中定义的实现
  • demo-parentdemo-child的依赖项,在demo-child的pom.xml中定义

在演示父级中:

AccessAPI.java

public interface AccessAPI {
    void call();
}
@SpringBootApplication
public class SpringDemoParentApplication {

    @Autowired
    private AccessAPI accessAPI;

    public static void main(String[] args) {
        SpringApplication.run(SpringDemoParentApplication.class, args);
    }

    @PostConstruct
    void exec() {
        accessAPI.call();
    }
}
@Service
public class AccessAPIImpl implements AccessAPI {
    @Override
    public void call() {
        System.out.println("Executing from AccessAPIImpl");
    }
}
SpringDemoParentApplication.java

public interface AccessAPI {
    void call();
}
@SpringBootApplication
public class SpringDemoParentApplication {

    @Autowired
    private AccessAPI accessAPI;

    public static void main(String[] args) {
        SpringApplication.run(SpringDemoParentApplication.class, args);
    }

    @PostConstruct
    void exec() {
        accessAPI.call();
    }
}
@Service
public class AccessAPIImpl implements AccessAPI {
    @Override
    public void call() {
        System.out.println("Executing from AccessAPIImpl");
    }
}

在演示子项中,我有服务的实现:

accessapimpl.java

public interface AccessAPI {
    void call();
}
@SpringBootApplication
public class SpringDemoParentApplication {

    @Autowired
    private AccessAPI accessAPI;

    public static void main(String[] args) {
        SpringApplication.run(SpringDemoParentApplication.class, args);
    }

    @PostConstruct
    void exec() {
        accessAPI.call();
    }
}
@Service
public class AccessAPIImpl implements AccessAPI {
    @Override
    public void call() {
        System.out.println("Executing from AccessAPIImpl");
    }
}


努力实现的目标: 我必须能够独立构建这些项目,并通过类路径传递演示子项目项目jar,以选择实现并在运行演示父项目时注入所有实现。 例如:

>java -jar demo-parent.jar -cp demo-child.jar
我预计实现将从演示子项中拾取并自动注入,但它没有按预期工作
注意:我不想在演示父项上添加演示子项依赖项,必须在运行时获取实现/依赖项


请检查Git存储库:


TL;TR

java -cp demo-parent.jar -Dloader.path=demo-child.jar org.springframework.boot.loader.PropertiesLauncher
如果demo-child.jar是Spring Boot应用程序,即如果jar被Spring Boot插件重新打包,则需要更改加载程序路径:

java -cp demo-parent.jar -Dloader.path='demo-child.jar!/BOOT-INF/classes' org.springframework.boot.loader.PropertiesLauncher
说明:

默认情况下,SpringBoot使用JarLauncher,它只在jar归档文件的Boot-INF/lib/中查找,
-cp
参数无效。上面的命令切换到PropertiesLauncher,它接受
loader.path
参数(
-cp
等效项)。详情请参阅

顺便说一句,项目结构似乎有点问题:

  • 将spring引导应用程序(demo parent.jar)作为依赖项添加到demo-child.jar是很棘手的,因为demo-parent.jar被spring引导插件重新打包,maven找不到AccessAPI类
  • 即使POM中没有明确指定,也存在运行时循环依赖项
我不知道详细要求,但如果可能,我建议:

  • 将接口提取到单独的项目,比如说演示api
  • 制作演示父级和演示子级依赖于演示api,而不是相互依赖
  • 制作演示api演示子项常规jar,而不是Spring引导应用程序(删除Spring引导插件)

感谢您的回复。但解决方案没有奏效。我得到以下异常:线程“main”java.lang.IllegalArgumentException中的异常:文件D:\Workout\Spring\Spring boot runtime jar load parent\target\'child.jar必须存在。它必须与路径有关。有一个'before child.jar'吗?这是我运行的:java-cp parent.jar-Dloader.path='child.jar/BOOT-INF/classes'org.springframework.BOOT.loader.propertiesLauncher我用双引号运行时,没有看到IllegalArgumentException::>java-cp parent.jar-Dloader.path=“child.jar!/BOOT-INF/classes”org.springframework.BOOT.loader.propertiesLauncher好吧,它不会那样工作。您需要将
springdemochild
制作成
springdemoparent
的子包(不一定直接),或者将
@ComponentScan(“com.savk.workout.spring.springdemochild”)
注释添加到
SpringDemoParentApplication
。看见