Как убрать приведение типа из конструкции фреймворка 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 шт):

Автор решения: Sergey Rebrov

Можно написать таким образом:

IFilesManager filesManager = applicationContext.getBean(IFilesManager.class);

→ Ссылка
Автор решения: RomanMitasov

Но ведь для того, чтобы этот код скомпилировался, нам нужно импортировать явно FilesManager. Получается, мы жестко ссылаемся на этот класс - не вижу, какое преимущество перед тем, что если бы мы написали по-дедовски

Согласно документации Spring использование applicationContext где-либо кроме конфигурационных классов спринга - уже нарушение концепции инверсии контроля.

Лучший вариант - собирать бины в *Configuration классах, а там как раз и надо писать конкретные реализации:

IFilesManager filesManager = new FilesManager();

Это и называется "инверсией контроля", так как объекты, которые используют IFilesManager, не занимаются получением экземпляров этого интерфейса, а этим занимается какая-то третья система/фреймворк/менеджер зависимостей.

Короче, ваши классы в Spring-приложении не должны знать о существовании Spring вообще, а вот он должен знать о них всё.

Лучший способ ответить на вопрос "А правильно ли я делаю" - сначала ответить на вопрос "Сможет ли мой код работать без спринга вообще, ну, например, с другим Dependency Injection фреймворком.

Прошу прощения, что ответ не совсем по теме, но для данного обсуждения следовало это упомянуть

→ Ссылка