Di mana anotasi @Service harus disimpan? Antarmuka atau Implementasi?

133

Saya sedang mengembangkan aplikasi menggunakan Spring. Saya diharuskan menggunakan @Serviceanotasi. Saya punya ServiceIdan ServiceImplitu ServiceImpl implements ServiceI. Saya bingung di sini di mana saya harus menyimpan @Serviceanotasi.

Haruskah saya membubuhi keterangan antarmuka atau implementasinya @Service? Apa perbedaan antara kedua pendekatan ini?

Efek Kojuju
sumber
Ini adalah jawaban saya untuk posting serupa: stackoverflow.com/questions/38618995/…
Agustí Sánchez

Jawaban:

140

Saya tidak pernah menaruh @Component(atau @Service, ...) di antarmuka, karena ini membuat antarmuka tidak berguna. Biarkan saya jelaskan alasannya.

klaim 1: Jika Anda memiliki antarmuka maka Anda ingin menggunakan antarmuka itu untuk jenis titik injeksi.

klaim 2: Tujuan dari antarmuka adalah bahwa ia mendefinisikan kontrak yang dapat diimplementasikan oleh beberapa implementasi. Di sisi lain Anda memiliki titik injeksi ( @Autowired). Memiliki hanya satu antarmuka dan hanya satu kelas yang mengimplementasikannya, adalah (IMHO) tidak berguna, dan melanggar YAGNI .

fakta: Ketika Anda menempatkan:

  • @Component(atau @Service, ...) di antarmuka,
  • memiliki beberapa kelas yang mengimplementasikannya,
  • setidaknya dua kelas menjadi Spring Beans, dan
  • memiliki titik injeksi yang menggunakan antarmuka untuk injeksi berbasis tipe,

maka Anda akan mendapatkan dan NoUniqueBeanDefinitionException (atau Anda memiliki pengaturan konfigurasi yang sangat khusus, dengan Lingkungan, Profil atau Kualifikasi ...)

Kesimpulan: Jika Anda menggunakan @Component(atau @Service, ...) pada sebuah antarmuka maka Anda harus melanggar setidaknya satu dari dua clain. Oleh karena itu saya pikir tidak berguna (kecuali beberapa skenario langka) untuk diletakkan @Componentpada level antarmuka.


Antarmuka Spring-Data-JPA Repository adalah sesuatu yang sangat berbeda

Muntah
sumber
3
Sangat menarik apa yang Anda tulis ... jadi mana jalan yang benar? Apakah itu tidak membubuhi keterangan antarmuka sama sekali dan memberikan Layanan anotasi untuk implementasi? Apakah Spring masih dapat melakukan autowiring menggunakan tipe antarmuka? Apa jawaban Anda untuk ini> stackoverflow.com/questions/12899372/…
corlaez
3
Saya punya pertanyaan, mengapa kita perlu membuat antarmuka untuk lapisan layanan ketika hanya ada satu kelas yang mengimplementasikannya? Saya telah melihat banyak proyek, mereka memiliki lapisan pengontrol, lapisan layanan ** ( servicInterface , serviceInterfaceImpl ), dan lapisan repositori .
Yubaraj
4
@Yubaraj: titik adil, tetapi pertanyaan Anda adalah tentang topik yang cukup lain (untuk jawaban saya, saya mengambil asumsi: bahwa ada antarmuka dan pertanyaannya bukan tentang memiliki antarmuka tetapi tentang di mana harus menempatkan anotasi). Untuk pertanyaan Anda: Hampir tidak ada alasan untuk memiliki antarmuka untuk kelas layanan bisnis yang tidak akan pernah memiliki dua implementasi. (BTW: Selama Anda tidak membuat api untuk orang lain, Anda selalu dapat memperbaiki kode Anda dan memperkenalkan antarmuka nanti ketika Anda membutuhkannya)
Ralph
1
@Yubaraj, antarmuka memungkinkan untuk membuat proksi jdk berbasis antarmuka ringan ke kacang saat dibutuhkan. Ketika tidak ada antarmuka, pegas harus melakukan subkelas atau memodifikasi kacang menggunakan cglib untuk membuat proxy. @Transactionaladalah salah satu contoh di mana proxy untuk kacang digunakan. AOP adalah satu lagi.
Yoory N.
1
Meskipun beberapa kali Anda tidak akan memiliki lebih dari satu kelas implementasi, saya masih lebih suka mendeklarasikan metode saya di antarmuka. Sesama pengembang akan merasa lebih mudah untuk memeriksa layanan apa yang tersedia hanya dengan melihat deklarasi dan dokumentasi tanpa khawatir dengan implementasinya.
HFSDev
32

