@ Hizmet ek açıklaması nerede tutulmalıdır? Arayüz mü, Uygulama mı?


133

Spring kullanarak bir uygulama geliştiriyorum. @ServiceEk açıklamayı kullanmam gerekiyor . Bende var ServiceIve ServiceImplöyle ServiceImpl implements ServiceI. @ServiceEk açıklamayı nerede saklamam gerektiği konusunda kafam karıştı .

Arayüze veya uygulamaya ile açıklama eklemeli miyim @Service? Bu iki yaklaşım arasındaki farklar nelerdir?


Benzer bir
gönderiye

Yanıtlar:


141

Bir arayüze asla @Component(veya @Service, ...) koymadım, çünkü bu arayüzü işe yaramaz hale getiriyor. Nedenini açıklayayım.

İstem 1: Bir arayüzünüz varsa, o arayüzü enjeksiyon noktası türü için kullanmak istersiniz.

İddia 2: Bir arayüzün amacı, çeşitli uygulamalar tarafından uygulanabilen bir sözleşme tanımlamasıdır. Diğer tarafta enjeksiyon noktanız ( @Autowired) var. Sadece bir arayüze ve onu uygulayan tek bir sınıfa sahip olmak (IMHO) faydasızdır ve YAGNI'yi ihlal eder .

olgu: Ne zaman koyarsan:

  • @Component(veya @Service, ...) bir arayüzde,
  • onu uygulayan birden çok sınıfa sahip olmak,
  • en az iki sınıf Bahar Fasulyesi olur ve
  • tip tabanlı enjeksiyon için arayüzü kullanan bir enjeksiyon noktasına sahip olmak,

o zaman alırsınız ve NoUniqueBeanDefinitionException (veya Ortam, Profiller veya Niteleyiciler ile çok özel bir konfigürasyon kurulumunuz olur ...)

Sonuç: Bir arayüzde @Component(veya @Service, ...) kullanırsanız, o zaman iki cümlecikten en az birini ihlal etmeniz gerekir. Bu nedenle @Component, arayüz düzeyine koymanın (bazı nadir senaryolar dışında) yararlı olmadığını düşünüyorum .


Spring-Data-JPA Repository arayüzleri tamamen farklı bir şeydir


3
Yazdıkların çok ilginç ... öyleyse hangisi doğru yol? Arayüze hiç açıklama yazmıyor ve uygulamalara Servis notu vermiyor mu? Spring, arayüz tipini kullanarak hala otomatik kablolama yapabiliyor mu? Buna cevabınız nedir> stackoverflow.com/questions/12899372/…
corlaez

3
Bir sorum var, onu uygulayan tek bir sınıf varken neden servis katmanı için bir arayüz oluşturmamız gerekiyor? Sahip oldukları pek çok projeyi gördük denetleyici katmanı, ** hizmet katmanı ( servicInterface , serviceInterfaceImpl ) ve depo katmanı .
Yubaraj

4
@Yubaraj: doğru nokta, ama sorunuz oldukça farklı bir konu hakkında (cevabım için bir arayüz olduğu varsayımını aldım ve soru arayüze sahip olmakla değil, notun nereye yerleştirileceğiyle ilgili). Sorunuz için: Hiçbir zaman iki uygulamaya sahip olmayacak bir işletme hizmet sınıfı için bir arayüze sahip olmak için neredeyse hiçbir neden yoktur. (BTW: Başka biri için bir API oluşturmadığınız sürece, kodunuzu her zaman yeniden düzenleyebilir ve daha sonra ihtiyacınız olduğunda arayüzü tanıtabilirsiniz)
Ralph

1
@Yubaraj, arayüzler, ihtiyaç duyulduğunda fasulyelere hafif arayüz tabanlı jdk proxy'leri yapmaya izin verir. Arayüz olmadığında, spring bir proxy yapmak için cglib kullanarak alt sınıflandırma yapmak veya fasulyeleri değiştirmek zorundadır. @Transactionalbir fasulyenin vekilinin kullanıldığı örneklerden biridir. AOP başka bir tanesidir.
Yoory N.

