@Resource vs @Autowired

381

Anotasi, @Resource ( jsr250 ) atau @Autowired (khusus Musim Semi) manakah yang harus saya gunakan dalam DI?

Saya telah berhasil menggunakan keduanya di masa lalu, @Resource(name="blah")dan@Autowired @Qualifier("blah")

Naluri saya adalah untuk tetap dengan @Resourcetag karena sudah diratifikasi oleh orang-orang jsr.
Adakah yang punya pemikiran kuat tentang ini?

mlo55
sumber
FYI - Saya menghapus 'pembaruan', itu seharusnya ditanyakan sebagai pertanyaan terpisah. Sesuai komentar yang ditolak ini, "Pengeditan ini menyimpang dari maksud asli kiriman. Bahkan pengeditan yang harus membuat perubahan drastis harus berusaha untuk menjaga tujuan pemilik kiriman"
mlo55

Jawaban:

195

Di musim semi pra-3.0 tidak masalah yang mana.

Di musim semi 3.0 ada dukungan untuk anotasi standar ( JSR-330 ) @javax.inject.Inject- gunakan, dengan kombinasi @Qualifier. Perhatikan bahwa pegas sekarang juga mendukung @javax.inject.Qualifiermeta-anotasi:

@Qualifier
@Retention(RUNTIME)
public @interface YourQualifier {}

Jadi kamu bisa punya

<bean class="com.pkg.SomeBean">
   <qualifier type="YourQualifier"/>
</bean>

atau

@YourQualifier
@Component
public class SomeBean implements Foo { .. }

Lalu:

@Inject @YourQualifier private Foo foo;

Ini membuat penggunaan nama String menjadi lebih sedikit, yang dapat salah eja dan sulit dipertahankan.


Adapun pertanyaan asli: keduanya, tanpa menentukan atribut apa pun dari penjelasan, lakukan injeksi berdasarkan jenis. Perbedaannya adalah:

  • @Resource memungkinkan Anda menentukan nama kacang yang disuntikkan
  • @Autowired memungkinkan Anda untuk menandainya sebagai tidak wajib.
