Chú thích @Service nên được lưu giữ ở đâu? Giao diện hay thực hiện?


133

Tôi đang phát triển một ứng dụng bằng Spring. Tôi bắt buộc phải sử dụng @Servicechú thích. Tôi có ServiceIServiceImplnhư vậy ServiceImpl implements ServiceI. Tôi bối rối ở đây là tôi nên giữ @Servicechú thích ở đâu.

Tôi nên chú thích giao diện hoặc việc thực hiện với @Service? Sự khác biệt giữa hai phương pháp này là gì?


Đây là câu trả lời của tôi cho một bài viết tương tự: stackoverflow.com/questions/38618995/
trộm

Câu trả lời:


140

Tôi không bao giờ đặt @Component(hoặc @Service, ...) tại một giao diện, vì điều này làm cho giao diện trở nên vô dụng. Hãy để tôi giải thích tại sao.

Yêu cầu 1: Nếu bạn có một giao diện thì bạn muốn sử dụng giao diện đó cho loại điểm tiêm.

Yêu cầu 2: Mục đích của giao diện là xác định hợp đồng có thể được thực hiện bằng một số triển khai. Mặt khác bạn có điểm tiêm ( @Autowired). Chỉ có một giao diện và chỉ có một lớp thực hiện nó, là (IMHO) vô dụng và vi phạm YAGNI .

Thực tế: Khi bạn đặt:

  • @Component(hoặc @Service, ...) tại một giao diện,
  • có nhiều lớp thực hiện nó,
  • ít nhất hai lớp trở thành Đậu mùa xuân và
  • có một điểm tiêm sử dụng giao diện cho kiểu tiêm dựa trên,

sau đó bạn sẽ nhận được và NoUniqueBeanDefinitionException (hoặc bạn có một thiết lập cấu hình rất đặc biệt, với Môi trường, Cấu hình hoặc Vòng loại ...)

Kết luận: Nếu bạn sử dụng @Component(hoặc @Service, ...) tại một giao diện thì bạn phải vi phạm ít nhất một trong hai mục. Do đó, tôi nghĩ rằng nó không hữu ích (ngoại trừ một số tình huống hiếm gặp) để đặt @Componentở cấp độ giao diện.


Các giao diện Kho lưu trữ Spring-Data-JPA là một cái gì đó hoàn toàn khác


3
Những gì bạn viết rất thú vị ... vậy đó là cách đúng đắn? Có phải nó không chú thích giao diện nào không và đưa chú thích Dịch vụ cho các cài đặt? Spring vẫn có khả năng tự động sử dụng loại giao diện? Câu trả lời của bạn cho vấn đề này là gì> stackoverflow.com/questions/12899372/
Kẻ

3
Tôi có một câu hỏi, tại sao chúng ta cần tạo một giao diện cho lớp dịch vụ khi chỉ có một lớp thực hiện nó? Tôi đã thấy nhiều dự án, chúng có lớp trình điều khiển, lớp dịch vụ ** ( servicInterface , serviceInterfaceImpl ) và lớp kho lưu trữ .
Yubaraj

4
@Yubaraj: điểm công bằng, nhưng câu hỏi của bạn là về một chủ đề hoàn toàn khác (đối với câu trả lời của tôi, tôi đã đưa ra giả định: có một giao diện và câu hỏi không phải là về giao diện mà là về nơi đặt chú thích). Đối với câu hỏi của bạn: Hầu như không có lý do để có một giao diện cho một lớp dịch vụ kinh doanh sẽ không bao giờ có hai triển khai. (BTW: Miễn là bạn không xây dựng api cho người khác, bạn luôn có thể cấu trúc lại mã của mình và giới thiệu giao diện sau này khi bạn cần)
Ralph

1
@Yubaraj, các giao diện cho phép tạo các proxy jdk dựa trên giao diện nhẹ cho các bean khi cần. Khi không có giao diện, spring phải thực hiện phân lớp hoặc sửa đổi các bean bằng cglib để tạo proxy. @Transactionallà một trong những ví dụ sử dụng proxy cho bean. AOP là một số khác.
Yoory N.