Pada dasarnya anotasi seperti @Service , @Repository , @Component , dll. Semuanya memiliki tujuan yang sama:

deteksi otomatis saat menggunakan konfigurasi berbasis anotasi dan pemindaian classpath.

Dari pengalaman saya, saya selalu menggunakan @Serviceanotasi pada antarmuka atau kelas abstrak dan anotasi seperti @Componentdan @Repositoryuntuk implementasinya. @Componentanotasi yang saya gunakan pada kelas-kelas yang melayani tujuan dasar, kacang Spring sederhana, tidak lebih. @Repositoryannotation yang saya gunakan dalam DAOlayer, untuk misalnya jika saya harus berkomunikasi dengan database, melakukan beberapa transaksi, dll.

Jadi saya akan menyarankan untuk membubuhi keterangan antarmuka Anda dengan @Servicedan lapisan lainnya tergantung pada fungsi.

Paulius Matulionis
sumber
10
Bisakah Anda tahu apa perbedaan antara antarmuka anotasi dan implementasi anotasi?
TheKojuEffect
27
Dari dokumen Spring , "anotasi ini berfungsi sebagai spesialisasi @Component, memungkinkan kelas implementasi untuk secara otomatis terdeteksi melalui pemindaian classpath," menunjukkan bahwa itu dimaksudkan untuk digunakan pada kelas implementasi.
nbrooks
1
@TheKojuEffect, Posting ini menjelaskan secara terperinci perbedaan antara antarmuka yang beranotasi vs implementasi - stackoverflow.com/questions/3120143/…
Mahesh
@ user3257644 Catat saja bahwa saran yang diberikan oleh jawaban di pos itu berkaitan dengan anotasi '@Transaksional' secara khusus, tidak semua anotasi secara umum.
Jonathan
3
Penjelasan @service pada antarmuka tidak memiliki efek, sama seperti penjelasan stereotip lainnya. Semua anotasi stereotip harus diletakkan di kelas abstrak atau konkret.
bigfoot
13

Saya menggunakan @Component, @Service, @Controllerdan @Repositoryanotasi hanya pada kelas implementasi dan bukan pada antarmuka. Tapi @Autowiredpenjelasan dengan Antarmuka masih bekerja untuk saya.

yalkris
sumber
7

Kelebihan dari menempatkan anotasi pada @Service adalah memberikan petunjuk bahwa itu adalah layanan. Saya tidak tahu apakah ada kelas pelaksana yang secara bawaan akan mewarisi pengumuman ini.

Sisi con adalah bahwa Anda menggabungkan antarmuka Anda dengan kerangka kerja tertentu yaitu Spring, dengan menggunakan anotasi khusus spring. Karena antarmuka seharusnya dipisahkan dari implementasi, saya tidak akan menyarankan menggunakan kerangka kerja Anotasi khusus atau bagian objek dari antarmuka Anda.

Kuldeep Tiwari
sumber
1
Saya pikir kita semua pernah mendengar argumen kopling yang kuat beberapa kali, tetapi ingat bahwa anotasi dapat hadir tanpa toples, jadi pada dasarnya selama kopling Anda ada pada anotasi, masih dapat dipisahkan.
Niels Bech Nielsen
1

Salah satu manfaat pegas adalah dengan mudah mengganti implementasi Layanan (atau lainnya). Untuk ini, Anda perlu membuat catatan pada antarmuka dan mendeklarasikan variabel seperti ini:

@Autowired
private MyInterface myVariable;

dan tidak :

@Autowired
private MyClassImplementationWhichImplementsMyInterface myVariable;

