Как перезаписать сервисные компоненты Spring по имени, используя только аннотации

Учитывая, что у меня есть компонент Spring, настроенный как

@Service("myService")
public class DefaultService extends MyService {
}

и класс, использующий этот компонент

public class Consumer {
    @Autowired
    @Qualifier("myService")
    private MyService service;
    ...
}

Теперь я хочу, чтобы в моем проекте, включающем предыдущие классы, была внедрена Consumer еще одна реализация MyService. Поэтому я хотел бы перезаписать bean-компонент myService

@Service("myService")
public class SpecializedService implements MyService {
}

в результате Consumer теперь содержит экземпляр SpecializedService вместо DefaultService. По определению у меня не может быть двух bean-компонентов с одинаковым именем в контейнере Spring. Как я могу сказать Spring, что определение новой службы должно перезаписать старую? Я не хочу изменять класс Consumer.


person Lars Blumberg    schedule 07.04.2011    source источник


Ответы (4)


Либо определите сервисный компонент явно

<bean id="myService" class="x.y.z.SpecializedService" />

или компонент-сканировать его.

В любом случае, в контексте вашего приложения избегайте явного определения DefaultService и избегайте его сканирования компонентов.

person Community    schedule 07.04.2011
comment
Спасибо, Вилли. Мы остановились на вашем решении, так как решили также по причинам обслуживания (мы говорим о сотнях сервисов) хранить список всех сервисов в одном файле, а именно в конфигурации bean-компонента spring. Определение только идентификатора и имени класса не слишком болезненно, так как использование только аннотаций более заманчиво. - person Lars Blumberg; 07.04.2011

Исключите его из проверки компонентов с помощью фильтра

<component-scan base-package="your-package">
    <exclude-filter type="regex" expression="DefaultService" />
</component-scan>

Не уверен, что есть способ сделать это только с аннотациями (кроме удаления аннотации @Service из DefaultService).

person Wilhelm Kleu    schedule 07.04.2011
comment
Спасибо, Вильгельм, я уверен, что ваше решение сработает. Но тогда мне пришлось бы сканировать свои услуги самостоятельно. Хорошая идея! - person Lars Blumberg; 07.04.2011

Связывание на основе аннотаций происходит до конфигурации на основе XML, это означает, что bean-компоненты, определенные в XML, перезапишут связывание, выполненное с помощью аннотаций. Таким образом, явное определение в XML, как сказал Вилли, сделает работу.

<bean id="myService" class="x.y.z.SpecializedService" />

Spring рекомендует использовать XML для bean-компонентов службы и репозитория и аннотацию для bean-компонентов MVC. Он также рекомендует @Autowired без сканирования компонентов. Но аннотации в целом поощряются, хотя они объединяют код и конфигурацию (вопреки разделению проблем).

Во-вторых, используйте @Qualifiers("id объявленного bean-компонента"), где он передается.

person vimal krishna    schedule 25.12.2014

Я знаю, уже поздно. Все равно публикую.

У вас должны быть разные имена для разных реализаций MyService.

Например

@Service("mySpecializedService")
public class SpecializedService implements MyService {
}

@Service("myService")
public class DefaultService extends MyService {
 }

При их автоматическом подключении (скажем, в контроллере) вы можете использовать @Qualifier для внедрения желаемой реализации, как указано ниже.

Чтобы получить реализацию по умолчанию

@Autowired
@Qualifier("myService")
MyService myService;   

Чтобы получить специализированную реализацию

@Autowired
@Qualifier("mySpecializedService")
MyService myService;
person Gyro    schedule 21.09.2017
comment
Это полностью противоречит тому, о чем просил ОП. - person Himanshu Bhardwaj; 21.09.2017
comment
Я бы определил новый bean-компонент поверх другого в отдельном файле конфигурации (xml или java) и позволил бы ему переопределить предыдущий, или я бы пошел вперед с Spring Profiles или @Conditional. - person Himanshu Bhardwaj; 25.09.2017