Как убрать приведение типа из конструкции фреймворка Spring `applicationContext.getBean`?
Типичная для Spring строка кода:
IFilesManager filesManager = (dev.example.FilesManager.FilesManager) applicationContext.getBean("FilesManager");
, где IFilesManager - интерфейс или абстрактный класс.
Вроде бы все эти финты с бинами придуманы для того, чтобы убрать жесткую связь приложения с конкретными реализациями, а в коде ссылаться только на абстракции. Но ведь для того, чтобы этот код скомпилировался, нам нужно импортировать явно FilesManager. Получается, мы жестко ссылаемся на этот класс - не вижу, какое преимущество перед тем, что если бы мы написали по-дедовски:
IFilesManager filesManager = new FilesManager();
Если же мы перепишем так:
IFilesManager filesManager = applicationContext.getBean("FilesManager");
то, поскольку applicationContext.getBean() возвращает Object, код не скомпилируется.
Можно ли переписать этот код так, чтобы ссылаться исключительно на абстракцию IFilesManager, а реализацию FilesManager не импортировать?
Кстати, по слухам, холивар между приверженцами Spring-контекста в xml-файлах и приверженцев аннотаций @Bean кончился в пользу последних. Не умею пока использовать @Bean-аннотации, но ответы с @Bean-аннотацией приветствуются.
Спасибо, что прочитали вопрос.
Ответы (2 шт):
Можно написать таким образом:
IFilesManager filesManager = applicationContext.getBean(IFilesManager.class);
Но ведь для того, чтобы этот код скомпилировался, нам нужно импортировать явно FilesManager. Получается, мы жестко ссылаемся на этот класс - не вижу, какое преимущество перед тем, что если бы мы написали по-дедовски
Согласно документации Spring использование applicationContext где-либо кроме конфигурационных классов спринга - уже нарушение концепции инверсии контроля.
Лучший вариант - собирать бины в *Configuration классах, а там как раз и надо писать конкретные реализации:
IFilesManager filesManager = new FilesManager();
Это и называется "инверсией контроля", так как объекты, которые используют IFilesManager, не занимаются получением экземпляров этого интерфейса, а этим занимается какая-то третья система/фреймворк/менеджер зависимостей.
Короче, ваши классы в Spring-приложении не должны знать о существовании Spring вообще, а вот он должен знать о них всё.
Лучший способ ответить на вопрос "А правильно ли я делаю" - сначала ответить на вопрос "Сможет ли мой код работать без спринга вообще, ну, например, с другим Dependency Injection фреймворком.
Прошу прощения, что ответ не совсем по теме, но для данного обсуждения следовало это упомянуть