2013-08-06 3 views
5

Я использую Spring 3.2 и хотел бы динамически выбирать реализацию сервиса в моем контроллере в зависимости от состояния. Рассмотрим У меня есть интерфейс и две реализации следующим образом:Dyamically выберите реализацию сервиса весной

public interface DevService { 
    public void add(Device device); 
} 

public class DevServiceImpl implements DevService { 
    public void add(Device device) { 
    } 
} 

public class RemoteDevServiceImpl implements DevService { 
    public void add(Device device) { 
    } 
} 

Так что в моем контроллере, в зависимости от того, является ли действие, которое будет выполняться на локальном сайте или удаленном месте, мне нужно либо выполнить его локально или отправить команду на удаленный сайт для ее выполнения. По сути, сайт, на который пользователь нажимает, определяет, какой вызов службы должен вызвать. Может ли кто-нибудь предложить чистый способ добиться этого?

ответ

8

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

interface DevService 
{ 
    void add(Device d); 
    String getName(); 
} 

@Service("devServiceLocal") 
class DevServiceLocalImpl implements DevService 
{ 
    void add(Device d) {...} 
    String getName() {return "local";} 
} 

class Controller 
{ 
    @Autowired 
    Collection<DevService> services; 

    void doSomethingWithService() 
    { 
     // TODO: Check type somehow 
     String servType = "local"; 
     for(DevService s: services) 
     { 
     if(servType.equals(s.getName()) 
     { 
      // Call service methods 
      break; 
     } 
     } 
    } 
} 
0

Вы можете использовать аннотацию @Named и получить фасоль по имени.

Таким образом вы можете определить базовое имя «ServiceName» и добавить суффикс, например «Remote» или «Local», в зависимости от условия, которое вы объяснили. Вы также должны аннотировать бобы (реализации услуг) как

@Named("ServiceNameRemote") и @Named("ServiceNameLocal") соответственно

Наконец на контроллере, вы можете использовать (DevService)BeanFactory.getBean("beanName"), чтобы получить его по динамически генерируемое имя.

0

Это не проверено, но если вы используете Spring-MVC, вы сможете справиться с этим, проверив ваши заголовки в контроллере. Хотя, я не уверен, как ваш код развертывается. Следующий подход имеет несколько падений, но должно работать:

package <PACKAGE NAME>; 

import org.springframework.stereotype.Controller; 
import org.springframework.web.bind.annotation.ModelAttribute; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 

@Controller 
@RequestMapping("/device") 
public class DeviceController { 

    @RequestMapping(headers={"Host=*.local.domain.com"}) 
    public void localDevice(
     @ModelAttribute("device") Device device 
    ) { 
     ... 
    } 

    @RequestMapping(headers={"Host!=*.local.domain.com"}) 
    public void remoteDevice(
     @ModelAttribute("device") Device device 
    ) { 
     ... 
    } 

} 

А именно, он опирается на хост остаются теми же, в то время как вы можете вводить список для ваших заголовков, я не уверен, если вы все еще можете получить карта исключения для удаленного хоста с использованием этого подхода. Кроме того, я думаю, что это имеет большое значение в отношении того, как запрос направляется в класс контроллера.

2

Ваш вопрос подразумевает, что под «динамическим» вы подразумеваете, что вы хотели бы иметь возможность выбирать во время запуска, но вам не нужно менять его в середине. Если это так, я настоятельно рекомендую использовать @Profile. Моя обычная практика, использующая конфигурацию на основе аннотаций, состоит в том, чтобы иметь отдельный класс @Configuration для каждого профиля, который определяет профили @Bean s, которые должны быть доступны там. Даже легко определить только для разработки @Controller с, которые полностью отключены в режиме производства. Определите класс с константами String для каждого профиля, чтобы избежать опечаток.

Смежные вопросы