1
Bazı zamanlar birden fazla uygulama sınıfınız olmayacak olsa da, yine de yöntemlerimi bir arayüzde bildirmeyi tercih ediyorum. Bir diğer geliştirici, uygulama konusunda endişelenmeden yalnızca bildirimlere ve belgelere bakarak hangi hizmetlerin mevcut olduğunu kontrol etmeyi daha kolay bulacaktır.
HFSDev

32

Temelde @Service , @Repository , @Component , vb. Gibi ek açıklamalar hepsi aynı amaca hizmet eder:

açıklama tabanlı yapılandırma ve sınıf yolu taraması kullanılırken otomatik algılama.

Benim deneyim hep kullanıyorum @Servicearayüzleri ya da benzeri soyut sınıflar ve ek açıklamalar üzerine ek açıklama @Componentve @Repositorybunların uygulanması için. @Componentek açıklama temel amaçlara hizmet eden sınıflarda kullanıyorum, basit Bahar fasulyesi, daha fazlası değil. Katmanda @Repositorykullandığım ek açıklama DAO, örneğin veri tabanıyla iletişim kurmam gerekiyorsa, bazı işlemlerim varsa vb.

Bu nedenle @Service, işlevselliğe bağlı olarak arayüzünüze ve diğer katmanlara açıklama eklemenizi öneririm .


10
Açıklama arayüzleri ile açıklama ekleyen uygulamalar arasındaki farkların ne olduğunu söyleyebilir misiniz?
TheKojuEffect

28
Gönderen Bahar docs , "Bu açıklama uygulama sınıfları, sınıf yolu tarama yoluyla autodetected edilecek sağlayan, @Component bir uzmanlık olarak hizmet veren" o uygulama sınıfına kullanılmak niyetiyle düşündürmektedir.
nbrooks

1
@TheKojuEffect, Bu gönderi, açıklama ekleyen arayüzler ile uygulamalar arasındaki farkı ayrıntılı olarak açıklıyor - stackoverflow.com/questions/3120143/…
Mahesh

@ user3257644 Bu gönderideki yanıtların verdiği önerilerin, genel olarak tüm ek açıklamaları değil, özellikle '@Transactional' ek açıklamasıyla ilgili olduğunu unutmayın.
Jonathan

3
Arabirimlerdeki @service açıklamasının, diğer stereotip açıklamaları gibi hiçbir etkisi yoktur. Tüm stereotip ek açıklamaları ya soyut ya da somut sınıflara konulmalıdır.
koca ayak

13

Ben kullanılan @Component, @Service, @Controllerve @Repositorysadece uygulama sınıfları üzerinde değil, arabirimde ek notların. Ancak @AutowiredArabirimler ile ek açıklama hala benim için çalıştı.


7

@Service'e açıklama koymanın avantajları, bunun bir hizmet olduğuna dair bir ipucu vermesidir. Herhangi bir uygulama sınıfının varsayılan olarak bu açıklamayı miras alacağını bilmiyorum.

Ek olarak, yaya özel açıklama kullanarak arayüzünüzü belirli bir çerçeve, yani Bahar ile birleştiriyorsunuzdur. Arayüzlerin uygulamadan ayrıştırılması gerektiği için, arayüzünüzün herhangi bir çerçeveye özgü Ek Açıklamaları veya nesne parçasını kullanmanızı önermem.


1
Sanırım hepimiz güçlü birleştirme argümanını birçok kez duymuşuzdur, ancak notların kavanoz olmadan da mevcut olabileceğini unutmayın, bu nedenle temelde kuplajınız notlarda olduğu sürece hala ayrılabilir.
Niels Bech Nielsen

1

Yayın bir faydası, Servis (veya diğer) uygulamasını kolayca değiştirmektir. Bunun için arayüzde açıklama eklemeniz ve şu şekilde değişken bildirmeniz gerekir:

@Autowired
private MyInterface myVariable;

ve yok :

@Autowired
private MyClassImplementationWhichImplementsMyInterface myVariable;