Bozho
sumber
Ini mungkin terlihat seperti pertanyaan konyol, tetapi ketika Anda menggunakan gaya injeksi ini, apakah Anda memerlukan setter publik untuk fooatau konstruktor SomeBeandengan Fooparam?
Snekse
@Snekse - Mendapat jawaban saya: stackoverflow.com/questions/3536674/…
Snekse
nggak. Anda tidak membutuhkan semua itu. Hanya lapangan. (Musim semi
mengisinya
@ Bozho Jawaban ini sebenarnya tidak menunjukkan perbedaan antara @Resourcedan @Autowired, jawaban sebenarnya adalah yang diposting oleh @Iththyo, saya pikir yang ini harus diperbarui.
Boris Treukhov
1
Iya. Bahkan saya terkadang menjawab pertanyaan dengan memberikan alternatif pendekatan yang lebih baik. Tapi saya memasukkan jawaban untuk pertanyaan asli di bawah ini, untuk kelengkapannya
Bozho
509

Keduanya @Autowired(atau @Inject) dan @Resourcebekerja sama baiknya. Tetapi ada perbedaan konseptual atau perbedaan makna

  • @Resourceberarti beri saya sumber daya yang dikenal dengan nama . Nama diekstraksi dari nama setter atau bidang beranotasi, atau diambil dari nama-Parameter.
  • @Injectatau @Autowiredcoba menyambungkan komponen lain yang sesuai berdasarkan jenis .

Jadi, pada dasarnya ini adalah dua konsep yang sangat berbeda. Sayangnya Implementasi Musim Semi @Resourcememiliki built-in fallback, yang muncul ketika resolusi dengan nama gagal. Dalam hal ini, itu jatuh kembali ke- @Autowiredjenis resolusi menurut-jenis. Meskipun fallback ini mudah digunakan, IMHO itu menyebabkan banyak kebingungan, karena orang tidak mengetahui perbedaan konseptual dan cenderung menggunakan @Resourceautowiring berbasis tipe.

Ichthyo
sumber
81
Ya, inilah jawaban yang seharusnya diterima. Misalnya jika Anda memiliki @Resourcebidang beranotasi, dan nama bidang cocok dengan id kacang dalam wadah, maka Spring akan membuang org.springframework.beans.factory.BeanNotOfRequiredTypeExceptionjika tipenya berbeda - ini karena kacang pertama kali dicocokkan dengan nama dalam @Resourceanotasi, bukan menurut jenis. Tetapi jika nama properti tidak cocok dengan nama kacang, maka Spring akan mengirimkannya berdasarkan jenis.
Boris Treukhov
Anda dapat merujuk posting lain yang memberi tahu perbedaan antara keduanya ketika Anda mencoba menggunakan PETA sederhana. stackoverflow.com/questions/13913752/…
Anver Sadhat
4
+1 untuk benar-benar menjawab pertanyaan daripada hanya merekomendasikan "praktik terbaik" yang sama sekali berbeda seperti jawaban yang diterima. Saya juga menemukan posting blog ini, yang menunjukkan hasil dari beberapa skenario umum dengan ketiga gaya anotasi, membantu: blogs.sourceallies.com/2011/08/...
Jules
1
Untuk pembaca, silakan temukan ringkasan artikel yang ditunjuk oleh @Jules di sini: stackoverflow.com/a/23887596/363573
Stephan
3
Salah satu implikasi dari ini: Ketika Anda ingin menyuntikkan kacang Peta / Daftar, @Autowiretidak bisa dan tidak akan berhasil. Anda harus menggunakannya @Resourcedalam kasus itu.
Ricardo van den Broek
76

Perbedaan utama adalah, @Autowiredadalah anotasi pegas. Sedangkan @Resourceditentukan oleh JSR-250, seperti yang Anda tunjukkan sendiri. Jadi yang terakhir adalah bagian dari Jawa sedangkan yang pertama adalah musim semi khusus.

Karenanya, Anda benar dalam menyarankan itu, dalam arti tertentu. Saya menemukan orang menggunakan @Autowireddengan @Qualifierkarena lebih kuat. Pindah dari beberapa kerangka kerja ke yang lain dianggap sangat tidak mungkin, jika bukan mitos, terutama dalam kasus Musim Semi.

Adeel Ansari
sumber
7
1, karena @Autowireddengan @Qualifierbenar-benar adalah lebih kuat daripada JSR standar @Resourcepenjelasan (memikirkan dependensi opsional misalnya dengan @Autowired(required=false). Anda tidak dapat melakukan itu dengan @Resource)
Stefan Haberl
70

Saya ingin menekankan satu komentar dari @ Jules pada jawaban untuk pertanyaan ini. Komentar tersebut membawa tautan yang bermanfaat: Spring Injection dengan @Resource, @Autowired, dan @Inject . Saya mendorong Anda untuk membacanya seluruhnya, namun berikut ini ringkasan singkat kegunaannya:

Bagaimana penjelasan memilih implementasi yang tepat?

@Autowired dan @Inject

  1. Cocok dengan Jenis
  2. Dibatasi oleh Kualifikasi
  3. Cocok dengan Nama

@Resource

  1. Cocok dengan Nama
  2. Cocok dengan Jenis
  3. Dibatasi oleh Kualifikasi (diabaikan jika kecocokan ditemukan berdasarkan nama)

Anotasi (atau kombinasi) mana yang harus saya gunakan untuk menyuntikkan kacang saya?

  1. Beri nama komponen Anda secara eksplisit [@Component ("beanName")]

  2. Gunakan @Resourcedengan nameatribut [@Resource (name = "beanName")]

Mengapa saya tidak menggunakannya @Qualifier?

Hindari @Qualifieranotasi kecuali Anda ingin membuat daftar kacang yang serupa. Misalnya, Anda mungkin ingin menandai serangkaian aturan dengan @Qualifieranotasi tertentu . Pendekatan ini membuatnya mudah untuk menyuntikkan sekelompok kelas aturan ke dalam daftar yang dapat digunakan untuk memproses data.

Apakah injeksi kacang memperlambat program saya?

Pindai paket spesifik untuk komponen [context:component-scan base-package="com.sourceallies.person"]. Meskipun ini akan menghasilkan lebih banyak component-scankonfigurasi, ini mengurangi kemungkinan Anda akan menambahkan komponen yang tidak perlu ke konteks Musim Semi Anda.


Referensi: Pegas Injeksi dengan @Resource, @Autowired dan @Inject

Stephan
sumber
39

Ini yang saya dapat dari Manual Referensi Spring 3.0.x : -

Tip

Jika Anda bermaksud untuk mengekspresikan injeksi yang digerakkan oleh anotasi berdasarkan nama, jangan gunakan terutama @Autowired, meskipun secara teknis mampu merujuk ke nama bean melalui nilai-nilai @Qualifier. Sebagai gantinya, gunakan anotasi JSR-250 @Resource, yang secara semantik didefinisikan untuk mengidentifikasi komponen target spesifik dengan nama uniknya, dengan tipe yang dinyatakan tidak relevan untuk proses pencocokan.

Sebagai konsekuensi spesifik dari perbedaan semantik ini, kacang yang sendiri didefinisikan sebagai koleksi atau tipe peta tidak dapat disuntikkan melalui @ Autowired, karena pencocokan tipe tidak dapat diterapkan dengan benar kepada mereka. Gunakan @Resource untuk kacang semacam itu, merujuk pada koleksi tertentu atau peta kacang dengan nama unik.

@Autowired berlaku untuk bidang, konstruktor, dan metode multi-argumen, memungkinkan penyempitan hingga anotasi kualifikasi pada tingkat parameter. Sebaliknya, @Resource hanya didukung untuk metode setter bidang dan kacang properti dengan satu argumen. Akibatnya, tetap dengan kualifikasi jika target injeksi Anda adalah konstruktor atau metode multi-argumen.

Kartik
sumber
Untuk versi saat ini, lihat docs.spring.io/spring/docs/current/spring-framework-reference/… (tip diperbarui)
Lu55
28

@Autowired + @Qualifier hanya akan berfungsi dengan spring DI, jika Anda ingin menggunakan beberapa DI lain di masa depan @Resource adalah pilihan yang baik.

Perbedaan lain yang saya temukan sangat signifikan adalah @Qualifier tidak mendukung pengkabelan kacang dinamis, karena @Qualifier tidak mendukung placeholder, sementara @Resource melakukannya dengan sangat baik.

Misalnya: jika Anda memiliki antarmuka dengan banyak implementasi seperti ini

interface parent {

}
@Service("actualService")
class ActualService implements parent{

}
@Service("stubbedService")
class SubbedService implements parent{

}

dengan @Autowired & @Qualifier Anda perlu mengatur implementasi anak tertentu seperti

@Autowired
@Qualifier("actualService") or 
@Qualifier("stubbedService") 
Parent object;

yang tidak menyediakan placeholder sementara dengan @Resource Anda dapat menempatkan placeholder dan menggunakan file properti untuk menyuntikkan implementasi anak seperti

@Resource(name="${service.name}")
Parent object;  

di mana service.name diatur dalam file properti sebagai

#service.name=actualService
 service.name=stubbedService

Semoga itu bisa membantu seseorang :)

