@Kaynak vs @Autowired


380

DI'de hangi açıklama, @Resource ( jsr250 ) veya @Autowired (İlkbahara özgü) kullanmalıyım?

Geçmişte başarılı bir şekilde kullandım @Resource(name="blah")ve@Autowired @Qualifier("blah")

İçgüdülerim sopa etmektir @Resourceo jsr insanlar tarafından onaylanmıştır beri etiketi.
Bu konuda güçlü düşünceleri olan var mı?


FYI - 'Güncellemeyi' kaldırdım, ayrı bir soru olarak sorulmalıydı. Bu reddedilen yoruma göre, "Bu düzenleme gönderinin orijinal amacından sapıyor.
Sıkı

Yanıtlar:


194

İlkbahar 3.0 öncesi hangisinin olduğu önemli değil.

İlkbahar 3.0'da standart ( JSR-330 ) ek açıklama için destek var @javax.inject.Inject- bunu bir arada kullanın @Qualifier. Yayın artık @javax.inject.Qualifiermeta ek açıklamayı da desteklediğini unutmayın :

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

Böylece sahip olabilirsiniz

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

veya

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

Ve sonra:

@Inject @YourQualifier private Foo foo;

Bu, yanlış yazılmış ve bakımı zor olan String adlarını daha az kullanır.


Orijinal soruya gelince: her ikisi de, ek açıklamanın özelliklerini belirtmeden, türe göre enjeksiyon yapın. Fark şu:

  • @Resource enjekte edilen fasulyenin adını belirtmenize izin verir
  • @Autowired zorunlu olarak işaretlemenizi sağlar.

Bu aptalca bir soru gibi görünebilir, ancak bu enjeksiyon tarzını kullandığınızda , bir param ile bir kamu kurucuya fooveya SomeBeanbir Fookurucuya ihtiyacınız var mı?
Snekse

@Snekse - Cevabımı aldım: stackoverflow.com/questions/3536674/…
Snekse

Hayır. Bunlardan hiçbirine ihtiyacınız yok. Sadece tarla. (Bahar onu yansıma yoluyla doldurur)
Bozho

@Bozho Bu cevap aslında arasındaki farkı göstermez @Resourceve @Autowiredgerçek cevap @Ichthyo tarafından gönderilen cevaptır, bence bu güncellenmelidir.
Boris Treukhov

1
Evet. Aslında bazen yaklaşıma daha iyi bir alternatif sunarak soruları cevaplıyorum. Ancak aşağıdaki orijinal sorunun cevabını eksiksizlik için
ekledim

509

Hem @Autowired(ya da @Inject) ve @Resourceeşit derecede iyi çalışıyor. Ama kavramsal bir fark ya da anlamında bir fark var

  • @Resourcebana ismiyle bilinen bir kaynak bulmak demek . Ad, ek açıklamalı ayarlayıcı veya alanın adından çıkarılır veya name-Parameter öğesinden alınır.
  • @Injectveya türüne göre uygun başka bir bileşeni@Autowired kablolamaya çalışın .

Yani, temelde bunlar birbirinden oldukça farklı iki kavram. Ne yazık ki, Bahar Uygulamasında, @Resourceçözüm adının başarısız olması durumunda devreye giren yerleşik bir geri dönüş vardır. Bu durumda, @Autowiredtüre göre -kind çözünürlüğe geri döner . Bu geri dönüş uygun olsa da, IMHO çok fazla karışıklığa neden olur, çünkü insanlar kavramsal farkın farkında değildir ve @Resourcetip tabanlı otomatik kablolama için kullanma eğilimindedir .


81
Evet, kabul edilen bir cevap budur. Örneğin @Resource, ek açıklamalı bir alanınız varsa ve alan adı kaptaki bir fasulyenin kimliğiyle eşleşiyorsa, org.springframework.beans.factory.BeanNotOfRequiredTypeExceptiontürleri farklıysa Bahar atar - bunun nedeni, fasulye ilk olarak @Resourceek açıklamada türe göre değil, adla eşleştirilmesidir . Ancak, mülkün adı fasulyenin adıyla eşleşmiyorsa, Bahar onları türe göre düzenler.
Boris Treukhov

Basit bir MAP kullanmaya çalıştığınızda bu ikisi arasındaki farkı söyleyen diğer gönderiye başvurabilirsiniz. stackoverflow.com/questions/13913752/…
Anver Sadhat