Seperti kasus pertama, Anda dapat mengaktifkan implementasi yang akan disuntikkan dari saat itu unik (hanya satu kelas yang mengimplementasikan antarmuka). Dalam kasus kedua, Anda perlu memperbaiki semua kode Anda (implementasi kelas baru memiliki nama lain). Sebagai konsekuensinya, penjelasan harus ada di antarmuka sebanyak mungkin. Lebih jauh lagi, proksi JDK sangat cocok untuk ini: mereka dibuat dan dipakai pada startup aplikasi karena tipe runtime dikenal sebelumnya, bertentangan dengan proksi CGlib.

François F.
sumber
4
"Penerapan MyClassI yang mengimplementasikanMyInterface" LOL
inafalcao
Anda tidak perlu membuat catatan pada antarmuka untuk contoh pertama agar berfungsi. Anda dapat membuat catatan dengan @Serviceimplementasi dan autowire antarmuka. Spring akan memeriksa objek apa pun yang mengimplementasikan antarmuka ini.
Marco
1

Saya akan memakai @Servicekelas Anda tetapi menempatkan nama antarmuka sebagai parameter untuk contoh anotasi

interface ServiceOne {}

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

Dengan melakukan itu, Anda mendapatkan semua manfaat dan masih bisa menyuntikkan antarmuka tetapi mendapatkan kelas

@Autowired 
private ServiceOne serviceOne;

Jadi antarmuka Anda tidak terikat pada kerangka pegas dan Anda dapat mengubah kelas kapan saja dan tidak harus memperbarui semua titik injeksi Anda.

Jadi jika saya ingin mengubah kelas implementasi saya hanya bisa menjelaskan kelas baru dan menghapus dari yang pertama tapi itu saja yang perlu diubah. Jika Anda menyuntikkan kelas Anda bisa memiliki banyak pekerjaan kapan pun Anda ingin mengubah kelas impl.

pengguna1239403
sumber
-1

Untuk membuatnya lebih sederhana:

@Service adalah anotasi Stereotype untuk lapisan layanan .

@Repository adalah penjelasan Stereotype untuk ketekunan lapisan.

@Component adalah anotasi stereotip generik yang digunakan untuk memberi tahu Spring untuk membuat instance objek dalam Konteks Aplikasi. Dimungkinkan untuk menentukan nama apa pun untuk instance, defaultnya adalah nama kelas sebagai case unta.

HughParker
sumber
3
Makna dari anotasi ini tidak sedang dicari tetapi DI MANA untuk menempatkan mereka pada Interface atau implementasinya.
nanosoft
-3

Ada 5 anotasi yang dapat digunakan untuk membuat kacang panjang. Tuliskan jawaban di bawah ini.

Apakah Anda benar-benar membutuhkan antarmuka? Jika Anda akan memiliki satu implementasi untuk setiap antarmuka layanan, hindari saja, gunakan hanya kelas. Tentu saja, jika Anda tidak memiliki RMI atau ketika antarmuka proxy diperlukan.

@Repository - gunakan untuk menyuntikkan kelas lapisan dao Anda.

@Service - gunakan untuk menyuntikkan kelas lapisan layanan Anda. Di lapisan layanan juga Anda mungkin perlu menggunakan penjelasan @Transaksional untuk manajemen transaksi db.

@Controller - gunakan untuk pengontrol layer frontend Anda, seperti suntikan kacang yang dikelola JSF sebagai kacang pegas.

@RestController - gunakan untuk pengendali spring rest, ini akan membantu Anda menghindari setiap saat untuk memasukkan penjelasan @ResponseBody dan @RequestBody dalam metode istirahat Anda.

@Component - gunakan dalam kasus lain ketika Anda perlu Menyuntikkan spring bean yang bukan pengontrol, layanan, atau kelas dao

Artur Yolchyan
sumber
Ya, Anda memerlukan antarmuka pada batas lapisan Anda (seperti lapisan akses data dan lapisan layanan). Mereka memungkinkan kopling longgar dari modul yang berisi implementasi lapisan itu. Tanpa mereka, klien dari lapisan yang disebutkan harus tahu jenis beton dan Anda perlu mengubahnya ketika Anda, misalnya, ingin menghias BasicDao Anda dengan CachingPOR ...
Igand