Ali
sumber
16

Keduanya sama-sama bagus. Keuntungan menggunakan Sumber Daya adalah di masa depan jika Anda ingin kerangka kerja DI lain selain pegas, perubahan kode Anda akan jauh lebih sederhana. Menggunakan Autowired kode Anda sangat erat dengan mata air DI.

Teja Kantamneni
sumber
17
Tidak akan pernah terjadi. Dan bahkan jika itu terjadi - melakukan pencarian / ganti nama anotasi akan menjadi masalah Anda yang paling kecil.
Daniel Alexiuc
13

Ketika Anda menganalisis secara kritis dari kelas dasar dari dua penjelasan ini. Anda akan menyadari perbedaan berikut.

@Autowiredgunakan AutowiredAnnotationBeanPostProcessor untuk menyuntikkan dependensi.
@Resourcegunakan CommonAnnotationBeanPostProcessoruntuk menyuntikkan dependensi.

Meskipun mereka menggunakan kelas post processor yang berbeda, mereka semua berperilaku hampir identik. Perbedaannya terletak pada jalur eksekusi mereka, yang telah saya soroti di bawah ini.

@Autowired / @Inject

1.Matches menurut Tipe
2.Restitions oleh Kualifier
3.Matches oleh Nama

@Resource

1.Matches by Name
2.Matches by Type
3.Restitions by Qualifiers (diabaikan jika kecocokan ditemukan berdasarkan nama)

Amos Kosgei
sumber
6

Dengan @ResourceAnda dapat melakukan injeksi mandiri kacang, mungkin diperlukan untuk menjalankan semua logika tambahan yang ditambahkan oleh prosesor pos kacang seperti hal-hal yang terkait dengan transaksi atau keamanan.

Dengan Spring 4.3+ @Autowiredjuga mampu melakukan ini.

Bohdan Levchenko
sumber
2

@Resourcesering digunakan oleh objek tingkat tinggi, didefinisikan melalui JNDI. @Autowiredatau @Injectakan digunakan oleh kacang yang lebih umum.

Sejauh yang saya tahu, itu bukan spesifikasi, atau bahkan konvensi. Ini lebih logis cara kode standar akan menggunakan anotasi ini.

Nicolas Zozol
sumber
0

Sebagai catatan di sini: SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContextdan SpringBeanAutowiringSupport.processInjectionBasedOnServletContext JANGAN bekerja dengan @Resource anotasi. Jadi ada perbedaan.

msangel
sumber