4
Kabul edilen yanıtın yaptığı gibi tamamen farklı bir "en iyi uygulama" yı önermek yerine, soruyu gerçekten yanıtladığınız için +1. Ayrıca, üç ek açıklama stilinin de yer aldığı bazı yaygın senaryoların sonuçlarını gösteren bu blog gönderisini de buldum: blogs.sourceallies.com/2011/08/…
Jules

1
Okuyucu için lütfen @Jules tarafından işaret edilen makalenin bir özetini burada bulabilirsiniz: stackoverflow.com/a/23887596/363573
Stephan

3
Bunun bir sonucu: Bir Harita / Liste çekirdeği enjekte etmek istediğinizde @Autowire, çalışamaz ve çalışmaz. Bu @Resourcedurumda kullanmanız gerekecek .
Ricardo van den Broek

76

Birincil fark, @Autowiredbir yaylı nottur. Oysa @Resourcesiz kendinizi işaret ettiğiniz gibi JSR-250 tarafından belirtilir. Bu yüzden ikincisi Java'nın bir parçası iken, birincisi Bahara özgüdür.

Dolayısıyla, bir anlamda bunu önermede haklısınız. İnsanların @Autowiredbirlikte kullandıklarını gördüm @Qualifierçünkü daha güçlü. Bir çerçeveden diğerine geçiş, mit olmasa bile, özellikle Bahar durumunda, pek olası değildir.


7
Çünkü 1, @Autowiredile @Qualifiergerçekten olduğu JSR standart daha güçlü @Resourceaçıklama ile (örneğin isteğe bağlı bağımlılıkları düşünüyorum @Autowired(required=false). Sen ile bunu yapamaz @Resource)
Stefan Haberl

70

Ben itibaren bir yorumunu vurgulamak isteriz @Jules üzerine bu cevap bu soruya. Yorum faydalı bir bağlantı getiriyor: @Resource, @Autowired ve @Inject ile Spring Injection . Tamamen okumanızı tavsiye ederim, ancak burada yararlılığının hızlı bir özeti verilmiştir:

Ek açıklamalar doğru uygulamayı nasıl seçer?

@Autowired ve @Inject

  1. Türe Göre Eşleşmeler
  2. Elemeleri Kısıtlamaları
  3. İsme Göre Eşleşir

@Resource

  1. İsme Göre Eşleşir
  2. Türe Göre Eşleşmeler
  3. Niteleyiciler Tarafından Kısıtlamalar (ada göre eşleşme bulunursa yoksayılır)

Fasulyelerimi enjekte etmek için hangi ek açıklamaları (veya kombinasyonlarını) kullanmalıyım?

  1. Bileşeninizi açıkça adlandırın [@Component ("beanName")]

  2. Kullanım @Resourceile nameöznitelik [@Resource (ad = "beanName")]

Neden kullanmamalıyım @Qualifier?

@QualifierBenzer fasulye listesi oluşturmak istemiyorsanız ek açıklamalardan kaçının . Örneğin, bir kural kümesini belirli bir @Qualifierek açıklama ile işaretlemek isteyebilirsiniz . Bu yaklaşım, bir grup kural sınıfını veri işlemek için kullanılabilecek bir listeye enjekte etmeyi kolaylaştırır.

Fasulye enjeksiyonu programımı yavaşlatır mı?

Bileşenler için belirli paketleri tarayın [context:component-scan base-package="com.sourceallies.person"]. Bu, daha fazla component-scanyapılandırmayla sonuçlanacak olsa da, Spring içeriğinize gereksiz bileşenler ekleme olasılığınızı azaltır.


Referans: @Resource, @Autowired ve @Inject ile Yay Enjeksiyonu


39

Spring 3.0.x Başvuru Kılavuzu'ndan aldığım şey bu : -

İpucu

Ek açıklamaya dayalı enjeksiyonu ada göre ifade etmek istiyorsanız, teknik olarak @Qualifier değerleri aracılığıyla bir fasulye adına atıfta bulunsa bile öncelikle @Autowired kullanmayın. Bunun yerine, belirli bir hedef bileşeni benzersiz adıyla tanımlamak için semantik olarak tanımlanan JSR-250 @Resource ek açıklamasını kullanın ve bildirilen tür eşleşen işlemle ilgisizdir.

