2013-08-06 28 views
5

Tôi đang sử dụng spring 3.2 và muốn tự động chọn triển khai dịch vụ trong bộ điều khiển của tôi tùy thuộc vào điều kiện. Hãy xem xét tôi có một giao diện và hai triển khai như sau:Chọn một cách tự nhiên việc triển khai dịch vụ vào mùa xuân

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) { 
    } 
} 

Vì vậy, trong điều khiển của tôi, tuỳ thuộc vào việc hành động là để được thực thi trên trang web địa phương hoặc trang web từ xa, tôi cần phải hoặc là thực hiện nó tại địa phương hoặc gửi lệnh đến trang từ xa để thực thi nó. Về cơ bản, trang web mà người dùng nhấp vào xác định dịch vụ nào sẽ gọi đến. Ai có thể đề xuất một cách sạch sẽ để đạt được điều này?

Trả lời

8

Giả sử bạn cần cả hai triển khai trong môi trường sản xuất (nếu không - sử dụng hồ sơ Spring để phân tách rõ ràng giữa các môi trường). Cách tiếp cận đơn giản sẽ là:

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

Bạn có thể sử dụng chú thích @Named và nhận bean theo tên.

Bằng cách này, bạn có thể xác định tên cơ sở "ServiceName" và thêm một số hậu tố, như "Từ xa" hoặc "Địa phương" tùy thuộc vào điều kiện bạn đã giải thích. Bạn cũng sẽ cần phải chú thích đậu của bạn (triển khai dịch vụ) như

@Named("ServiceNameRemote")@Named("ServiceNameLocal") tương ứng

Cuối cùng trên bộ điều khiển, bạn có thể sử dụng (DevService)BeanFactory.getBean("beanName") để có được nó bằng tên tự động tạo ra nó.

0

Điều này chưa được kiểm tra, nhưng nếu bạn đang sử dụng Spring-MVC, bạn sẽ có thể xử lý nó bằng cách kiểm tra các tiêu đề của bạn trong bộ điều khiển. Mặc dù, tôi không chắc chắn mã của bạn đang được triển khai như thế nào. Các phương pháp sau đây có một vài downfalls, nhưng nên làm việc:

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 
    ) { 
     ... 
    } 

} 

Cụ thể, nó dựa trên máy chủ của bạn ở cùng, trong khi bạn có thể tiêm một danh sách cho tiêu đề của bạn, tôi không chắc chắn nếu bạn vẫn có thể nhận được bản đồ loại trừ cho máy chủ từ xa bằng cách sử dụng phương pháp đó. Ngoài ra, tôi nghĩ rằng nó quan trọng rất nhiều về cách yêu cầu được định tuyến vào lớp điều khiển.

2

Câu hỏi của bạn ngụ ý rằng theo "động" nghĩa là bạn muốn có thể chọn lúc khởi động, nhưng bạn không cần phải thay đổi nó trong thời gian khởi động. Nếu đúng như vậy, tôi thực sự khuyên bạn nên sử dụng @Profile. Thực hành thông thường của tôi, sử dụng cấu hình dựa trên chú thích, là phải có một lớp riêng biệt @Configuration cho mỗi cấu hình xác định cấu hình cụ thể @Bean mà cần phải có sẵn ở đó. Nó thậm chí còn dễ dàng để xác định chỉ phát triển @Controller s đó là hoàn toàn vô hiệu hóa trong chế độ sản xuất. Xác định một lớp với hằng số String cho mỗi cấu hình để tránh lỗi chính tả.