Нам приходится иметь дело с унаследованным кодом, даже когда мы хотим использовать самые лучшие и новейшие доступные технологии. Представьте, что новый код написан с использованием новейших технологий Spring Framework, а унаследованный код вообще не написан на Spring. Затем использование управляемых bean-компонентов Spring в неуправляемых объектах Spring — один из шаблонов, с которыми нам приходится иметь дело. Унаследованный код содержит неуправляемые объекты Spring, а код, на который мы хотим сослаться, — это управляемый компонент Spring. Как мы решаем эту проблему?
Создать бобов весны
Предположим, у нас есть управляемый Spring Bean под названием TaxService и объект с именем LegacyObject . LegacyObject — это унаследованный код, из которого мы могли бы сделать ссылку на метод LegacyObject в управляемом Spring Bean.
TaxService
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
package com.jdriven;import org.springframework.stereotype.Service;@Servicepublic class TaxServiceImpl implements TaxService { @Override public Double calculateTax(Double price) { return new Double(price * 0.21); }} |
Интерфейс с мостовыми методами обслуживания
Мы определяем интерфейс, который содержит список методов. Каждый из этих методов возвращает управляемый компонент Spring. Мы создаем метод getTaxService для возврата только что созданного TaxService .
SpringContextBridgedServices
|
1
2
3
4
5
6
7
8
|
package com.jdriven;/** * This interface represents a list of Spring Beans (services) which need to be referenced from a non Spring class. */public interface SpringContextBridgedServices { TaxService getTaxService();} |
Реализуйте Spring Context Bridge
Далее мы создаем реализацию для интерфейса SpringContextBridgedServices . Давайте назовем этот класс SpringContextBridge сделаем его Spring Bean и добавим в класс следующую функциональность.
- Этот класс также должен реализовывать интерфейс
ApplicationContextAwareиз Spring. Единственный аргумент в методе, который нам нужно реализовать из интерфейса, — это аргументApplicationContext. Мы храним этот аргумент в статической переменной-члене. - Создайте статический метод для возврата
SpringContextBridgedServicesи дайте этому методу вернутьSpringContextBridgedServicesкоторым управляет Spring. ИспользуйтеapplicationContext.getBean(SpringContextBridgedServices.class)чтобы вернуть его. - Автоматически подключите
TaxServiceи верните его в методе, который нам нужно реализовать из методаSpringContextBridgedServices.
SpringContextBridge
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
package com.jdriven;import org.springframework.beans.BeansException;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Component;/*** Register this SpringContextBridge as a Spring Component.*/@Componentpublic class SpringContextBridge implements SpringContextBridgedServices, ApplicationContextAware { private static ApplicationContext applicationContext; @Autowired private TaxService taxService; //Autowire the TaxService @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } /** * A static method to lookup the SpringContextBridgedServices Bean in * the applicationContext. It is basically an instance of itself, which * was registered by the @Component annotation. * * @return the SpringContextBridgedServices, which exposes all the * Spring services that are bridged from the Spring context. */ public static SpringContextBridgedServices services() { return applicationContext.getBean(SpringContextBridgedServices.class); } @Override public TaxService getTaxService() { return taxService; //Return the Autowired taxService }} |
- Примечание 1: есть возможность вернуть управляемый бин Spring в самом статическом методе. Я предпочитаю этого не делать, поэтому у меня меньше статических методов, и я могу позже смоделировать некоторые службы ссылок.
- Примечание 2: В конце концов вы хотели бы разделить две функции. Один, содержащий
ApplicationContextи возвращающийSpringContextBridgedServices. Другой — самSpringContextBridgedServices. В этой короткой демонстрации я просто поместил их в один и тот же компонент.
Возьми меня на мост
Теперь пришло время позвонить на мост. Это так просто, как показано в коде ниже.
LegacyObject
|
01
02
03
04
05
06
07
08
09
10
11
12
|
package com.jdriven;public class LegacyObject { private Double price; public Double doTheCalculation() { //Get the Service from the Bridge TaxService taxService = SpringContextBridge.services().getTaxService(); return taxService.calculateTax(this.price); }} |
Гибкая, но не ограниченная альтернатива
Это способ, которым список связанных служб ограничен. Только сервисы, упомянутые в интерфейсе SpringContextBridgedServices будут соединены мостом. Если вы хотите более гибкий, но менее контролируемый способ, вы можете переписать SpringContextBridgedServices .
SpringContextBridgedServicesAlternative
|
1
2
3
4
5
6
|
package com.jdriven;public interface SpringContextBridgedServicesAlternative { <T> T getService(Class<T> serviceType);} |
Теперь мы можем получить сервис, вызвав SpringContextBridge.services().getService(TaxService.class) . В этой альтернативе у нас нет контроля над тем, какой управляемый бин Spring может быть соединен.
| Ссылка: | Использование Spring Bean в неуправляемом объекте от нашего партнера по JCG Виллема Чейзу из блога JDriven . |