Я пытаюсь реализовать шестиугольную архитектуру поверх приложения Spring Boot с несколькими модулями Maven
. Основная идея зависеть от абстракций, а не от конкреций.
Я создал три модуля 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-core
и все. Однако невозможно реализовать без третьей зависимости, где test-application зависит от test-adapter . В данном примере, который я использовал, они сделали это таким образом (добавили прямую зависимость). Однако я хотел бы избежать этого, так как я хочу иметь архитектурный дизайн без такой связи.
Можно ли как-то реализовать? Или я хочу слишком много? Или я неправильно понимаю архитектуру Ports-And-Adapters?
Чтобы сделать проблему более понятной, ниже вы можете найти код. 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!"; }
}
Application.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': неудовлетворенная зависимость, выраженная через поле 'fooService'; вложенное исключение - org.springframework.beans.factory.NoSuchBeanDefinitionException: нет доступного квалифицирующего компонента типа 'com.example.core.FooService': ожидается как минимум 1 компонент, который квалифицируется как кандидат для автоматического подключения. Аннотации зависимостей: {@ org.springframework.beans.factory.annotation.Autowired (обязательно = 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 { }
ConfigAdapter.java
package com.example.adapter;
@Configuration
@ComponentScan(basePackages = {"com.example.adapter"})
public class ConfigAdapter { }
ConfigApplication.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 ?