Внедрение зависимостей на основе конструктора не выполняется при запросе bean-компонента через beanFactory.getBean(CommaJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Внедрение зависимостей на основе конструктора не выполняется при запросе bean-компонента через beanFactory.getBean(Comma

Сообщение Anonymous »

Я перехожу с внедрения на местах (

Код: Выделить всё

@Autowired
) для внедрения на основе конструктора в приложение Spring Boot (Java 21), но я сталкиваюсь с BeanCreationException, когда Spring пытается создать экземпляр моего командного объекта.

Единственная зависимость, которую Spring должен автоматически подключать, — это Service.
DTO — это не bean-компонент Spring, и контроллер должен предоставлять его вручную, поэтому я извлекаю команда с:

Код: Выделить всё

beanFactory.getBean(Command.class, inputDto);
При внедрении полей все работает, потому что Spring внедряет только Service через аннотацию @Autowired, а затем я устанавливаю DTO.
Когда я переключаюсь на внедрение конструктора (помечая зависимости как окончательные), Spring больше не может найти соответствующий конструктор, поскольку он пытается автоматически связать оба параметра (включая DTO, который не является bean-компонентом), и это приводит к BeanCreationException.

Код: Выделить всё

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'exampleCommand' defined in file [...\example-project\target\diraliases\OPENSHIFT\classes\com\examplepackage\command\ExampleCommand.class]: Could not resolve matching constructor on bean class [com.examplepackage.command.ExampleCommand] (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities.  You should also check the consistency of arguments when mixing indexed and named arguments, especially in case of bean definition inheritance)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:291)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1395)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1232)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:569)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:529)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:357)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:227)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1613)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1571)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:564)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:393)
at com.examplepackage.controller.ExampleController.exampleApi(ExampleController.java:26)
[...]

Похоже, что Spring не может решить, какой конструктор использовать, или не может разрешить параметры (параметр DTO является динамическим, служба является компонентом Spring).
Ниже приведены фрагменты кода:
Контроллер:

Код: Выделить всё

@RequiredArgsConstructor
@RestController
@RequestMapping(value = "/api", produces = {MediaType.APPLICATION_JSON_VALUE, "application/hal+json"})
public class ExampleController {

private final BeanFactory beanFactory;

@PostMapping(path = "/exampleApi")
public ResponseEntity exampleApi(@RequestBody String stringDTO) throws Exception {

ExampleCommand command = beanFactory.getBean(ExampleCommand.class, new ExampleDto(stringDTO));
String resource = command.execute();

return ok(resource);
}
}
Команда:

Код: Выделить всё

@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class ExampleCommand {
private final ExampleDto exampleDto;
private final ExampleService exampleService;

public ExampleCommand(ExampleDto exampleDto, ExampleService exampleService) {
this.exampleDto = exampleDto;
this.exampleService = exampleService;
}

public String execute() {return exampleService.exampleMethod(exampleDto);}
}
Сервис:

Код: Выделить всё

@Service
public class ExampleService {
public String exampleMethod(ExampleDto exampleDto) {
return String.join(exampleDto.value(), "-joined");
}
}
DTO:

Код: Выделить всё

public record ExampleDto(String value) {}
Чего я ожидаю
Spring должен использовать конструктор, который принимает служебный компонент + DTO, переданный в getBean(...), не требуя @Autowired для SampleService.
Что происходит на самом деле
Spring не может разрешить конструктор и выдает исключение выше.
Вопрос
Что я делаю не так? Как мне правильно структурировать свой конструктор, чтобы Spring мог внедрить служебный компонент и принять DTO (который не является компонентом) в качестве параметра времени выполнения при использовании beanFactory.getBean(Command.class, dto)?

Нужен ли мне @Autowired для конкретного конструктора или мне следует использовать другой шаблон?

Подробнее здесь: https://stackoverflow.com/questions/798 ... beanfactor
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»