Bu anlamsal farkın özel bir sonucu olarak, kendileri bir koleksiyon veya harita türü olarak tanımlanan fasulye, @Autowired aracılığıyla enjekte edilemez, çünkü tür eşleşmesi onlar için uygun şekilde uygulanamaz. Belirli bir koleksiyona veya benzersiz bir adla harita çekirdeğine atıfta bulunarak bu tür fasulye için @Resource'u kullanın.

@Otowired, parametre düzeyinde niteleyici ek açıklamaları daraltmaya izin veren alanlar, yapıcılar ve çoklu bağımsız değişken yöntemleri için geçerlidir. Buna karşılık, @Resource yalnızca tek bir bağımsız değişkeni olan alanlar ve fasulye özelliği ayarlayıcı yöntemleri için desteklenir. Sonuç olarak, enjeksiyon hedefiniz bir kurucu veya çok değişkenli bir yöntemse niteleyicilerle devam edin.


Geçerli sürüm için bkz. Docs.spring.io/spring/docs/current/spring-framework-reference/… (ipucu güncellendi)
Lu55

28

@Autowired + @Qualifier gelecekte başka bir DI kullanmak isterseniz @ bahar DI ile çalışacaktır @Kaynak iyi bir seçenektir.

@Qualifier @Nualifier yer tutucuyu desteklemediğinden @Qualifier dinamik fasulye kablolamayı desteklemediğini fark ettiğim diğer bir fark da @Resource çok iyi yapıyor.

Örneğin: bunun gibi birden fazla uygulamaya sahip bir arayüzünüz varsa

interface parent {

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

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

}

@Autowired & @Qualifier ile aşağıdaki gibi belirli bir çocuk uygulaması ayarlamanız gerekir

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

@Resource ile yer tutucu sunmazken, yer tutucu koyabilir ve aşağıdaki gibi belirli bir çocuk uygulamasını enjekte etmek için özellik dosyasını kullanabilirsiniz.

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

Burada service.name özellik dosyasında

#service.name=actualService
 service.name=stubbedService

Umarım birine yardım eder :)


16

Her ikisi de eşit derecede iyidir. İlkbahar dışında başka bir DI çerçevesi istiyorsanız, Kaynak kullanmanın avantajı gelecekte kod değişiklikleriniz çok daha kolay olacaktır. Autowired kullanarak kodunuz DI yayları ile sıkıca bağlıdır.


17
Asla olmayacak. Ve öyle olsa bile - ek açıklama adlarında bir bul / değiştir işlemi yapmak sorunlarınızın en azı olacaktır.
Daniel Alexiuc

13

Bu iki ek açıklamanın temel sınıflarından eleştirel olarak analiz ettiğinizde, aşağıdaki farkları fark edeceksiniz.

@AutowiredAutowiredAnnotationBeanPostProcessor bağımlılıkları enjekte etmek için kullanır . bağımlılıkları enjekte etmek için
@Resourcekullanır CommonAnnotationBeanPostProcessor.

Farklı post işlemci sınıfları kullanıyor olsalar da, hepsi neredeyse aynı şekilde davranıyor. Farklılıklar, aşağıda vurguladığım yürütme yollarında kritik olarak yatmaktadır.

@Autowired / @Inject

1. Türe Göre
Eşleşmeler 2. Eleme
Bölümlerine Göre Kısıtlamalar 3. Ada Göre Eşleşmeler

@Resource

1. İsme
Göre Eşleşmeler 2. Türüne Göre
Eşleşmeler 3. Elemeleri Göre Kısıtlamalar (eğer isme göre bulunursa yoksayılır)


6

İle @ResourceEğer fasulye kendine enjeksiyon yapabilir, bu işlem veya güvenlik ilişkili şeyler gibi fasulye sonrası işlemciler tarafından eklenen tüm ekstra mantığı çalıştırmak için gerekli olabilir.

Spring 4.3+ @Autowiredile de bunu yapabilir.


2

@Resourcegenellikle JNDI ile tanımlanan üst düzey nesneler tarafından kullanılır. @Autowiredveya @Injectdaha yaygın fasulye tarafından kullanılacaktır.

Bildiğim kadarıyla, bu bir şartname ve hatta bir sözleşme değil. Standart kodun bu ek açıklamaları kullanması mantıklı bir yöntemdir.


0

: Bir burada not olarak SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContextve SpringBeanAutowiringSupport.processInjectionBasedOnServletContext etmez ile çalışmak @Resource açıklama. Yani, fark var.

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.