İlk durumda olduğu gibi, benzersiz olduğu andan itibaren hangi uygulamanın enjekte edileceğini etkinleştirebilirsiniz (arabirimi yalnızca bir sınıf uygular). İkinci durumda, tüm kodunuzu yeniden düzenlemeniz gerekir (yeni sınıf uygulamasının başka bir adı vardır). Sonuç olarak, ek açıklamanın mümkün olduğunca arayüzde olması gerekir. Ayrıca, JDK vekil sunucuları bunun için çok uygundur: CGlib vekil sunucularının aksine, çalışma zamanı türü önceden bilindiğinden uygulama başlangıcında oluşturulur ve başlatılırlar.


4
"MyClassImplementationWhichImplementsMyInterface" LOL
inafalcao

İlk örneğin çalışması için arayüzde açıklama yapmanız gerekmez. @ServiceBir uygulama ile açıklama ekleyebilir ve arayüzü otomatik olarak kablolayabilirsiniz. Spring, bu arayüzü uygulayan herhangi bir nesneyi kontrol edecektir.
Marco

1

Ben koyardı @Serviceclassınıza ama açıklama ör parametre olarak arayüzün adını koymak

interface ServiceOne {}

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

Bunu yaparak tüm faydaları elde edersiniz ve yine de arayüzü enjekte edebilirsiniz ancak sınıfı elde edersiniz

@Autowired 
private ServiceOne serviceOne;

Böylece arayüzünüz yay çerçevesine bağlı değildir ve sınıfı istediğiniz zaman değiştirebilir ve tüm enjeksiyon noktalarınızı güncellemenize gerek kalmaz.

Bu yüzden, uygulama sınıfını değiştirmek istersem, yeni sınıfa not ekleyebilir ve ilkinden kaldırabilirdim, ancak değiştirilmesi gereken tek şey bu. Sınıfa enjekte ederseniz, impl sınıfını değiştirmek istediğinizde çok işiniz olabilir.


-1

Basitçe söylemek gerekirse:

@Service , hizmet katmanı için bir Stereotype açıklamadır .

@Repository için bir klişe şerhleridir kalıcılık tabakası.

@Component , Spring'e Uygulama Bağlamında nesnenin bir örneğini oluşturmasını söylemek için kullanılan genel bir klişe açıklamadır. Örnek için herhangi bir ad tanımlamak mümkündür, varsayılan, deve durumu olarak sınıf adıdır.


3
Bu ek açıklamaların anlamı aranmaz, ancak Arayüz veya uygulanmasına NEREDE koyulur.
nanosoft

-3

Bahar fasulyesi yapımında kullanılabilecek 5 açıklama vardır. Aşağıdaki cevapların listesi.

Gerçekten bir arayüze ihtiyacınız var mı? Her hizmet arabirimi için bir uygulamaya sahip olacaksanız, bundan kaçının, yalnızca sınıfı kullanın. Elbette, RMI'niz yoksa veya arabirim proxy'si gerektiğinde.

@Repository - dao katman sınıflarınızı enjekte etmek için kullanın.

@Service - hizmet katmanı sınıflarınızı enjekte etmek için kullanın. Hizmet katmanında ayrıca, db işlem yönetimi için @Transactional annotation kullanmanız gerekebilir.

@Controller - Bahar fasulyesi olarak enjekte edilen JSF tarafından yönetilen çekirdekler gibi ön uç katman denetleyicileriniz için kullanın.

@RestController - yay dinlenme denetleyicileri için kullanın, bu, dinlenme yöntemlerinize @ResponseBody ve @RequestBody ek açıklamalarını her defasında eklemekten kaçınmanıza yardımcı olur.

@Component - denetleyici, servis veya dao sınıfı olmayan yaylı fasulyeyi enjekte etmeniz gerektiğinde başka bir durumda kullanın


Evet, katmanlarınızın sınırlarında (veri erişim katmanı ve hizmet katmanı gibi) bir arayüze ihtiyacınız var. Bu katman uygulamalarını içeren modüllerin gevşek bağlanmasını sağlarlar. Onlar olmadan, bahsedilen katmanların müşterileri somut türleri bilmek zorundadır ve siz, örneğin Basic dao'nuzu Önbelleğe Alma Dao ile süslemek istediğinizde bunları değiştirmeniz gerekir ...
Igand
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.