1
Mặc dù đôi khi bạn sẽ không có nhiều hơn một lớp triển khai, tôi vẫn thích khai báo các phương thức của mình trong một giao diện. Một nhà phát triển đồng nghiệp sẽ thấy dễ dàng hơn để kiểm tra những dịch vụ nào có sẵn chỉ bằng cách xem các tuyên bố và tài liệu mà không phải lo lắng về việc triển khai.
HFSDev

32

Về cơ bản các chú thích như @Service , @Rep repository , @Component , v.v ... tất cả chúng đều phục vụ cùng một mục đích:

tự động phát hiện khi sử dụng cấu hình dựa trên chú thích và quét đường dẫn.

Từ kinh nghiệm của mình, tôi luôn sử dụng @Servicechú thích trên các giao diện hoặc các lớp trừu tượng và chú thích như @Component@Repositoryđể thực hiện chúng. @Componentchú thích Tôi đang sử dụng trên các lớp phục vụ các mục đích cơ bản, đậu mùa xuân đơn giản, không có gì hơn. @Repositorychú thích tôi đang sử dụng trongDAO lớp, ví dụ: nếu tôi phải giao tiếp với cơ sở dữ liệu, có một số giao dịch, v.v.

Vì vậy, tôi sẽ đề nghị chú thích giao diện của bạn với @Servicecác lớp khác và tùy thuộc vào chức năng.


10
Bạn có thể cho biết sự khác biệt giữa các giao diện chú thích và chú thích triển khai không?
TheKojuEffect

27
Từ các tài liệu Spring , "Chú thích này đóng vai trò là một chuyên môn của @Component, cho phép các lớp thực hiện được tự động phát hiện thông qua quét đường dẫn lớp", cho thấy rằng nó dự định sẽ được sử dụng trên lớp triển khai.
Nbrooks

1
@TheKojuEffect, Bài đăng này giải thích chi tiết về sự khác biệt giữa chú thích giao diện so với triển khai - stackoverflow.com/questions/3120143/
Kẻ

@ user3257644 Chỉ cần lưu ý rằng các đề xuất được đưa ra bởi các câu trả lời trong bài đăng đó liên quan đến chú thích '@Transactional', không phải tất cả các chú thích nói chung.
Jonathan

3
Chú thích @service trên các giao diện không có tác dụng, giống như các chú thích khuôn mẫu khác. Tất cả các chú thích khuôn mẫu nên được đặt trên các lớp trừu tượng hoặc cụ thể.
bigfoot

13

Tôi đã sử dụng @Component, @Service, @Controller@Repositorychú thích của chỉ trên lớp thực hiện và không phải trên giao diện. Nhưng @Autowiredchú thích với Giao diện vẫn hoạt động với tôi.


7

Ưu điểm của việc đặt chú thích trên @Service là nó đưa ra gợi ý rằng đó là một dịch vụ. Tôi không biết nếu bất kỳ lớp thực hiện nào theo mặc định sẽ kế thừa chú thích này.

Mặt trái là bạn đang ghép giao diện của mình với một khung cụ thể tức là Spring, bằng cách sử dụng chú thích cụ thể của mùa xuân. Vì các giao diện được cho là tách rời khỏi triển khai, tôi sẽ không đề xuất sử dụng bất kỳ Chú thích cụ thể hoặc phần đối tượng nào trong giao diện của bạn.


1
Tôi nghĩ rằng tất cả chúng ta đã nghe thấy đối số khớp nối mạnh nhiều lần, nhưng hãy nhớ rằng các chú thích có thể xuất hiện mà không cần bình, vì vậy về cơ bản miễn là khớp nối của bạn nằm trên các chú thích thì nó vẫn có thể được tách rời.
Niels Bech Nielsen

1

Một lợi ích của mùa xuân là dễ dàng chuyển đổi triển khai Dịch vụ (hoặc khác). Đối với điều này, bạn cần chú thích trên giao diện và khai báo biến như thế này:

@Autowired
private MyInterface myVariable;

và không :

@Autowired
private MyClassImplementationWhichImplementsMyInterface myVariable;

