java - 带有 Spring 和模块的六边形架构
问题描述
我正在尝试在具有多个Maven
模块的 Spring Boot 应用程序上实现 Hexagonal 架构。主要思想依赖于抽象,而不是具体。我创建了三个模块test-core,test-adapter,test-application基本上如此处所述:
┌ \ pom.xml
├ \ test-core
│ ├ pom.xml
│ └─ src\com\example\core\
| ├─ ConfigCore.java
| └─ FooService.java
├ \ test-adapter
│ ├ pom.xml
| └─ src\com\example\adapter\
| ├─ ConfigAdapter.java
| └─ FooServiceImpl.java
└ \ test-application
├ pom.xml
└─ src\com\example\
├─ ConfigApplication.java
└─ Application.java
主要思想是具有下一个依赖项:
- 测试适配器依赖于测试核心
- 测试应用依赖于测试核心
就这样。但是,如果没有第三个依赖项,则无法实现test-application依赖于test-adapter。在给定的示例中,我使用了它们以这种方式进行操作(添加了直接依赖项)。但是我想避免这种情况,因为我希望在没有这种耦合的情况下进行架构设计。是否有可能以某种方式实施?还是我想要的太多?或者我错误地理解了端口和适配器架构?
为了使问题更清楚,您可以在下面找到代码。FooServices.java
package com.example.core;
public interface FooService { String execute(); }
FooServiceImpl.java
package com.example.adapter;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Qualifier;
import com.example.core.FooService;
@Service
@Qualifier("fooService")
public class FooServiceImpl implements FooService {
public String execute() { return "Hello world!"; }
}
应用程序.java
package com.example;
@SpringBootApplication(scanBasePackages = {"com.example"})
public class Application {
@Autowired
@Qualifier("fooService")
FooService fooService;
public static void main(String[] args) { SpringApplication.run(Application.class, args); }
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) { return args -> { System.out.println(fooService.execute()); }; }
}
在\test-application\pom.xml中没有对test-adapter的书面依赖
<dependency>
<groupId>com.example</groupId>
<artifactId>test-adapter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
我不断收到下一个错误
上下文初始化期间遇到异常 - 取消刷新尝试:org.springframework.beans.factory.UnsatisfiedDependencyException:创建名为“application”的bean时出错:通过字段“fooService”表达的不满足的依赖关系;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有可用的“com.example.core.FooService”类型的合格 bean:预计至少有 1 个有资格作为自动装配候选者的 bean。依赖注解:{@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=fooService)}
如您所见@Qualifier
,注释在这里没有帮助。@ComponentScan(basePackages = {"com.example"})
,@SpringBootApplication(scanBasePackages = {"com.example"})
以及。
解决方案是执行后续步骤: ConfigCore.java
package com.example.core;
@Configuration
@ComponentScan(basePackages = {"com.example.core"})
public class ConfigCore { }
配置适配器.java
package com.example.adapter;
@Configuration
@ComponentScan(basePackages = {"com.example.adapter"})
public class ConfigAdapter { }
配置应用程序.java
package com.example;
import com.example.core.ConfigCore;
import com.example.adapter.ConfigAdapter;
@Configuration
@ComponentScan(basePackages = {"com.example"})
@Import({ConfigCore.class, ConfigAdapter.class})
public class ConfigApplication { }
并将相应的依赖项(如上所述)放入pom.xml。在这种情况下,一切正常。但是,正如我提到的,我认为这不是正确的方法。您能否帮助我了解消除test-adapter和test-application之间这种依赖关系的可能性?
解决方案
这与六边形架构并没有真正的关系。
SpringBootApplication 将需要在类路径中所有要在 ApplicationContext 中公开的 bean。
我想在你的情况下,这个类位于test-application。如果您没有对test-adapter设置任何依赖项,则不会加载配置,因此您的 ComponentScan 无效。
即使是 SpringBoot 中的神奇自动配置 bean,也必须至少在 pom.xml 的运行时范围内声明
而且在Hexagonal Architecture实现中,我们通常使用应用模块来组成bean注入策略。所以你应该把你的配置放在这一层。
适配器用于与您的域进行交互,例如 Rest 层。
给定的六边形架构实现示例有一个模块,其中收集了应用程序和适配器。但是如果你想拆分它,你基本上会得到:
- 在应用程序模块中:配置和 *Application
- 在 youtube 适配器中:youtube 包(在这种情况下为 SPI)
- 在休息适配器中:控制器和资源
但是应用程序模块必须依赖于每个适配器。
六边形架构的主要目的是将业务逻辑与技术部分解耦。没有说明适配器应该是独立的,但无论如何它都可以是您的实现选择:)
推荐阅读
- opengl - 具有多个点光源的 Cook-Torrance 着色器
- python - 在 concurrent.futures.ProcessPoolExecutor map() 和 submit() 方法中使用 numpy.fromiter 和 numpy.array 的问题
- c# - 年度和季度数据 SQL
- node.js - 无法将一个猫鼬模型的数据添加到另一个模型中
- c# - Assert.AreEqual 问题与验证错误 c# Selenium
- android - 从 Windows 语言环境代码中获取语言名称
- firebase - 如何向 Google 云打印进行身份验证
- sql - 如何将数据插入本地数据库(表)
- javascript - 如何使用 JavaScript 方法创建“或”条件?
- macos - 如何在 mac os 10.13 上安装 php-redis 扩展?