Giống như trường hợp đầu tiên, bạn có thể kích hoạt triển khai thực hiện từ lúc nó là duy nhất (chỉ có một lớp thực hiện giao diện). Trong trường hợp thứ hai, bạn cần cấu trúc lại tất cả mã của mình (việc triển khai lớp mới có tên khác). Do đó, chú thích cần phải có trên giao diện càng nhiều càng tốt. Hơn nữa, các proxy JDK rất phù hợp cho việc này: chúng được tạo và khởi tạo khi khởi động ứng dụng vì loại thời gian chạy được biết trước, trái với proxy của CGlib.


4
"MyClassImcellenceationWhichImplementsMyInterface" LOL
inafalcao

Bạn không cần chú thích trên giao diện để ví dụ đầu tiên hoạt động. Bạn có thể chú thích với @Servicemột triển khai và tự động giao diện. Spring sẽ kiểm tra bất kỳ đối tượng thực hiện giao diện này.
Marco

1

Tôi sẽ đặt @Servicevào lớp của bạn nhưng đặt tên của giao diện làm tham số cho chú thích, vd

interface ServiceOne {}

@Service("ServiceOne")
class ServiceOneImpl implements ServiceOne{}

Bằng cách đó, bạn nhận được tất cả các lợi ích và vẫn có thể tiêm giao diện nhưng có được lớp

@Autowired 
private ServiceOne serviceOne;

Vì vậy, giao diện của bạn không bị ràng buộc với khung mùa xuân và bạn có thể thay đổi lớp bất cứ lúc nào và không phải cập nhật tất cả các điểm tiêm của bạn.

Vì vậy, nếu tôi muốn thay đổi lớp triển khai, tôi chỉ có thể chú thích lớp mới và xóa khỏi lớp đầu tiên nhưng đó là tất cả những gì bắt buộc phải thay đổi. Nếu bạn tiêm lớp, bạn có thể có rất nhiều công việc khi bạn muốn thay đổi lớp impl.


-1

Nói một cách đơn giản:

@Service là một chú thích khuôn mẫu cho dịch vụ lớp .

@Repository là một chú thích định kiến đối với sự kiên trì lớp.

@Component là một chú thích khuôn mẫu chung được sử dụng để nói với Spring để tạo một thể hiện của đối tượng trong Bối cảnh ứng dụng. Có thể định nghĩa bất kỳ tên nào cho ví dụ, mặc định là tên lớp là trường hợp lạc đà.


3
Ý nghĩa của các chú thích này không được tìm kiếm nhưng ở đâu để đưa chúng vào Giao diện hoặc việc thực hiện.
nanosoft

-3

Có 5 chú thích có thể được sử dụng để làm đậu mùa xuân. Danh sách dưới đây của câu trả lời.

Bạn có thực sự cần một giao diện? Nếu bạn sắp có một triển khai cho mỗi giao diện dịch vụ, chỉ cần tránh nó, chỉ sử dụng lớp. Tất nhiên, nếu bạn không có RMI hoặc khi cần có proxy giao diện.

@ Lưu trữ - sử dụng để tiêm các lớp lớp dao của bạn.

@Service - sử dụng để tiêm các lớp lớp dịch vụ của bạn. Trong lớp dịch vụ, bạn cũng có thể cần sử dụng chú thích @Transactional để quản lý giao dịch db.

@Controll - sử dụng cho các bộ điều khiển lớp frontend của bạn, chẳng hạn như đậu được quản lý JSF tiêm dưới dạng đậu mùa xuân.

@RestControll - sử dụng cho bộ điều khiển nghỉ mùa xuân, điều này sẽ giúp bạn tránh mọi lúc để đặt chú thích @ResponseBody và @RequestBody trong các phương thức nghỉ ngơi của bạn.

@Component - sử dụng nó trong mọi trường hợp khác khi bạn cần Tiêm đậu mùa xuân không phải là bộ điều khiển, dịch vụ hoặc lớp dao


Có, bạn cần một giao diện trên viền của các lớp của bạn (như lớp truy cập dữ liệu và lớp dịch vụ). Chúng cho phép ghép lỏng các mô-đun có chứa các lớp triển khai đó. Không có chúng, các khách hàng của các lớp được đề cập phải biết các loại cụ thể và bạn cần thay đổi chúng khi bạn muốn trang trí BasicDao của mình bằng CachingDao ...
Igand
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.